diff --git a/README.md b/README.md index ee143f22079..b95838e9139 100644 --- a/README.md +++ b/README.md @@ -15,54 +15,237 @@

All-in-one web3 SDK for Browser, Node and Mobile apps

-## Features - -- Support for React & React-Native -- First party support for [Embedded Wallets](https://portal.thirdweb.com/wallets) (social/email login) -- First party support for [Account Abstraction](https://portal.thirdweb.com/wallets/sponsor-gas) -- Instant connection to any chain with RPC Edge integration -- Integrated IPFS upload/download -- UI Components for connection, transactions, nft rendering -- High level contract extensions for interacting with common standards +## πŸ“¦ Packages + +This monorepo contains multiple packages designed to work together to provide a comprehensive web3 development experience. Each package serves a specific purpose and can be used independently or in combination with others. + +### Core Package + +#### [`thirdweb`](./packages/thirdweb/README.md) +The main SDK package providing all-in-one web3 functionality for Browser, Node, and Mobile applications. + +```bash +npm install thirdweb +``` + +**Features:** +- Type-safe contract and wallet APIs +- Embedded wallets with social/email login +- Account abstraction (ERC4337) support +- React hooks and UI components - Automatic ABI resolution +- IPFS upload/download +- Cross-platform support (Web, React Native) + +### Platform Adapters + +#### [`@thirdweb-dev/react-native-adapter`](./packages/react-native-adapter/README.md) +Required polyfills and configuration for running the thirdweb SDK in React Native applications. + +```bash +npm install @thirdweb-dev/react-native-adapter +``` + +**Purpose:** Provides necessary polyfills and setup instructions for React Native compatibility. + +#### [`@thirdweb-dev/wagmi-adapter`](./packages/wagmi-adapter/README.md) +Integration layer for using thirdweb's in-app wallets with wagmi. + +```bash +npm install @thirdweb-dev/wagmi-adapter +``` + +**Purpose:** Enables seamless integration between thirdweb wallets and the wagmi ecosystem. + +### Backend Services + +#### [`@thirdweb-dev/engine`](./packages/engine/README.md) +TypeScript SDK for Engine, thirdweb's backend onchain executor service. + +```bash +npm install @thirdweb-dev/engine +``` + +**Purpose:** Interact with thirdweb Engine for backend transaction execution and blockchain operations. + +#### [`@thirdweb-dev/vault-sdk`](./packages/vault-sdk/README.md) +SDK for interacting with Vault, thirdweb's secure key management service. + +```bash +npm install @thirdweb-dev/vault-sdk +``` + +**Purpose:** Secure key management and wallet operations through thirdweb's Vault service. + +#### [`@thirdweb-dev/nebula`](./packages/nebula/README.md) +TypeScript SDK for Nebula, thirdweb's AI agent service. + +```bash +npm install @thirdweb-dev/nebula +``` + +**Purpose:** Integrate AI-powered blockchain interactions and smart contract operations. + +#### [`@thirdweb-dev/insight`](./packages/insight/README.md) +TypeScript SDK for Insight, thirdweb's analytics and monitoring service. + +```bash +npm install @thirdweb-dev/insight +``` + +**Purpose:** Analytics, monitoring, and insights for your web3 applications and smart contracts. + +#### [`@thirdweb-dev/api`](./packages/api/README.md) +TypeScript SDK for thirdweb's general API services. + +```bash +npm install @thirdweb-dev/api +``` + +**Purpose:** Access thirdweb's general API endpoints for various web3 services and utilities. + +### Utilities + +#### [`@thirdweb-dev/service-utils`](./packages/service-utils/README.md) +Internal utilities and shared functionality for thirdweb services. + +```bash +npm install @thirdweb-dev/service-utils +``` + +**Purpose:** Shared utilities, types, and helper functions used across thirdweb services. + +## πŸš€ Quick Start + +### For Web Applications + +```bash +npm install thirdweb +``` + +```typescript +import { createThirdwebClient } from "thirdweb"; +import { ConnectButton } from "thirdweb/react"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", +}); + +function App() { + return ; +} +``` + +### For React Native Applications + +```bash +npm install thirdweb @thirdweb-dev/react-native-adapter +``` + +```typescript +// Import at the top of your App.tsx +import "@thirdweb-dev/react-native-adapter"; +import { createThirdwebClient } from "thirdweb"; +import { ConnectButton } from "thirdweb/react"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", +}); + +function App() { + return ; +} +``` + +### For Backend Applications + +```bash +npm install thirdweb @thirdweb-dev/engine +``` + +```typescript +import { createThirdwebClient } from "thirdweb"; +import { configure } from "@thirdweb-dev/engine"; + +// Configure Engine client +configure({ + secretKey: "YOUR_SECRET_KEY", +}); + +const client = createThirdwebClient({ + secretKey: "YOUR_SECRET_KEY", +}); +``` + +## πŸ”— Package Dependencies + +```mermaid +graph TD + A[thirdweb] --> B[Core SDK] + C[@thirdweb-dev/react-native-adapter] --> A + D[@thirdweb-dev/wagmi-adapter] --> A + E[@thirdweb-dev/engine] --> F[Engine API] + G[@thirdweb-dev/vault-sdk] --> H[Vault Service] + I[@thirdweb-dev/nebula] --> J[Nebula AI] + K[@thirdweb-dev/insight] --> L[Analytics] + M[@thirdweb-dev/api] --> N[thirdweb API] + O[@thirdweb-dev/service-utils] --> P[Shared Utils] +``` + +## πŸ“š Documentation + +- **Main Documentation**: [https://portal.thirdweb.com/typescript/v5](https://portal.thirdweb.com/typescript/v5) +- **React Documentation**: [https://portal.thirdweb.com/typescript/v5/react](https://portal.thirdweb.com/typescript/v5/react) +- **React Native Guide**: [https://portal.thirdweb.com/react-native](https://portal.thirdweb.com/react-native) +- **Templates**: [https://thirdweb.com/templates](https://thirdweb.com/templates) + +## πŸ›  Development + +### Prerequisites + +- Node.js >= 20 +- pnpm >= 9 + +### Installation + +```bash +pnpm install +``` + +### Building Packages + +```bash +# Build all packages +pnpm build + +# Build specific package +pnpm build --filter=./packages/thirdweb +``` + +### Testing + +```bash +# Run all tests +pnpm test + +# Run tests for specific package +pnpm test --filter=./packages/thirdweb +``` -## Library Comparison - -| | thirdweb | Wagmi + Viem | Ethers@6 | -| ----------------------------------------- | -------- | ------------------ | -------- | -| Type safe contract API | βœ… | βœ… | βœ… | -| Type safe wallet API | βœ… | βœ… | βœ… | -| EVM utils | βœ… | βœ… | βœ… | -| RPC for any EVM | βœ…Β  | ⚠️ public RPC only | ❌ | -| Automatic ABI Resolution | βœ… | ❌ | ❌ | -| IPFS Upload/Download | βœ… | ❌ | ❌ | -| Embedded wallet (email/ social login) | βœ… | ⚠️ via 3rd party | ❌ | -| Account abstraction (ERC4337) support | βœ… | ⚠️ via 3rd party | ❌ | -| Web3 wallet connectors | βœ… | βœ… | ❌ | -| Local wallet creation | βœ… | βœ… | βœ… | -| Auth (SIWE) | βœ… | βœ… | ❌ | -| Extensions functions for common standards | βœ… | βœ… | ❌ | -| React Hooks | βœ… | βœ… | ❌ | -| React UI components | βœ… | ❌ | ❌ | -| React Native Hooks | βœ… | βœ… | ❌ | -| React Native UI Components | βœ… | ❌ | ❌ | - -## Contributing +## 🀝 Contributing We welcome contributions from all developers regardless of experience level. If you are interested in contributing, please read our [Contributing Guide](.github/contributing.md) to learn how the repo works, how to test your changes, and how to submit a pull request. See our [open source page](https://thirdweb.com/open-source) for more information on our open-source bounties and program. -## Additional Resources +## πŸ“„ License -- [Documentation](https://portal.thirdweb.com/typescript/v5) -- [Templates](https://thirdweb.com/templates) -- [YouTube](https://www.youtube.com/c/thirdweb) +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. -## Support +## πŸ†˜ Support -For help or feedback, please [visit our support site](https://thirdweb.com/support) +For help or feedback, please [visit our support site](https://thirdweb.com/support) or join our [Discord community](https://discord.gg/thirdweb). -## Security +## πŸ”’ Security If you believe you have found a security vulnerability in any of our packages, we kindly ask you not to open a public issue; and to disclose this to us by emailing `security@thirdweb.com`. diff --git a/packages/api/README.md b/packages/api/README.md index 81afac66dc1..35be7657dd4 100644 --- a/packages/api/README.md +++ b/packages/api/README.md @@ -1,42 +1,920 @@ -# thirdweb API OpenAPI TypeScript wrapper +# API SDK -This package is a thin OpenAPI wrapper for the thirdweb API +## Description -## Configuration +The **@thirdweb-dev/api** package is a TypeScript SDK that provides access to thirdweb's comprehensive API services. This package serves as a unified interface to interact with various thirdweb backend services, including contract deployment, metadata management, account abstraction, authentication, and other web3 infrastructure services. -```ts +### Key Features + +- **Contract Management**: Deploy, interact with, and manage smart contracts +- **Metadata Services**: Upload and manage NFT metadata and assets +- **Account Abstraction**: Create and manage smart accounts (ERC-4337) +- **Authentication**: Secure authentication and session management +- **Chain Information**: Access blockchain network data and configurations +- **Gas Estimation**: Get accurate gas estimates for transactions +- **Event Indexing**: Query blockchain events and transaction history +- **Type Safety**: Full TypeScript support with auto-generated types +- **Rate Limiting**: Built-in rate limiting and retry mechanisms +- **Error Handling**: Comprehensive error handling and debugging + +## Installation + +```bash +npm install @thirdweb-dev/api +``` + +### Prerequisites + +To use the API SDK, you need: + +1. **thirdweb Account**: A registered thirdweb account +2. **API Key**: Valid API key from the thirdweb dashboard +3. **Project Setup**: Configured project in the thirdweb dashboard + +## Usage + +### Basic Setup + +#### 1. Configure API Client + +```typescript import { configure } from "@thirdweb-dev/api"; -// call this once at the startup of your application +// Configure once at application startup configure({ - secretKey: "", + secretKey: "YOUR_SECRET_KEY", // For server-side usage + baseUrl: "https://api.thirdweb.com", // Optional: custom endpoint + timeout: 30000, // Request timeout in ms }); ``` -## Example Usage +#### 2. Client-Side Configuration -```ts -import { writeContract } from "@thirdweb-dev/api"; +```typescript +import { createAPIClient } from "@thirdweb-dev/api"; -const result = await writeContract({ - headers: { - "x-secret-key": "", +// For client-side applications +const apiClient = createAPIClient({ + clientId: "YOUR_CLIENT_ID", + domain: "your-domain.com", // For CORS and authentication +}); +``` + +### Contract Management + +#### Deploy Contract + +```typescript +import { deployContract } from "@thirdweb-dev/api"; + +const deployment = await deployContract({ + body: { + contractType: "nft-collection", // or "nft-drop", "token", "marketplace", etc. + metadata: { + name: "My NFT Collection", + symbol: "MNC", + description: "A collection of unique digital art pieces", + image: "ipfs://QmYourImageHash", + }, + constructorParams: { + name: "My NFT Collection", + symbol: "MNC", + royaltyRecipient: "0x...", + royaltyBps: 500, // 5% royalty + }, + chainId: 137, // Polygon + deployerAddress: "0x...", + }, +}); + +console.log("Contract deployed:", { + address: deployment.data.contractAddress, + transactionHash: deployment.data.transactionHash, + explorer: deployment.data.explorerUrl, +}); +``` + +#### Get Contract Information + +```typescript +import { getContract } from "@thirdweb-dev/api"; + +const contractInfo = await getContract({ + path: { + chainId: "137", + contractAddress: "0x1234567890123456789012345678901234567890", + }, +}); + +console.log("Contract info:", contractInfo.data); + +// Example response: +// { +// name: "My NFT Collection", +// symbol: "MNC", +// contractType: "ERC721", +// owner: "0x...", +// totalSupply: "100", +// metadata: {...} +// } +``` + +#### List User Contracts + +```typescript +import { getUserContracts } from "@thirdweb-dev/api"; + +const contracts = await getUserContracts({ + query: { + walletAddress: "0x...", + chainId: 137, + contractType: "nft-collection", + limit: 50, + offset: 0, + }, +}); + +console.log("User contracts:", contracts.data.result); +``` + +### Metadata Management + +#### Upload to IPFS + +```typescript +import { uploadToIPFS } from "@thirdweb-dev/api"; + +// Upload single file +const file = new File(["content"], "metadata.json", { type: "application/json" }); +const singleUpload = await uploadToIPFS({ + body: { + file: file, + metadata: { + name: "NFT Metadata", + description: "Metadata for my NFT", + }, + }, +}); + +console.log("IPFS URL:", singleUpload.data.ipfsUrl); + +// Upload multiple files +const files = [ + new File(["{}"], "1.json", { type: "application/json" }), + new File(["{}"], "2.json", { type: "application/json" }), +]; + +const batchUpload = await uploadToIPFS({ + body: { + files: files, + options: { + uploadWithGatewayUrl: true, + uploadWithoutDirectory: false, + }, + }, +}); + +console.log("Batch upload:", batchUpload.data.baseUri); +``` + +#### Generate NFT Metadata + +```typescript +import { generateNFTMetadata } from "@thirdweb-dev/api"; + +const metadata = await generateNFTMetadata({ + body: { + name: "Epic Dragon NFT", + description: "A legendary dragon with fire-breathing abilities", + image: "ipfs://QmYourImageHash", + attributes: [ + { trait_type: "Element", value: "Fire" }, + { trait_type: "Rarity", value: "Legendary" }, + { trait_type: "Power", value: "95" }, + ], + animation_url: "ipfs://QmYourAnimationHash", + external_url: "https://myproject.com/nft/1", + }, +}); + +console.log("Generated metadata:", metadata.data); +``` + +### Account Abstraction (Smart Accounts) + +#### Create Smart Account + +```typescript +import { createSmartAccount } from "@thirdweb-dev/api"; + +const smartAccount = await createSmartAccount({ + body: { + chainId: 137, + adminAddress: "0x...", // EOA that will control the smart account + factoryAddress: "0x...", // Smart account factory address + accountSalt: "unique-salt-string", // For deterministic addresses + gasSponsorship: { + enabled: true, + sponsorAddress: "0x...", + policy: "always", // or "conditional" + }, + }, +}); + +console.log("Smart account created:", { + address: smartAccount.data.accountAddress, + isDeployed: smartAccount.data.isDeployed, +}); +``` + +#### Execute Smart Account Transaction + +```typescript +import { executeSmartAccountTransaction } from "@thirdweb-dev/api"; + +const execution = await executeSmartAccountTransaction({ + body: { + smartAccountAddress: "0x...", + chainId: 137, + transaction: { + to: "0x...", // Target contract + value: "0", + data: "0x...", // Encoded function call + }, + gasSponsorship: true, + adminSignature: "0x...", // Signature from admin EOA + }, +}); + +console.log("Transaction executed:", { + transactionHash: execution.data.transactionHash, + gasUsed: execution.data.gasUsed, + sponsored: execution.data.sponsored, +}); +``` + +### Authentication Services + +#### Generate Auth Token + +```typescript +import { generateAuthToken } from "@thirdweb-dev/api"; + +const authToken = await generateAuthToken({ + body: { + domain: "myapp.com", + address: "0x...", // User's wallet address + chainId: 1, + expirationTime: Date.now() + 24 * 60 * 60 * 1000, // 24 hours + resources: [ + "https://myapp.com/api/user", + "https://myapp.com/api/nfts", + ], }, +}); + +console.log("Auth token:", authToken.data.token); +``` + +#### Verify Authentication + +```typescript +import { verifyAuth } from "@thirdweb-dev/api"; + +const verification = await verifyAuth({ body: { - from: "0x1234567891234567891234567891234567891234", + message: "Sign this message to authenticate", + signature: "0x...", // User's signature + address: "0x...", // User's wallet address + chainId: 1, + }, +}); + +console.log("Auth verified:", verification.data.valid); +``` + +### Chain and Network Information + +#### Get Chain Data + +```typescript +import { getChainData } from "@thirdweb-dev/api"; + +const chainData = await getChainData({ + path: { + chainId: "137", // Polygon + }, +}); + +console.log("Chain data:", chainData.data); + +// Example response: +// { +// chainId: 137, +// name: "Polygon", +// currency: "MATIC", +// rpcUrls: ["https://polygon-rpc.com"], +// blockExplorers: [{ +// name: "PolygonScan", +// url: "https://polygonscan.com" +// }], +// nativeCurrency: { +// name: "MATIC", +// symbol: "MATIC", +// decimals: 18 +// } +// } +``` + +#### Get Supported Chains + +```typescript +import { getSupportedChains } from "@thirdweb-dev/api"; + +const chains = await getSupportedChains({ + query: { + includeTestnets: false, + includeL2s: true, + }, +}); + +console.log("Supported chains:", chains.data.chains); +``` + +### Gas Estimation + +#### Estimate Transaction Gas + +```typescript +import { estimateGas } from "@thirdweb-dev/api"; + +const gasEstimate = await estimateGas({ + body: { + chainId: 1, + from: "0x...", + to: "0x...", + value: "1000000000000000000", // 1 ETH + data: "0x...", // Contract call data + }, +}); + +console.log("Gas estimate:", { + gasLimit: gasEstimate.data.gasLimit, + gasPrice: gasEstimate.data.gasPrice, + estimatedCost: gasEstimate.data.estimatedCost, +}); +``` + +#### Get Current Gas Prices + +```typescript +import { getGasPrices } from "@thirdweb-dev/api"; + +const gasPrices = await getGasPrices({ + path: { chainId: "1", - calls: [ + }, +}); + +console.log("Gas prices:", { + standard: gasPrices.data.standard, + fast: gasPrices.data.fast, + fastest: gasPrices.data.fastest, +}); +``` + +### Event Indexing and Queries + +#### Query Contract Events + +```typescript +import { getContractEvents } from "@thirdweb-dev/api"; + +const events = await getContractEvents({ + path: { + chainId: "137", + contractAddress: "0x...", + }, + query: { + eventName: "Transfer", // Optional: filter by event name + fromBlock: 18000000, + toBlock: "latest", + limit: 100, + offset: 0, + }, +}); + +console.log("Contract events:", events.data.events); +``` + +#### Get Transaction History + +```typescript +import { getTransactionHistory } from "@thirdweb-dev/api"; + +const history = await getTransactionHistory({ + query: { + walletAddress: "0x...", + chainId: 137, + contractAddress: "0x...", // Optional: filter by contract + limit: 50, + offset: 0, + }, +}); + +console.log("Transaction history:", history.data.transactions); +``` + +### Advanced Features + +#### Batch API Requests + +```typescript +import { batchRequests } from "@thirdweb-dev/api"; + +const batchResults = await batchRequests({ + body: { + requests: [ + { + method: "GET", + path: "/contract/137/0x.../metadata", + }, + { + method: "GET", + path: "/contract/137/0x.../events", + query: { limit: 10 }, + }, { - contractAddress: "0x1234567890123456789012345678901234567890", - method: "function transfer(address to, uint256 amount)", - params: [ - "0x1234567890123456789012345678901234567890", - "1000000000000000000", - ], + method: "POST", + path: "/gas/estimate", + body: { + chainId: 137, + to: "0x...", + data: "0x...", + }, }, ], }, }); + +console.log("Batch results:", batchResults.data.results); +``` + +#### Webhook Management + +```typescript +import { createWebhook, listWebhooks } from "@thirdweb-dev/api"; + +// Create webhook +const webhook = await createWebhook({ + body: { + name: "Contract Events Webhook", + url: "https://myapp.com/webhooks/contract-events", + eventTypes: ["contract.deployed", "nft.minted", "transaction.completed"], + filters: { + chainIds: [1, 137], + contractAddresses: ["0x..."], + }, + active: true, + }, +}); + +// List webhooks +const webhooks = await listWebhooks({ + query: { + active: true, + limit: 50, + }, +}); + +console.log("Active webhooks:", webhooks.data.webhooks); +``` + +## Configuration Options + +### Client Configuration + +```typescript +import { configure } from "@thirdweb-dev/api"; + +configure({ + secretKey: "your-secret-key", // Server-side only + clientId: "your-client-id", // Client-side only + baseUrl: "https://api.thirdweb.com", + + // Request configuration + timeout: 30000, // 30 seconds + retries: 3, + retryDelay: 1000, // 1 second + + // Rate limiting + rateLimit: { + requestsPerSecond: 10, + burstLimit: 50, + }, + + // Error handling + errorHandling: { + throwOnError: true, + logErrors: true, + maxRetries: 3, + }, + + // Caching + cache: { + enabled: true, + ttl: 300000, // 5 minutes + maxSize: 1000, // Max cached items + }, +}); +``` + +### Request Configuration + +```typescript +const requestConfig = { + // Headers + headers: { + "Content-Type": "application/json", + "User-Agent": "MyApp/1.0.0", + "X-Client-Version": "5.0.0", + }, + + // Authentication + auth: { + type: "bearer", // or "api-key" + token: "your-token", + }, + + // Pagination + pagination: { + defaultLimit: 50, + maxLimit: 1000, + }, + + // Filtering + filtering: { + caseSensitive: false, + allowRegex: false, + }, +}; +``` + +## API Reference + +### Core Functions + +- `configure(options)` - Configure the API client +- `createAPIClient(options)` - Create client instance for frontend use +- `batchRequests(requests)` - Execute multiple API requests in batch + +### Contract Functions + +- `deployContract(options)` - Deploy new smart contract +- `getContract(chainId, address)` - Get contract information +- `getUserContracts(options)` - List user's deployed contracts +- `updateContract(options)` - Update contract metadata + +### Metadata Functions + +- `uploadToIPFS(options)` - Upload files to IPFS +- `generateNFTMetadata(options)` - Generate NFT metadata +- `getMetadata(uri)` - Retrieve metadata from URI +- `pinToIPFS(hash)` - Pin content to IPFS + +### Account Abstraction Functions + +- `createSmartAccount(options)` - Create new smart account +- `executeSmartAccountTransaction(options)` - Execute transaction via smart account +- `getSmartAccountInfo(address)` - Get smart account information +- `sponsorTransaction(options)` - Sponsor transaction gas fees + +### Authentication Functions + +- `generateAuthToken(options)` - Generate authentication token +- `verifyAuth(options)` - Verify authentication signature +- `refreshToken(token)` - Refresh expired token +- `revokeToken(token)` - Revoke authentication token + +### Chain Functions + +- `getChainData(chainId)` - Get blockchain network information +- `getSupportedChains(options)` - List supported chains +- `getBlockData(chainId, blockNumber)` - Get block information + +### Gas Functions + +- `estimateGas(options)` - Estimate transaction gas cost +- `getGasPrices(chainId)` - Get current gas prices +- `optimizeGas(options)` - Get gas optimization suggestions + +### Event Functions + +- `getContractEvents(options)` - Query contract events +- `getTransactionHistory(options)` - Get wallet transaction history +- `subscribeToEvents(options)` - Subscribe to real-time events + +## Examples + +### Complete Contract Deployment Service + +```typescript +import { + deployContract, + uploadToIPFS, + getContract, + createSmartAccount +} from "@thirdweb-dev/api"; + +class ContractDeploymentService { + constructor(private secretKey: string) { + configure({ secretKey }); + } + + async deployNFTCollection(params: { + name: string; + symbol: string; + description: string; + image: File; + ownerAddress: string; + chainId: number; + royaltyBps: number; + }) { + try { + // Upload image to IPFS + const imageUpload = await uploadToIPFS({ + body: { file: params.image }, + }); + + // Deploy contract + const deployment = await deployContract({ + body: { + contractType: "nft-collection", + metadata: { + name: params.name, + symbol: params.symbol, + description: params.description, + image: imageUpload.data.ipfsUrl, + }, + constructorParams: { + name: params.name, + symbol: params.symbol, + royaltyRecipient: params.ownerAddress, + royaltyBps: params.royaltyBps, + }, + chainId: params.chainId, + deployerAddress: params.ownerAddress, + }, + }); + + // Wait for deployment confirmation + await this.waitForDeployment( + params.chainId, + deployment.data.transactionHash + ); + + // Get deployed contract info + const contractInfo = await getContract({ + path: { + chainId: params.chainId.toString(), + contractAddress: deployment.data.contractAddress, + }, + }); + + return { + success: true, + contract: { + address: deployment.data.contractAddress, + transactionHash: deployment.data.transactionHash, + explorerUrl: deployment.data.explorerUrl, + metadata: contractInfo.data, + }, + }; + } catch (error) { + console.error("Deployment failed:", error); + throw error; + } + } + + async createManagedAccount(adminAddress: string, chainId: number) { + // Create smart account for managed operations + const smartAccount = await createSmartAccount({ + body: { + chainId, + adminAddress, + gasSponsorship: { + enabled: true, + sponsorAddress: adminAddress, + policy: "conditional", + }, + }, + }); + + return smartAccount.data; + } + + private async waitForDeployment(chainId: number, txHash: string) { + // Implementation to wait for transaction confirmation + // This would poll the transaction status until confirmed + let attempts = 0; + const maxAttempts = 30; + + while (attempts < maxAttempts) { + try { + const receipt = await this.getTransactionReceipt(chainId, txHash); + if (receipt.status === "success") { + return receipt; + } + } catch (error) { + // Transaction might not be indexed yet + } + + await new Promise(resolve => setTimeout(resolve, 2000)); + attempts++; + } + + throw new Error("Deployment confirmation timeout"); + } + + private async getTransactionReceipt(chainId: number, txHash: string) { + // Implementation to get transaction receipt + // This would use the transaction history API + return { status: "success" }; // Placeholder + } +} + +// Usage +const deploymentService = new ContractDeploymentService("your-secret-key"); + +const result = await deploymentService.deployNFTCollection({ + name: "My Art Collection", + symbol: "ART", + description: "A curated collection of digital art", + image: imageFile, + ownerAddress: "0x...", + chainId: 137, + royaltyBps: 500, // 5% +}); + +console.log("Deployment result:", result); ``` -This package was autogenerated from the [thirdweb openAPI spec](https://api.thirdweb.com/reference) using [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) +### Multi-Chain Event Monitor + +```typescript +import { + getContractEvents, + createWebhook, + getSupportedChains +} from "@thirdweb-dev/api"; + +class EventMonitor { + private webhooks: Map = new Map(); + + async monitorContract( + contractAddress: string, + eventNames: string[], + chainIds: number[] + ) { + for (const chainId of chainIds) { + // Create webhook for each chain + const webhook = await createWebhook({ + body: { + name: `Contract Events - Chain ${chainId}`, + url: `https://myapp.com/webhooks/events`, + eventTypes: ["contract.event"], + filters: { + chainIds: [chainId], + contractAddresses: [contractAddress], + eventNames, + }, + active: true, + }, + }); + + this.webhooks.set(`${chainId}-${contractAddress}`, webhook.data); + + // Get historical events + const historicalEvents = await getContractEvents({ + path: { + chainId: chainId.toString(), + contractAddress, + }, + query: { + fromBlock: "earliest", + limit: 1000, + }, + }); + + console.log( + `Historical events for chain ${chainId}:`, + historicalEvents.data.events.length + ); + } + } + + async getEventsSummary(contractAddress: string, chainIds: number[]) { + const summaries = await Promise.all( + chainIds.map(async (chainId) => { + const events = await getContractEvents({ + path: { + chainId: chainId.toString(), + contractAddress, + }, + query: { + fromBlock: "earliest", + limit: 10000, + }, + }); + + return { + chainId, + totalEvents: events.data.events.length, + eventTypes: this.aggregateEventTypes(events.data.events), + }; + }) + ); + + return summaries; + } + + private aggregateEventTypes(events: any[]) { + const types = new Map(); + + events.forEach(event => { + const count = types.get(event.eventName) || 0; + types.set(event.eventName, count + 1); + }); + + return Object.fromEntries(types); + } + + async cleanup() { + // Remove all webhooks + for (const [key, webhook] of this.webhooks) { + try { + await this.deleteWebhook(webhook.id); + console.log(`Removed webhook for ${key}`); + } catch (error) { + console.error(`Failed to remove webhook for ${key}:`, error); + } + } + + this.webhooks.clear(); + } + + private async deleteWebhook(webhookId: string) { + // Implementation to delete webhook + // This would use the webhook deletion API + } +} + +// Usage +const monitor = new EventMonitor(); + +await monitor.monitorContract( + "0x1234567890123456789012345678901234567890", + ["Transfer", "Mint", "Burn"], + [1, 137, 42161] // Ethereum, Polygon, Arbitrum +); + +const summary = await monitor.getEventsSummary( + "0x1234567890123456789012345678901234567890", + [1, 137, 42161] +); + +console.log("Events summary:", summary); +``` + +## References + +### Documentation +- [API Documentation](https://portal.thirdweb.com/api) - Complete API guide +- [Authentication Guide](https://portal.thirdweb.com/api/auth) - API authentication methods +- [Rate Limits](https://portal.thirdweb.com/api/rate-limits) - API usage limits and optimization + +### API Endpoints +- [Contract API](https://portal.thirdweb.com/api/contracts) - Contract deployment and management +- [Metadata API](https://portal.thirdweb.com/api/metadata) - IPFS and metadata services +- [Smart Accounts API](https://portal.thirdweb.com/api/smart-accounts) - Account abstraction services +- [Events API](https://portal.thirdweb.com/api/events) - Blockchain event indexing + +### Integration Examples +- [API Examples](https://github.com/thirdweb-example/api-examples) - Example implementations +- [Backend Integration](https://github.com/thirdweb-example/api-backend) - Server-side API usage +- [Frontend Integration](https://github.com/thirdweb-example/api-frontend) - Client-side API usage + +### Advanced Topics +- [Webhooks Guide](https://portal.thirdweb.com/api/webhooks) - Real-time event notifications +- [Batch Processing](https://portal.thirdweb.com/api/batch) - Efficient bulk operations +- [Caching Strategies](https://portal.thirdweb.com/api/caching) - Optimizing API performance + +### OpenAPI Integration +- [OpenAPI Specification](https://api.thirdweb.com/openapi.json) - Complete API specification +- [Postman Collection](https://portal.thirdweb.com/api/postman) - Ready-to-use API collection +- [API Testing](https://portal.thirdweb.com/api/testing) - Testing strategies and tools + +### Community and Support +- [Discord #api](https://discord.gg/thirdweb) - API specific help and discussions +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report API SDK issues +- [API Status](https://status.thirdweb.com/api) - API service status and uptime diff --git a/packages/engine/README.md b/packages/engine/README.md index 922e4cfd851..b8cbae9ff52 100644 --- a/packages/engine/README.md +++ b/packages/engine/README.md @@ -1,44 +1,513 @@ -# Engine OpenAPI TypeScript wrapper +# Engine SDK -This package is a thin OpenAPI wrapper for Engine, our backend onchain executor service. +## Description -## Configuration +The **@thirdweb-dev/engine** package is a TypeScript SDK that provides a type-safe wrapper around thirdweb's Engine API. Engine is a high-performance backend service for executing blockchain transactions at scale, handling wallet management, transaction queuing, and gas optimization. This SDK enables developers to integrate Engine's powerful backend capabilities into their applications with full TypeScript support and automatic OpenAPI-generated client methods. -```ts +### Key Features + +- **Backend Transaction Execution**: Execute blockchain transactions from your backend without private key exposure +- **Wallet Management**: Create and manage wallets securely in Engine's hosted environment +- **Transaction Queuing**: Handle high-volume transaction processing with automatic queuing and retry logic +- **Gas Optimization**: Automatic gas price optimization and transaction acceleration +- **Multi-chain Support**: Execute transactions across all supported EVM-compatible networks +- **Type Safety**: Full TypeScript support with auto-generated types from OpenAPI spec +- **Auto-retry Logic**: Built-in retry mechanisms for failed transactions +- **Webhook Integration**: Real-time transaction status updates via webhooks + +## Installation + +```bash +npm install @thirdweb-dev/engine +``` + +### Prerequisites + +Before using the Engine SDK, you need: + +1. **Engine Instance**: Access to a running thirdweb Engine instance +2. **API Keys**: Valid API keys for authentication +3. **Backend Wallets**: Configured backend wallets in Engine for transaction signing + +## Usage + +### Basic Setup + +#### 1. Configure the Engine Client + +```typescript import { configure } from "@thirdweb-dev/engine"; -// call this once at the startup of your application +// Configure once at application startup configure({ - secretKey: "", + baseUrl: "https://your-engine-instance.com", // Your Engine URL + secretKey: "YOUR_SECRET_KEY", // Your secret key }); ``` -## Example Usage +#### 2. Alternative Configuration with thirdweb Client -```ts +```typescript +import { configureWithClient } from "@thirdweb-dev/engine"; +import { createThirdwebClient } from "thirdweb"; + +const thirdwebClient = createThirdwebClient({ + secretKey: "YOUR_SECRET_KEY", +}); + +configureWithClient(thirdwebClient); +``` + +### Contract Interactions + +#### Writing to Contracts + +```typescript import { writeContract } from "@thirdweb-dev/engine"; const result = await writeContract({ headers: { - "x-vault-access-token": "", + "x-backend-wallet-address": "0x...", // Backend wallet address + "x-account-address": "0x...", // Optional: smart account address + }, + body: { + chain: "ethereum", + contractAddress: "0x1234567890123456789012345678901234567890", + functionName: "transfer", + args: [ + "0x742d35Cc06C94a2E0b2dE76D63CB8d35e3Ae1B1a", // to + "1000000000000000000", // amount (1 ETH in wei) + ], + txOverrides: { + gas: "21000", + gasPrice: "20000000000", // 20 gwei + }, + }, +}); + +console.log("Transaction queued:", result.data.queueId); +``` + +#### Reading from Contracts + +```typescript +import { readContract } from "@thirdweb-dev/engine"; + +const balance = await readContract({ + body: { + chain: "polygon", + contractAddress: "0xA0b86a33E6441e13C7C95C5D6b55b7cE06eB6a9D", // USDC + functionName: "balanceOf", + args: ["0x742d35Cc06C94a2E0b2dE76D63CB8d35e3Ae1B1a"], + }, +}); + +console.log("USDC Balance:", balance.data.result); +``` + +### Wallet Management + +#### Create Backend Wallet + +```typescript +import { createBackendWallet } from "@thirdweb-dev/engine"; + +const wallet = await createBackendWallet({ + body: { + type: "local", // or "aws-kms", "gcp-kms" + label: "My Backend Wallet", + }, +}); + +console.log("Created wallet:", wallet.data.walletAddress); +``` + +#### Import Existing Wallet + +```typescript +import { importBackendWallet } from "@thirdweb-dev/engine"; + +const importedWallet = await importBackendWallet({ + body: { + type: "local", + privateKey: "0x...", // Your private key + label: "Imported Wallet", + }, +}); +``` + +#### List Backend Wallets + +```typescript +import { getBackendWallets } from "@thirdweb-dev/engine"; + +const wallets = await getBackendWallets(); +console.log("Available wallets:", wallets.data.result); +``` + +### Transaction Management + +#### Get Transaction Status + +```typescript +import { getTransaction } from "@thirdweb-dev/engine"; + +const transaction = await getTransaction({ + path: { + queueId: "your-queue-id", + }, +}); + +console.log("Transaction status:", transaction.data.status); +console.log("Transaction hash:", transaction.data.transactionHash); +``` + +#### List All Transactions + +```typescript +import { getTransactions } from "@thirdweb-dev/engine"; + +const transactions = await getTransactions({ + query: { + page: 1, + limit: 50, + status: "completed", // or "queued", "sent", "failed" + }, +}); + +console.log("Transactions:", transactions.data.result); +``` + +#### Cancel Transaction + +```typescript +import { cancelTransaction } from "@thirdweb-dev/engine"; + +await cancelTransaction({ + path: { + queueId: "your-queue-id", + }, +}); +``` + +### Smart Contract Deployment + +#### Deploy Contract + +```typescript +import { deployContract } from "@thirdweb-dev/engine"; + +const deployment = await deployContract({ + headers: { + "x-backend-wallet-address": "0x...", }, body: { - executionOptions: { - from: "0x1234567891234567891234567891234567891234", - chainId: "1", + chain: "polygon", + contractType: "erc721", // or custom contract + contractMetadata: { + name: "My NFT Collection", + symbol: "MNC", + description: "A sample NFT collection", }, - params: [ + constructorParams: [], // Constructor parameters + }, +}); + +console.log("Contract deployed:", deployment.data.contractAddress); +``` + +### Advanced Features + +#### Batch Transactions + +```typescript +import { batchWriteContract } from "@thirdweb-dev/engine"; + +const batchResult = await batchWriteContract({ + headers: { + "x-backend-wallet-address": "0x...", + }, + body: { + chain: "polygon", + transactions: [ + { + contractAddress: "0x...", + functionName: "mint", + args: ["0x...", "1"], + }, { - contractAddress: "0x1234567890123456789012345678901234567890", - method: "function transfer(address to, uint256 amount)", - params: [ - "0x1234567890123456789012345678901234567890", - "1000000000000000000", - ], + contractAddress: "0x...", + functionName: "mint", + args: ["0x...", "2"], }, ], }, }); ``` -This package was autogenerated from the [Engine openAPI spec](https://engine.thirdweb.com/reference) using [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) +#### Smart Account Operations + +```typescript +import { createSmartAccount, executeSmartAccountTransaction } from "@thirdweb-dev/engine"; + +// Create smart account +const smartAccount = await createSmartAccount({ + headers: { + "x-backend-wallet-address": "0x...", // Admin wallet + }, + body: { + chain: "polygon", + adminAddress: "0x...", + factoryAddress: "0x...", // Smart account factory + }, +}); + +// Execute transaction via smart account +const txResult = await executeSmartAccountTransaction({ + headers: { + "x-backend-wallet-address": "0x...", + "x-account-address": smartAccount.data.smartAccountAddress, + }, + body: { + chain: "polygon", + contractAddress: "0x...", + functionName: "mint", + args: ["0x...", "1"], + }, +}); +``` + +### Webhooks Integration + +#### Configure Webhooks + +```typescript +import { createWebhook } from "@thirdweb-dev/engine"; + +const webhook = await createWebhook({ + body: { + url: "https://your-app.com/webhooks/engine", + name: "Transaction Updates", + eventType: "transaction_status_update", + }, +}); +``` + +#### Handle Webhook Events + +```javascript +// Express.js webhook handler example +app.post('/webhooks/engine', (req, res) => { + const { queueId, status, transactionHash, errorMessage } = req.body; + + switch (status) { + case 'completed': + console.log(`Transaction ${queueId} completed: ${transactionHash}`); + // Update your database, notify users, etc. + break; + case 'failed': + console.log(`Transaction ${queueId} failed: ${errorMessage}`); + // Handle failed transaction + break; + case 'queued': + console.log(`Transaction ${queueId} queued`); + break; + } + + res.status(200).send('OK'); +}); +``` + +## Configuration Options + +### Client Configuration + +```typescript +import { configure } from "@thirdweb-dev/engine"; + +configure({ + baseUrl: "https://engine.example.com", + secretKey: "your-secret-key", + timeout: 30000, // Request timeout in ms + retries: 3, // Number of retries for failed requests +}); +``` + +### Request Headers + +Common headers used with Engine requests: + +```typescript +const headers = { + "x-backend-wallet-address": "0x...", // Required: Backend wallet for signing + "x-account-address": "0x...", // Optional: Smart account address + "x-account-factory-address": "0x...", // Optional: Smart account factory + "x-account-salt": "unique-salt", // Optional: Deterministic smart account + "x-idempotency-key": "unique-key", // Optional: Prevent duplicate transactions +}; +``` + +## API Reference + +### Core Functions + +- `configure(options)` - Configure the Engine client +- `writeContract(options)` - Execute write operations on smart contracts +- `readContract(options)` - Read data from smart contracts +- `deployContract(options)` - Deploy new smart contracts +- `getTransaction(options)` - Get transaction status and details + +### Wallet Management + +- `createBackendWallet(options)` - Create new backend wallet +- `importBackendWallet(options)` - Import existing wallet +- `getBackendWallets()` - List all backend wallets +- `getWalletBalance(options)` - Get wallet token balances + +### Transaction Management + +- `getTransactions(options)` - List transactions with filtering +- `cancelTransaction(options)` - Cancel queued transaction +- `retryTransaction(options)` - Retry failed transaction + +### Smart Accounts + +- `createSmartAccount(options)` - Create new smart account +- `getSmartAccounts()` - List smart accounts +- `executeSmartAccountTransaction(options)` - Execute via smart account + +## Examples + +### NFT Minting Service + +```typescript +import { writeContract, getTransaction } from "@thirdweb-dev/engine"; + +class NFTMintingService { + private backendWallet = "0x..."; // Your backend wallet address + private nftContract = "0x..."; // Your NFT contract address + + async mintNFT(recipientAddress: string, tokenId: string) { + try { + // Queue mint transaction + const result = await writeContract({ + headers: { + "x-backend-wallet-address": this.backendWallet, + "x-idempotency-key": `mint-${recipientAddress}-${tokenId}`, + }, + body: { + chain: "polygon", + contractAddress: this.nftContract, + functionName: "mint", + args: [recipientAddress, tokenId], + }, + }); + + const queueId = result.data.queueId; + + // Poll for completion + return await this.waitForCompletion(queueId); + } catch (error) { + console.error("Minting failed:", error); + throw error; + } + } + + private async waitForCompletion(queueId: string) { + let attempts = 0; + const maxAttempts = 30; + + while (attempts < maxAttempts) { + const transaction = await getTransaction({ + path: { queueId }, + }); + + if (transaction.data.status === "completed") { + return { + success: true, + transactionHash: transaction.data.transactionHash, + }; + } + + if (transaction.data.status === "failed") { + throw new Error(transaction.data.errorMessage); + } + + // Wait 2 seconds before next check + await new Promise(resolve => setTimeout(resolve, 2000)); + attempts++; + } + + throw new Error("Transaction timeout"); + } +} + +// Usage +const mintingService = new NFTMintingService(); +const result = await mintingService.mintNFT("0x...", "123"); +``` + +### Multi-Chain Token Transfer + +```typescript +import { writeContract, getBackendWallets } from "@thirdweb-dev/engine"; + +class MultiChainTransferService { + async transferTokensAcrossChains( + fromChain: string, + toChain: string, + tokenAddress: string, + amount: string, + recipient: string + ) { + const wallets = await getBackendWallets(); + const wallet = wallets.data.result[0].walletAddress; + + // Transfer from source chain + const transferResult = await writeContract({ + headers: { + "x-backend-wallet-address": wallet, + }, + body: { + chain: fromChain, + contractAddress: tokenAddress, + functionName: "transfer", + args: [recipient, amount], + }, + }); + + return transferResult.data.queueId; + } +} +``` + +## References + +### Documentation +- [Engine Documentation](https://portal.thirdweb.com/engine) - Complete Engine guide +- [Engine API Reference](https://engine.thirdweb.com/reference) - Full API documentation +- [Engine Setup Guide](https://portal.thirdweb.com/engine/get-started) - Getting started with Engine + +### Advanced Features +- [Webhooks Guide](https://portal.thirdweb.com/engine/features/webhooks) - Setting up webhooks +- [Smart Accounts](https://portal.thirdweb.com/engine/features/smart-accounts) - Account abstraction with Engine +- [Gas Optimization](https://portal.thirdweb.com/engine/features/gas-optimization) - Gas price management + +### Infrastructure +- [Self-Hosting Engine](https://portal.thirdweb.com/engine/self-host) - Deploy your own Engine instance +- [Cloud Engine](https://portal.thirdweb.com/engine/cloud) - Managed Engine service +- [Security Best Practices](https://portal.thirdweb.com/engine/security) - Securing your Engine deployment + +### Examples and Templates +- [Engine Examples](https://github.com/thirdweb-example/engine-examples) - Example implementations +- [Backend Integration](https://github.com/thirdweb-example/engine-backend) - Backend service examples +- [Webhook Handlers](https://github.com/thirdweb-example/engine-webhooks) - Webhook implementation examples + +### OpenAPI Integration +- [OpenAPI Specification](https://engine.thirdweb.com/json) - Raw OpenAPI spec +- [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) - Code generation tool used + +### Community and Support +- [Discord #engine](https://discord.gg/thirdweb) - Engine specific help +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report Engine SDK issues +- [Engine Status](https://status.thirdweb.com/) - Service status and uptime diff --git a/packages/insight/README.md b/packages/insight/README.md index d584ba2d258..dc7d13e485e 100644 --- a/packages/insight/README.md +++ b/packages/insight/README.md @@ -1,29 +1,919 @@ -# Insight OpenAPI TypeScript Wrapper +# Insight SDK -This package is a thin openAPI wrapper for insight, our in-house indexer. +## Description -## Configuration +The **@thirdweb-dev/insight** package is a TypeScript SDK for interacting with thirdweb's Insight service, a comprehensive analytics and monitoring platform for web3 applications. Insight provides real-time metrics, transaction tracking, user behavior analysis, and performance monitoring to help developers understand and optimize their decentralized applications. -```ts +### Key Features + +- **Real-time Analytics**: Live dashboards and metrics for your web3 applications +- **Transaction Monitoring**: Track and analyze all blockchain transactions +- **User Behavior Analytics**: Understand user interactions and usage patterns +- **Performance Metrics**: Monitor application performance and response times +- **Custom Events Tracking**: Track application-specific events and conversions +- **Revenue Analytics**: Monitor revenue streams and financial metrics +- **Smart Contract Analytics**: Deep insights into smart contract usage and performance +- **Multi-chain Support**: Analytics across all supported blockchain networks +- **Alerting System**: Real-time alerts for critical metrics and events +- **Data Export**: Export analytics data for further analysis + +## Installation + +```bash +npm install @thirdweb-dev/insight +``` + +### Prerequisites + +To use the Insight SDK, you need: + +1. **Insight Service Access**: Access to thirdweb's Insight analytics platform +2. **API Credentials**: Valid secret key or authentication token +3. **Project Configuration**: Configured project with tracking enabled + +## Usage + +### Basic Setup + +#### 1. Configure Insight Client + +```typescript import { configure } from "@thirdweb-dev/insight"; -// call this once at the startup of your application +// Configure once at application startup configure({ - clientId: "", + secretKey: "YOUR_SECRET_KEY", + projectId: "your-project-id", + baseUrl: "https://insight-api.thirdweb.com", // Optional: custom endpoint +}); +``` + +#### 2. Alternative Configuration with thirdweb Client + +```typescript +import { configureWithClient } from "@thirdweb-dev/insight"; +import { createThirdwebClient } from "thirdweb"; + +const thirdwebClient = createThirdwebClient({ + secretKey: "YOUR_SECRET_KEY", +}); + +configureWithClient(thirdwebClient); +``` + +### Analytics Tracking + +#### Track Custom Events + +```typescript +import { trackEvent } from "@thirdweb-dev/insight"; + +// Track user interactions +await trackEvent({ + eventName: "nft_minted", + properties: { + contractAddress: "0x1234567890123456789012345678901234567890", + tokenId: "123", + price: "0.1", + currency: "ETH", + userId: "user123", + walletAddress: "0x...", + }, + timestamp: Date.now(), +}); + +// Track conversions +await trackEvent({ + eventName: "purchase_completed", + properties: { + orderId: "order_456", + amount: "50.00", + currency: "USDC", + paymentMethod: "wallet", + items: [ + { id: "nft_123", name: "Cool NFT", price: "50.00" } + ], + }, +}); +``` + +#### Track Page Views + +```typescript +import { trackPageView } from "@thirdweb-dev/insight"; + +await trackPageView({ + page: "/marketplace", + title: "NFT Marketplace", + userId: "user123", + walletAddress: "0x...", + properties: { + category: "marketplace", + featured: true, + collectionCount: 25, + }, +}); +``` + +#### Track User Sessions + +```typescript +import { startSession, endSession } from "@thirdweb-dev/insight"; + +// Start tracking user session +const sessionId = await startSession({ + userId: "user123", + walletAddress: "0x...", + userAgent: navigator.userAgent, + referrer: document.referrer, + properties: { + platform: "web", + version: "1.0.0", + }, +}); + +// End session (call when user leaves or after timeout) +await endSession({ + sessionId, + duration: 1800000, // 30 minutes in ms + eventsCount: 15, + properties: { + exitPage: "/profile", + bounceRate: false, + }, +}); +``` + +### Transaction Analytics + +#### Track Transactions + +```typescript +import { trackTransaction } from "@thirdweb-dev/insight"; + +await trackTransaction({ + transactionHash: "0xabc123...", + chainId: 1, + fromAddress: "0x...", + toAddress: "0x...", + value: "1000000000000000000", // 1 ETH in wei + gasUsed: "21000", + gasPrice: "20000000000", // 20 gwei + status: "success", // or "failed", "pending" + blockNumber: 18500000, + timestamp: Date.now(), + contractAddress: "0x...", // if contract interaction + functionName: "transfer", // if contract call + eventType: "nft_purchase", + userId: "user123", +}); +``` + +#### Track Contract Interactions + +```typescript +import { trackContractInteraction } from "@thirdweb-dev/insight"; + +await trackContractInteraction({ + contractAddress: "0x...", + functionName: "mint", + parameters: { + to: "0x...", + amount: "5", + tokenId: "123", + }, + transactionHash: "0x...", + gasUsed: "85000", + status: "success", + userId: "user123", + eventProperties: { + mintType: "public", + mintPrice: "0.05", + }, +}); +``` + +### Data Retrieval and Analytics + +#### Get Analytics Overview + +```typescript +import { getAnalyticsOverview } from "@thirdweb-dev/insight"; + +const overview = await getAnalyticsOverview({ + projectId: "your-project-id", + timeRange: { + start: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago + end: Date.now(), + }, + metrics: [ + "users", + "sessions", + "transactions", + "revenue", + "gas_used" + ], +}); + +console.log("Analytics overview:", overview.data); + +// Example response: +// { +// totalUsers: 1250, +// activeUsers: 89, +// totalSessions: 2100, +// totalTransactions: 850, +// totalRevenue: "12.5", // ETH +// totalGasUsed: "2500000", +// conversionRate: 0.12 +// } +``` + +#### Get User Analytics + +```typescript +import { getUserAnalytics } from "@thirdweb-dev/insight"; + +const userAnalytics = await getUserAnalytics({ + projectId: "your-project-id", + timeRange: { + start: Date.now() - 7 * 24 * 60 * 60 * 1000, // 7 days + end: Date.now(), + }, + segmentation: { + newUsers: true, + returningUsers: true, + walletType: ["metamask", "coinbase", "walletconnect"], + }, +}); + +console.log("User analytics:", userAnalytics.data); +``` + +#### Get Transaction Analytics + +```typescript +import { getTransactionAnalytics } from "@thirdweb-dev/insight"; + +const txAnalytics = await getTransactionAnalytics({ + projectId: "your-project-id", + timeRange: { + start: Date.now() - 24 * 60 * 60 * 1000, // 24 hours + end: Date.now(), + }, + filters: { + chainIds: [1, 137, 42161], // Ethereum, Polygon, Arbitrum + contractAddresses: ["0x..."], + status: ["success"], + minValue: "0.01", // Minimum 0.01 ETH + }, + groupBy: "hour", +}); + +console.log("Transaction analytics:", txAnalytics.data); +``` + +### Real-time Monitoring + +#### Get Live Metrics + +```typescript +import { getLiveMetrics } from "@thirdweb-dev/insight"; + +const liveMetrics = await getLiveMetrics({ + projectId: "your-project-id", + metrics: [ + "active_users_now", + "transactions_per_minute", + "revenue_per_hour", + "gas_price_avg", + ], +}); + +console.log("Live metrics:", liveMetrics.data); + +// Example response: +// { +// activeUsersNow: 23, +// transactionsPerMinute: 2.5, +// revenuePerHour: "0.8", // ETH +// gasPriceAvg: "25000000000" // 25 gwei +// } +``` + +#### Set Up Real-time Alerts + +```typescript +import { createAlert } from "@thirdweb-dev/insight"; + +const alert = await createAlert({ + name: "High Gas Usage Alert", + description: "Alert when gas usage exceeds threshold", + conditions: { + metric: "gas_used_per_transaction", + operator: "greater_than", + threshold: 500000, + timeWindow: "5m", // 5 minutes + }, + notifications: [ + { + type: "email", + recipients: ["dev@company.com"], + }, + { + type: "webhook", + url: "https://api.company.com/alerts", + headers: { + "Authorization": "Bearer token123", + }, + }, + { + type: "slack", + channel: "#dev-alerts", + webhook: "https://hooks.slack.com/...", + }, + ], + enabled: true, +}); + +console.log("Alert created:", alert.data.alertId); +``` + +### Custom Dashboards + +#### Create Custom Dashboard + +```typescript +import { createDashboard } from "@thirdweb-dev/insight"; + +const dashboard = await createDashboard({ + name: "NFT Marketplace Dashboard", + description: "Key metrics for NFT marketplace performance", + widgets: [ + { + type: "metric", + title: "Total Sales", + metric: "revenue", + timeRange: "30d", + visualization: "number", + }, + { + type: "chart", + title: "Daily Active Users", + metric: "active_users", + timeRange: "30d", + visualization: "line_chart", + groupBy: "day", + }, + { + type: "table", + title: "Top Selling NFTs", + query: { + event: "nft_sold", + groupBy: "token_id", + orderBy: "count", + limit: 10, + }, + }, + ], + layout: { + columns: 3, + rows: 2, + }, + isPublic: false, +}); +``` + +#### Get Dashboard Data + +```typescript +import { getDashboardData } from "@thirdweb-dev/insight"; + +const dashboardData = await getDashboardData({ + dashboardId: "dashboard-123", + timeRange: { + start: Date.now() - 7 * 24 * 60 * 60 * 1000, + end: Date.now(), + }, + refreshCache: true, +}); + +console.log("Dashboard data:", dashboardData.data); +``` + +### Advanced Analytics + +#### Funnel Analysis + +```typescript +import { createFunnel } from "@thirdweb-dev/insight"; + +const funnel = await createFunnel({ + name: "NFT Purchase Funnel", + steps: [ + { + name: "Visited Marketplace", + event: "page_view", + filters: { page: "/marketplace" }, + }, + { + name: "Viewed NFT", + event: "nft_viewed", + }, + { + name: "Added to Cart", + event: "add_to_cart", + }, + { + name: "Initiated Purchase", + event: "purchase_initiated", + }, + { + name: "Completed Purchase", + event: "purchase_completed", + }, + ], + timeWindow: "1d", // Users must complete funnel within 1 day +}); + +// Get funnel results +const funnelResults = await getFunnelAnalysis({ + funnelId: funnel.data.funnelId, + timeRange: { + start: Date.now() - 30 * 24 * 60 * 60 * 1000, + end: Date.now(), + }, +}); +``` + +#### Cohort Analysis + +```typescript +import { createCohortAnalysis } from "@thirdweb-dev/insight"; + +const cohortAnalysis = await createCohortAnalysis({ + name: "User Retention Cohorts", + cohortDefinition: { + type: "first_transaction", + timeGranularity: "week", + }, + retentionDefinition: { + event: "transaction", + timeGranularity: "week", + periods: 12, // Track for 12 weeks + }, + timeRange: { + start: Date.now() - 90 * 24 * 60 * 60 * 1000, // 90 days + end: Date.now(), + }, +}); +``` + +### Data Export and Integration + +#### Export Analytics Data + +```typescript +import { exportData } from "@thirdweb-dev/insight"; + +const exportJob = await exportData({ + format: "csv", // or "json", "parquet" + data: { + events: { + eventNames: ["nft_minted", "nft_sold"], + timeRange: { + start: Date.now() - 30 * 24 * 60 * 60 * 1000, + end: Date.now(), + }, + }, + users: { + includeProperties: true, + activeOnly: false, + }, + transactions: { + chainIds: [1, 137], + includeContractData: true, + }, + }, + delivery: { + method: "email", + recipients: ["data@company.com"], + }, +}); + +console.log("Export job created:", exportJob.data.jobId); +``` + +#### Integration with External Tools + +```typescript +import { createIntegration } from "@thirdweb-dev/insight"; + +// Google Analytics integration +const gaIntegration = await createIntegration({ + type: "google_analytics", + name: "GA4 Integration", + configuration: { + measurementId: "G-XXXXXXXXXX", + apiSecret: "your-api-secret", + mappings: { + "nft_minted": "purchase", + "nft_sold": "conversion", + }, + }, + enabled: true, +}); + +// Mixpanel integration +const mixpanelIntegration = await createIntegration({ + type: "mixpanel", + name: "Mixpanel Analytics", + configuration: { + projectToken: "your-project-token", + apiSecret: "your-api-secret", + syncEvents: ["all"], + syncUsers: true, + }, + enabled: true, }); ``` -## Example Usage +## Configuration Options -```ts -import { getV1Events } from "@thirdweb-dev/insight"; +### Client Configuration + +```typescript +import { configure } from "@thirdweb-dev/insight"; -const events = await getV1Events({ - query: { - chain: [1, 137], - filter_address: "0x1234567890123456789012345678901234567890", +configure({ + secretKey: "your-secret-key", + projectId: "your-project-id", + baseUrl: "https://insight-api.thirdweb.com", + + // Optional configuration + timeout: 30000, // Request timeout in ms + retries: 3, // Number of retries for failed requests + batchSize: 100, // Events per batch + flushInterval: 5000, // Auto-flush interval in ms + + // Data collection settings + sampling: { + enabled: false, // Disable sampling for complete data + rate: 0.1, // Sample 10% of events (if enabled) + }, + + // Privacy settings + privacy: { + anonymizeIPs: true, + respectDoNotTrack: true, + cookieConsent: true, + }, + + // Error handling + errorHandling: { + silentErrors: false, + logErrors: true, + maxRetries: 3, }, }); ``` -This package was autogenerated from the [Insight openAPI spec](https://insight-api.thirdweb.com/reference) using [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) +### Tracking Configuration + +```typescript +const trackingConfig = { + // Automatic tracking + autoTrack: { + pageViews: true, + clicks: true, + formSubmissions: false, + scrollDepth: true, + timeOnPage: true, + }, + + // Custom properties to include with all events + globalProperties: { + appVersion: "1.0.0", + environment: "production", + userId: () => getCurrentUserId(), + sessionId: () => getSessionId(), + }, + + // Event filtering + filters: { + excludeEvents: ["debug_event"], + includeOnlyEvents: [], // Empty means include all + excludeBots: true, + excludeLocalhost: true, + }, +}; +``` + +## API Reference + +### Core Functions + +- `configure(options)` - Configure the Insight client +- `configureWithClient(client)` - Configure with thirdweb client +- `trackEvent(event)` - Track custom events +- `trackPageView(pageView)` - Track page views +- `trackTransaction(transaction)` - Track blockchain transactions + +### Analytics Functions + +- `getAnalyticsOverview(options)` - Get high-level analytics overview +- `getUserAnalytics(options)` - Get user behavior analytics +- `getTransactionAnalytics(options)` - Get transaction analytics +- `getRevenueAnalytics(options)` - Get revenue and financial metrics + +### Real-time Functions + +- `getLiveMetrics(options)` - Get real-time metrics +- `createAlert(alert)` - Create monitoring alerts +- `subscribeToMetrics(callback)` - Subscribe to real-time updates + +### Dashboard Functions + +- `createDashboard(dashboard)` - Create custom dashboard +- `getDashboardData(options)` - Get dashboard data +- `updateDashboard(dashboardId, updates)` - Update dashboard configuration + +### Advanced Analytics + +- `createFunnel(funnel)` - Create conversion funnel +- `getFunnelAnalysis(options)` - Get funnel analysis results +- `createCohortAnalysis(cohort)` - Create cohort analysis +- `exportData(options)` - Export analytics data + +## Examples + +### Complete Analytics Integration + +```typescript +import { + configure, + trackEvent, + trackPageView, + getAnalyticsOverview, + createAlert +} from "@thirdweb-dev/insight"; + +class AnalyticsService { + constructor(secretKey: string, projectId: string) { + configure({ + secretKey, + projectId, + batchSize: 50, + flushInterval: 3000, + }); + } + + // Track NFT marketplace events + async trackNFTEvent(eventType: string, data: any) { + await trackEvent({ + eventName: eventType, + properties: { + ...data, + timestamp: Date.now(), + source: "marketplace", + }, + }); + } + + // Track user journey + async trackUserJourney(userId: string, walletAddress: string) { + // Track page views + await trackPageView({ + page: window.location.pathname, + title: document.title, + userId, + walletAddress, + properties: { + referrer: document.referrer, + userAgent: navigator.userAgent, + }, + }); + + // Set up conversion tracking + await this.setupConversionTracking(userId); + } + + // Get comprehensive analytics + async getMarketplaceAnalytics(timeRange: any) { + const overview = await getAnalyticsOverview({ + projectId: this.projectId, + timeRange, + metrics: [ + "users", + "sessions", + "transactions", + "revenue", + "conversion_rate" + ], + }); + + return { + overview: overview.data, + insights: this.generateInsights(overview.data), + }; + } + + // Set up monitoring + async setupMonitoring() { + // High gas usage alert + await createAlert({ + name: "High Gas Alert", + conditions: { + metric: "avg_gas_used", + operator: "greater_than", + threshold: 300000, + timeWindow: "10m", + }, + notifications: [{ + type: "email", + recipients: ["ops@company.com"], + }], + }); + + // Low conversion rate alert + await createAlert({ + name: "Low Conversion Alert", + conditions: { + metric: "conversion_rate", + operator: "less_than", + threshold: 0.05, // 5% + timeWindow: "1h", + }, + notifications: [{ + type: "slack", + webhook: "https://hooks.slack.com/...", + }], + }); + } + + private async setupConversionTracking(userId: string) { + // Track key conversion events + const conversionEvents = [ + "nft_viewed", + "add_to_cart", + "purchase_initiated", + "purchase_completed" + ]; + + // Set up event listeners for conversion tracking + conversionEvents.forEach(event => { + document.addEventListener(event, (e: any) => { + this.trackNFTEvent(event, { + userId, + ...e.detail, + }); + }); + }); + } + + private generateInsights(data: any) { + const insights = []; + + if (data.conversionRate < 0.05) { + insights.push("Conversion rate is below 5% - consider optimizing the purchase flow"); + } + + if (data.totalGasUsed > data.totalTransactions * 200000) { + insights.push("Average gas usage is high - consider gas optimization"); + } + + return insights; + } +} + +// Usage +const analytics = new AnalyticsService("your-secret-key", "your-project-id"); + +// Track NFT mint +await analytics.trackNFTEvent("nft_minted", { + contractAddress: "0x...", + tokenId: "123", + price: "0.1", + currency: "ETH", + userId: "user123", +}); + +// Get analytics +const marketplaceData = await analytics.getMarketplaceAnalytics({ + start: Date.now() - 30 * 24 * 60 * 60 * 1000, + end: Date.now(), +}); +``` + +### Real-time Dashboard + +```typescript +import { + getLiveMetrics, + createDashboard, + subscribeToMetrics +} from "@thirdweb-dev/insight"; + +class RealTimeDashboard { + private metrics: any = {}; + private subscribers: any[] = []; + + async initialize() { + // Create dashboard + const dashboard = await createDashboard({ + name: "Live NFT Marketplace", + widgets: [ + { + type: "metric", + title: "Active Users", + metric: "active_users_now", + visualization: "number", + }, + { + type: "chart", + title: "Transactions/Min", + metric: "transactions_per_minute", + visualization: "gauge", + }, + ], + }); + + // Subscribe to real-time updates + subscribeToMetrics((data) => { + this.updateMetrics(data); + this.notifySubscribers(data); + }); + + // Start periodic updates + this.startPeriodicUpdates(); + } + + private async startPeriodicUpdates() { + setInterval(async () => { + const liveMetrics = await getLiveMetrics({ + projectId: "your-project-id", + metrics: [ + "active_users_now", + "transactions_per_minute", + "revenue_per_hour", + ], + }); + + this.updateMetrics(liveMetrics.data); + }, 30000); // Update every 30 seconds + } + + private updateMetrics(data: any) { + this.metrics = { ...this.metrics, ...data }; + } + + private notifySubscribers(data: any) { + this.subscribers.forEach(callback => callback(data)); + } + + subscribe(callback: (data: any) => void) { + this.subscribers.push(callback); + } + + getCurrentMetrics() { + return this.metrics; + } +} +``` + +## References + +### Documentation +- [Insight Documentation](https://portal.thirdweb.com/insight) - Complete Insight guide +- [Analytics Setup Guide](https://portal.thirdweb.com/insight/setup) - Getting started with analytics +- [Custom Events Guide](https://portal.thirdweb.com/insight/events) - Tracking custom events + +### Analytics Features +- [Real-time Monitoring](https://portal.thirdweb.com/insight/real-time) - Live metrics and alerts +- [Custom Dashboards](https://portal.thirdweb.com/insight/dashboards) - Building custom dashboards +- [Data Export](https://portal.thirdweb.com/insight/export) - Exporting analytics data + +### Integration Examples +- [Insight Examples](https://github.com/thirdweb-example/insight-examples) - Example implementations +- [E-commerce Analytics](https://github.com/thirdweb-example/insight-ecommerce) - E-commerce tracking +- [DeFi Analytics](https://github.com/thirdweb-example/insight-defi) - DeFi protocol analytics + +### Advanced Topics +- [Funnel Analysis](https://portal.thirdweb.com/insight/funnels) - Conversion funnel tracking +- [Cohort Analysis](https://portal.thirdweb.com/insight/cohorts) - User retention analysis +- [A/B Testing](https://portal.thirdweb.com/insight/ab-testing) - Experiment tracking + +### API References +- [Insight API Reference](https://insight-api.thirdweb.com/docs) - Complete API documentation +- [Event Schema](https://portal.thirdweb.com/insight/event-schema) - Event data structure +- [Rate Limits](https://portal.thirdweb.com/insight/rate-limits) - Usage limits and quotas + +### Privacy and Compliance +- [Privacy Guide](https://portal.thirdweb.com/insight/privacy) - Privacy-compliant analytics +- [GDPR Compliance](https://portal.thirdweb.com/insight/gdpr) - GDPR compliance features +- [Data Retention](https://portal.thirdweb.com/insight/retention) - Data retention policies + +### Community and Support +- [Discord #insight](https://discord.gg/thirdweb) - Insight specific help and discussions +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report Insight SDK issues +- [Feature Requests](https://feedback.thirdweb.com/insight) - Request new analytics features diff --git a/packages/nebula/README.md b/packages/nebula/README.md index 46d461c6376..1b0fc419ba0 100644 --- a/packages/nebula/README.md +++ b/packages/nebula/README.md @@ -1,46 +1,746 @@ -# Nebula OpenAPI TypeScript wrapper +# Nebula SDK -This package is a thin OpenAPI wrapper for Nebula, our AI agent service. +## Description -## Configuration +The **@thirdweb-dev/nebula** package is a TypeScript SDK for interacting with Nebula, thirdweb's AI agent service for web3 applications. Nebula provides intelligent automation, natural language processing, and AI-powered decision making for blockchain operations, smart contract interactions, and decentralized application management. -```ts +### Key Features + +- **AI-Powered Smart Contract Analysis**: Automatically analyze and understand smart contract functionality +- **Natural Language Processing**: Convert human language to blockchain operations +- **Intelligent Transaction Optimization**: AI-driven gas optimization and transaction routing +- **Automated Risk Assessment**: AI-based security analysis and risk scoring +- **Multi-Agent Orchestration**: Coordinate multiple AI agents for complex workflows +- **Learning and Adaptation**: Continuously improve through interaction and feedback +- **Integration Ready**: Easy integration with existing thirdweb SDK workflows +- **Type Safety**: Full TypeScript support with auto-generated types + +## Installation + +```bash +npm install @thirdweb-dev/nebula +``` + +### Prerequisites + +To use the Nebula SDK, you need: + +1. **Nebula Service Access**: Access to a thirdweb Nebula instance +2. **API Credentials**: Valid secret key or JWT token +3. **thirdweb Client**: Integration with thirdweb's core SDK + +## Usage + +### Basic Setup + +#### 1. Configure Nebula Client + +```typescript import { configure } from "@thirdweb-dev/nebula"; -// call this once at the startup of your application +// Configure once at application startup configure({ - secretKey: "", + secretKey: "YOUR_SECRET_KEY", + baseUrl: "https://nebula-api.thirdweb.com", // Optional: custom endpoint }); ``` -You can also configure the client with a Thirdweb client instance: +#### 2. Alternative Configuration with thirdweb Client -```ts +```typescript import { configureWithClient } from "@thirdweb-dev/nebula"; -import { twClient } from "./thirdwebClient"; +import { createThirdwebClient } from "thirdweb"; + +const thirdwebClient = createThirdwebClient({ + secretKey: "YOUR_SECRET_KEY", +}); -// call this once at the startup of your application -configureWithClient(twClient); +configureWithClient(thirdwebClient); ``` -## Example Usage +#### 3. Client-Side Configuration -```ts +```typescript +import { getNebulaClient } from "@thirdweb-dev/nebula"; + +// For client applications (e.g., NextJS frontend) +const nebulaClient = getNebulaClient("your-auth-token"); +``` + +### AI Models and Agents + +#### List Available Models + +```typescript import { getModels } from "@thirdweb-dev/nebula"; const models = await getModels(); +console.log("Available AI models:", models.data); + +// Example response: +// { +// models: [ +// { +// id: "nebula-contract-analyzer-v1", +// name: "Contract Analyzer", +// description: "Analyzes smart contracts for functionality and security", +// capabilities: ["analysis", "security", "optimization"] +// }, +// { +// id: "nebula-transaction-optimizer-v1", +// name: "Transaction Optimizer", +// description: "Optimizes transaction parameters for cost and speed", +// capabilities: ["optimization", "gas-estimation"] +// } +// ] +// } ``` -You can also use this package on a client application (eg. NextJS) by retrieving the Nebula API client first. +#### Get Available Agents -```ts -import { getNebulaClient, getAgents } from "@thirdweb-dev/nebula"; +```typescript +import { getAgents } from "@thirdweb-dev/nebula"; -// retrieve the Nebula auth token -const nebulaClient = getNebulaClient(authToken); +// Server-side usage +const agents = await getAgents(); -// pass the client inside the methods +// Client-side usage const agentsResult = await getAgents({ client: nebulaClient }); + +console.log("Available agents:", agentsResult.data); +``` + +### Smart Contract Analysis + +#### Analyze Contract Functionality + +```typescript +import { analyzeContract } from "@thirdweb-dev/nebula"; + +const analysis = await analyzeContract({ + body: { + contractAddress: "0x1234567890123456789012345678901234567890", + chainId: 1, // Ethereum mainnet + analysisType: "comprehensive", // or "security", "gas", "functionality" + includeSourceCode: true, + }, +}); + +console.log("Contract analysis:", analysis.data); + +// Example response: +// { +// contractType: "ERC721", +// functions: [ +// { +// name: "mint", +// type: "payable", +// description: "Mints new NFT tokens to specified address", +// riskLevel: "low", +// gasEstimate: "85000" +// } +// ], +// securityScore: 85, +// recommendations: [ +// "Consider implementing access controls for mint function", +// "Add reentrancy guards for external calls" +// ] +// } +``` + +#### Get Security Assessment + +```typescript +import { assessContractSecurity } from "@thirdweb-dev/nebula"; + +const securityAssessment = await assessContractSecurity({ + body: { + contractAddress: "0x...", + chainId: 1, + includeVulnerabilities: true, + checkCompliance: ["erc721", "eip165"], + }, +}); + +console.log("Security assessment:", securityAssessment.data); +``` + +### Natural Language Processing + +#### Convert Natural Language to Blockchain Operations + +```typescript +import { parseIntent } from "@thirdweb-dev/nebula"; + +const intent = await parseIntent({ + body: { + query: "Send 0.5 ETH to alice.eth and mint an NFT for bob.eth", + context: { + userAddress: "0x...", + availableContracts: ["0x..."], // User's deployed contracts + chainId: 1, + }, + }, +}); + +console.log("Parsed intent:", intent.data); + +// Example response: +// { +// operations: [ +// { +// type: "transfer", +// to: "0x...", // alice.eth resolved address +// amount: "500000000000000000", // 0.5 ETH in wei +// confidence: 0.95 +// }, +// { +// type: "contract_call", +// contractAddress: "0x...", +// functionName: "mint", +// parameters: ["0x..."], // bob.eth resolved address +// confidence: 0.88 +// } +// ], +// estimatedGas: "150000", +// totalCost: "0.003 ETH" +// } +``` + +#### Generate Smart Contract Code + +```typescript +import { generateContract } from "@thirdweb-dev/nebula"; + +const generatedContract = await generateContract({ + body: { + description: "Create an ERC721 NFT contract with marketplace functionality and royalties", + features: [ + "mintable", + "burnable", + "royalties", + "marketplace-integration" + ], + standards: ["erc721", "erc2981"], // Royalty standard + accessControl: "ownable", + }, +}); + +console.log("Generated contract:", generatedContract.data.sourceCode); +``` + +### Transaction Optimization + +#### Optimize Transaction Parameters + +```typescript +import { optimizeTransaction } from "@thirdweb-dev/nebula"; + +const optimization = await optimizeTransaction({ + body: { + transaction: { + to: "0x...", + data: "0x...", // Contract call data + value: "0", + }, + chainId: 1, + priority: "cost", // or "speed", "balanced" + userPreferences: { + maxGasPrice: "50000000000", // 50 gwei + maxWaitTime: 300, // 5 minutes + }, + }, +}); + +console.log("Optimized transaction:", optimization.data); + +// Example response: +// { +// optimizedParams: { +// gasLimit: "85000", +// gasPrice: "25000000000", // 25 gwei +// maxFeePerGas: "30000000000", +// maxPriorityFeePerGas: "2000000000" +// }, +// estimatedTime: "180", // 3 minutes +// estimatedCost: "0.002125 ETH", +// confidence: 0.92, +// reasoning: "Current network congestion is low, allowing for lower gas prices" +// } +``` + +#### Batch Transaction Analysis + +```typescript +import { analyzeBatchTransactions } from "@thirdweb-dev/nebula"; + +const batchAnalysis = await analyzeBatchTransactions({ + body: { + transactions: [ + { + to: "0x...", + data: "0x...", + value: "1000000000000000000", // 1 ETH + }, + { + to: "0x...", + data: "0x...", + value: "0", + }, + ], + optimizationGoals: ["minimize-cost", "atomic-execution"], + chainId: 1, + }, +}); +``` + +### AI Agent Workflows + +#### Create Custom AI Agent + +```typescript +import { createAgent } from "@thirdweb-dev/nebula"; + +const customAgent = await createAgent({ + body: { + name: "DeFi Portfolio Manager", + description: "Automated DeFi portfolio management and optimization", + capabilities: [ + "portfolio-analysis", + "yield-optimization", + "risk-management", + "rebalancing" + ], + model: "nebula-defi-agent-v1", + configuration: { + riskTolerance: "moderate", + rebalanceThreshold: 0.05, // 5% deviation triggers rebalance + maxSlippage: 0.01, // 1% max slippage + }, + automationRules: [ + { + trigger: "weekly", + action: "portfolio-review", + conditions: ["market-stable"] + } + ], + }, +}); + +console.log("Created agent:", customAgent.data.agentId); +``` + +#### Execute Agent Workflow + +```typescript +import { executeAgentWorkflow } from "@thirdweb-dev/nebula"; + +const workflowResult = await executeAgentWorkflow({ + body: { + agentId: "agent-123", + workflow: "portfolio-optimization", + inputs: { + walletAddress: "0x...", + targetAllocation: { + "ETH": 0.4, + "USDC": 0.3, + "WBTC": 0.2, + "Other": 0.1 + }, + maxGasPrice: "30000000000" // 30 gwei + }, + executionMode: "simulation", // or "live" + }, +}); + +console.log("Workflow result:", workflowResult.data); ``` -This package was autogenerated from the [Nebula openAPI spec](https://nebula-api.thirdweb.com/docs) using [@hey-api/openapi-ts](https://github.com/hey-api/openapi-ts) +### Real-time AI Assistance + +#### Start AI Chat Session + +```typescript +import { startChatSession, sendChatMessage } from "@thirdweb-dev/nebula"; + +// Start a chat session with AI assistant +const session = await startChatSession({ + body: { + context: { + userAddress: "0x...", + connectedChains: [1, 137, 42161], // Ethereum, Polygon, Arbitrum + availableTokens: ["ETH", "USDC", "MATIC"], + }, + personality: "helpful-expert", // or "casual", "technical" + capabilities: ["transaction-help", "contract-analysis", "market-insights"], + }, +}); + +// Send messages to the AI assistant +const response = await sendChatMessage({ + body: { + sessionId: session.data.sessionId, + message: "I want to swap 100 USDC for ETH on Polygon. What's the best way to do this?", + includeTransactionPlan: true, + }, +}); + +console.log("AI Response:", response.data.message); +console.log("Suggested transactions:", response.data.transactionPlan); +``` + +### Advanced Features + +#### Multi-Agent Coordination + +```typescript +import { orchestrateAgents } from "@thirdweb-dev/nebula"; + +const orchestration = await orchestrateAgents({ + body: { + task: "cross-chain-arbitrage", + agents: [ + { + id: "price-monitor-agent", + role: "market-surveillance", + chains: [1, 137, 42161] + }, + { + id: "transaction-executor-agent", + role: "execution", + chains: [1, 137, 42161] + }, + { + id: "risk-manager-agent", + role: "risk-assessment" + } + ], + coordinationRules: { + consensusRequired: true, + riskThreshold: 0.02, // 2% max risk + profitThreshold: 0.005, // 0.5% min profit + }, + }, +}); +``` + +#### Learning and Feedback + +```typescript +import { provideFeedback } from "@thirdweb-dev/nebula"; + +await provideFeedback({ + body: { + sessionId: "session-123", + interactionId: "interaction-456", + feedback: { + rating: 5, // 1-5 stars + success: true, + comments: "The AI correctly identified the optimal gas settings", + improvementSuggestions: ["Could provide more detailed risk analysis"], + }, + }, +}); +``` + +## Configuration Options + +### Client Configuration + +```typescript +import { configure } from "@thirdweb-dev/nebula"; + +configure({ + secretKey: "your-secret-key", + baseUrl: "https://nebula-api.thirdweb.com", + + // Optional configuration + timeout: 30000, // Request timeout in ms + retries: 3, // Number of retries for failed requests + + // AI model preferences + defaultModel: "nebula-general-v1", + temperature: 0.7, // Creativity vs accuracy (0-1) + maxTokens: 2048, // Max response length + + // Rate limiting + rateLimit: { + requestsPerMinute: 60, + burstLimit: 10, + }, +}); +``` + +### Agent Configuration + +```typescript +const agentConfig = { + model: "nebula-specialized-v1", + personality: { + tone: "professional", // casual, professional, technical + verbosity: "concise", // brief, concise, detailed + riskAversion: "moderate", // low, moderate, high + }, + capabilities: { + contractAnalysis: true, + transactionOptimization: true, + marketInsights: true, + crossChainOperations: true, + }, + constraints: { + maxGasPrice: "50000000000", // 50 gwei + maxTransactionValue: "10000000000000000000", // 10 ETH + allowedChains: [1, 137, 42161], + requireConfirmation: true, + }, +}; +``` + +## API Reference + +### Core Functions + +- `configure(options)` - Configure the Nebula client +- `configureWithClient(client)` - Configure with thirdweb client +- `getNebulaClient(token)` - Get client instance for frontend use +- `getModels()` - List available AI models +- `getAgents(options?)` - List available agents + +### Analysis Functions + +- `analyzeContract(options)` - Analyze smart contract functionality +- `assessContractSecurity(options)` - Security assessment of contracts +- `analyzeBatchTransactions(options)` - Analyze multiple transactions +- `optimizeTransaction(options)` - Optimize transaction parameters + +### NLP Functions + +- `parseIntent(options)` - Convert natural language to blockchain operations +- `generateContract(options)` - Generate smart contract code from description +- `explainTransaction(options)` - Explain transaction in human language + +### Agent Functions + +- `createAgent(options)` - Create custom AI agent +- `executeAgentWorkflow(options)` - Execute agent workflow +- `orchestrateAgents(options)` - Coordinate multiple agents + +### Chat Functions + +- `startChatSession(options)` - Start AI chat session +- `sendChatMessage(options)` - Send message to AI assistant +- `getChatHistory(sessionId)` - Retrieve chat history + +## Examples + +### AI-Powered DeFi Assistant + +```typescript +import { + startChatSession, + sendChatMessage, + executeAgentWorkflow +} from "@thirdweb-dev/nebula"; + +class DeFiAIAssistant { + private sessionId: string; + + async initialize(userContext: any) { + const session = await startChatSession({ + body: { + context: userContext, + personality: "helpful-expert", + capabilities: [ + "defi-strategies", + "yield-optimization", + "risk-analysis", + "transaction-planning" + ], + }, + }); + + this.sessionId = session.data.sessionId; + return session; + } + + async getYieldOptimizationAdvice(portfolioData: any) { + const response = await sendChatMessage({ + body: { + sessionId: this.sessionId, + message: `Analyze my DeFi portfolio and suggest yield optimization strategies: ${JSON.stringify(portfolioData)}`, + includeTransactionPlan: true, + includeRiskAssessment: true, + }, + }); + + return { + advice: response.data.message, + suggestedTransactions: response.data.transactionPlan, + riskAssessment: response.data.riskAssessment, + }; + } + + async executeOptimization(strategy: string) { + return await executeAgentWorkflow({ + body: { + agentId: "defi-optimizer-agent", + workflow: "yield-optimization", + inputs: { + strategy, + sessionId: this.sessionId, + }, + executionMode: "simulation", // Simulate first + }, + }); + } +} + +// Usage +const assistant = new DeFiAIAssistant(); +await assistant.initialize({ + userAddress: "0x...", + connectedChains: [1, 137], + currentPositions: { + "USDC": "10000", + "ETH": "5", + "MATIC": "1000" + } +}); + +const advice = await assistant.getYieldOptimizationAdvice({ + totalValue: "$50000", + riskTolerance: "moderate", + timeHorizon: "6-months" +}); +``` + +### Smart Contract Security Auditor + +```typescript +import { + analyzeContract, + assessContractSecurity, + generateContract +} from "@thirdweb-dev/nebula"; + +class AISecurityAuditor { + async auditContract(contractAddress: string, chainId: number) { + // Get comprehensive analysis + const analysis = await analyzeContract({ + body: { + contractAddress, + chainId, + analysisType: "comprehensive", + includeSourceCode: true, + }, + }); + + // Get detailed security assessment + const security = await assessContractSecurity({ + body: { + contractAddress, + chainId, + includeVulnerabilities: true, + checkCompliance: ["erc20", "erc721", "erc1155"], + }, + }); + + return { + analysis: analysis.data, + security: security.data, + overallRisk: this.calculateOverallRisk(analysis.data, security.data), + recommendations: this.generateRecommendations(analysis.data, security.data), + }; + } + + async generateSecureContract(requirements: any) { + const generatedContract = await generateContract({ + body: { + description: requirements.description, + features: requirements.features, + standards: requirements.standards, + accessControl: "role-based", + includeSecurityFeatures: [ + "reentrancy-guard", + "pause-mechanism", + "access-control", + "overflow-protection" + ], + }, + }); + + // Auto-audit the generated contract + const auditResult = await this.auditGeneratedContract( + generatedContract.data.sourceCode + ); + + return { + sourceCode: generatedContract.data.sourceCode, + securityScore: auditResult.securityScore, + potentialIssues: auditResult.issues, + deploymentGuidance: generatedContract.data.deploymentInstructions, + }; + } + + private calculateOverallRisk(analysis: any, security: any): string { + // Custom risk calculation logic + const riskScore = (100 - security.securityScore) * 0.7 + + analysis.complexityScore * 0.3; + + if (riskScore < 20) return "low"; + if (riskScore < 50) return "medium"; + return "high"; + } + + private generateRecommendations(analysis: any, security: any): string[] { + // Generate contextual recommendations based on analysis + const recommendations = [...security.recommendations]; + + if (analysis.contractType === "ERC721" && !analysis.hasRoyalties) { + recommendations.push("Consider implementing ERC2981 royalty standard"); + } + + return recommendations; + } + + private async auditGeneratedContract(sourceCode: string) { + // Implementation for auditing generated contracts + return { + securityScore: 95, + issues: [], + }; + } +} +``` + +## References + +### Documentation +- [Nebula Documentation](https://portal.thirdweb.com/nebula) - Complete Nebula guide +- [AI Agent Development](https://portal.thirdweb.com/nebula/agents) - Creating custom agents +- [Natural Language Processing](https://portal.thirdweb.com/nebula/nlp) - NLP capabilities and usage + +### AI Models and Capabilities +- [Available Models](https://portal.thirdweb.com/nebula/models) - List of AI models and their capabilities +- [Model Training](https://portal.thirdweb.com/nebula/training) - Custom model training and fine-tuning +- [Performance Metrics](https://portal.thirdweb.com/nebula/metrics) - Model performance and accuracy metrics + +### Integration Examples +- [Nebula Examples](https://github.com/thirdweb-example/nebula-examples) - Example implementations +- [AI DeFi Assistant](https://github.com/thirdweb-example/nebula-defi) - DeFi-focused AI assistant +- [Smart Contract Auditor](https://github.com/thirdweb-example/nebula-auditor) - AI-powered security auditing + +### Advanced Topics +- [Multi-Agent Systems](https://portal.thirdweb.com/nebula/multi-agent) - Coordinating multiple AI agents +- [Custom Workflows](https://portal.thirdweb.com/nebula/workflows) - Building custom AI workflows +- [Learning and Adaptation](https://portal.thirdweb.com/nebula/learning) - How Nebula learns and improves + +### API References +- [Nebula API Reference](https://nebula-api.thirdweb.com/docs) - Complete API documentation +- [WebSocket Events](https://portal.thirdweb.com/nebula/websockets) - Real-time communication +- [Rate Limits](https://portal.thirdweb.com/nebula/rate-limits) - Usage limits and optimization + +### Community and Support +- [Discord #nebula](https://discord.gg/thirdweb) - Nebula specific help and discussions +- [AI Research Papers](https://research.thirdweb.com/nebula) - Academic research and publications +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report Nebula SDK issues diff --git a/packages/react-native-adapter/README.md b/packages/react-native-adapter/README.md index c512d2b4716..ee051fc8676 100644 --- a/packages/react-native-adapter/README.md +++ b/packages/react-native-adapter/README.md @@ -1,128 +1,516 @@ # React Native Adapter -This package is required to run the thirdweb SDK in React Native. +## Description -## Instructions +The **@thirdweb-dev/react-native-adapter** package provides essential polyfills and configuration required to run the thirdweb SDK in React Native applications. This adapter bridges the gap between web APIs that the thirdweb SDK expects and the React Native runtime environment, ensuring seamless cross-platform functionality. -### 1. Install the packages +### Key Features -Using your favorite pacakge manager, install all the require dependencies +- **Essential Polyfills**: Provides crypto, network, and storage polyfills for React Native +- **Metro Configuration**: Guides for proper module resolution setup +- **Cross-Platform Support**: Works with both iOS and Android React Native apps +- **Expo Integration**: Full compatibility with Expo and Expo Router +- **Native Dependencies**: Manages complex native dependency requirements +- **Security**: Implements secure cryptographic operations for mobile environments -```shell -npx expo install thirdweb @thirdweb-dev/react-native-adapter -``` +## Installation -Since react native requires installing native dependencies directly, you also have to install these required peer dependencies: +### 1. Install Core Packages -```shell -npx expo install react-native-get-random-values @react-native-community/netinfo expo-application @react-native-async-storage/async-storage expo-web-browser expo-linking react-native-aes-gcm-crypto react-native-quick-crypto@0.7.0-rc.6 amazon-cognito-identity-js @coinbase/wallet-mobile-sdk react-native-mmkv react-native-svg @react-native-clipboard/clipboard +```bash +npm install thirdweb @thirdweb-dev/react-native-adapter ``` -Here's an explanation of each peer dependency and why its needed: +Or with Expo: +```bash +npx expo install thirdweb @thirdweb-dev/react-native-adapter ``` -// needed for wallet connect -react-native-get-random-values -@react-native-community/netinfo -expo-application -// needed wallet connect + in-app wallet -@react-native-async-storage/async-storage +### 2. Install Required Peer Dependencies + +Since React Native requires installing native dependencies directly, you must install these required peer dependencies: -// needed for inapp wallet -expo-web-browser // for oauth flows -amazon-cognito-identity-js // for authentication -react-native-aes-gcm-crypto // for encryption -react-native-quick-crypto@0.7.0-rc.6 //for fast hashing +```bash +npx expo install react-native-get-random-values @react-native-community/netinfo expo-application @react-native-async-storage/async-storage expo-web-browser expo-linking react-native-aes-gcm-crypto react-native-quick-crypto@0.7.0-rc.6 amazon-cognito-identity-js @coinbase/wallet-mobile-sdk react-native-mmkv react-native-svg @react-native-clipboard/clipboard +``` -// needed for the prebuilt UIs -react-native-svg -@react-native-clipboard/clipboard +#### Dependency Explanations + +```typescript +// Wallet Connect dependencies +"react-native-get-random-values" // Secure random number generation +"@react-native-community/netinfo" // Network state detection +"expo-application" // App information access + +// In-app wallet dependencies +"@react-native-async-storage/async-storage" // Persistent storage +"expo-web-browser" // OAuth flows +"amazon-cognito-identity-js" // Authentication +"react-native-aes-gcm-crypto" // Encryption +"react-native-quick-crypto" // Fast hashing + +// UI components dependencies +"react-native-svg" // SVG rendering +"react-native-mmkv" // Fast key-value storage +"@react-native-clipboard/clipboard" // Clipboard access ``` -### 2. Edit your `metro.config.js` +## Usage + +### 1. Configure Metro -If you don't already have a `metro.config.file.js` in your project, you can create one by running: +If you don't have a `metro.config.js` file, create one: -```shell +```bash npx expo customize metro.config.js ``` -Then, you need to add 2 properties to the metro resolver: `unstable_enablePackageExports` and `unstable_conditionNames`. This is to tell metro to resolve named `exports` properly. - -```js -// file: metro.config.js +Add the required resolver properties: -// Learn more https://docs.expo.io/guides/customizing-metro +```javascript +// metro.config.js const { getDefaultConfig } = require("expo/metro-config"); /** @type {import('expo/metro-config').MetroConfig} */ const config = getDefaultConfig(__dirname); -// ADD THESE 2 PROPERTIES +// Enable package exports and conditional exports config.resolver.unstable_enablePackageExports = true; config.resolver.unstable_conditionNames = [ "react-native", - "browser", + "browser", "require", ]; module.exports = config; ``` -### 3. Import `@thirdweb-dev/react-native-adapter` at the top of your `App.tsx` +### 2. Import Polyfills -This will polyfill all the required functionality needed. +#### Standard React Native App -```js -// this needs to be imported before anything else -import "@thirdweb-dev/react-native-adapter"; -// the rest of your app +Import the adapter at the very top of your `App.tsx`: + +```typescript +// App.tsx +import "@thirdweb-dev/react-native-adapter"; // Must be first import +import React from "react"; +import { View } from "react-native"; +import { ThirdwebProvider } from "thirdweb/react"; + +export default function App() { + return ( + + {/* Your app content */} + + ); +} ``` -If you're using `expo-router`, you need to polyfill before the router entry: +#### Expo Router Apps -1. create a `app/index.ts` +For Expo Router, create a new entry point to ensure polyfills load before routing: -This will be the new entrypoint to your app, ensuring the polyfills happen before any routing. +1. Create `app/index.ts`: -```ts -// file: app/index.ts +```typescript +// app/index.ts +import "@thirdweb-dev/react-native-adapter"; // Polyfills first +import "expo-router/entry"; // Then router +``` -// this needs to be imported before expo-router -import "@thirdweb-dev/react-native-adapter"; -import "expo-router/entry"; +2. Update your `package.json`: + +```json +{ + "main": "./app/index" +} ``` -2. Change your main entrypoint in `package.json` +### 3. Basic thirdweb Setup + +Once configured, use thirdweb exactly as you would in a web environment: + +```typescript +// MyComponent.tsx +import React from "react"; +import { View, Text } from "react-native"; +import { + ThirdwebProvider, + ConnectButton, + useActiveAccount +} from "thirdweb/react"; +import { createThirdwebClient } from "thirdweb"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", +}); + +function WalletInfo() { + const account = useActiveAccount(); + + return ( + + {account ? ( + Connected: {account.address} + ) : ( + Not connected + )} + + ); +} + +export default function App() { + return ( + + + + + + + ); +} +``` -Now you can replace `expo-router/entry` with `./app/index` as your main entrypoint. +### 4. In-App Wallets Example + +```typescript +import { createWallet } from "thirdweb/wallets"; +import { ConnectButton } from "thirdweb/react"; + +const inAppWallet = createWallet("inApp", { + auth: { + options: ["email", "google", "apple", "facebook"], + }, +}); + +function LoginScreen() { + return ( + + ); +} +``` +### 5. Smart Contract Interactions + +```typescript +import { getContract, readContract, prepareContractCall } from "thirdweb"; +import { useSendTransaction, useReadContract } from "thirdweb/react"; +import { polygon } from "thirdweb/chains"; + +const contract = getContract({ + client, + chain: polygon, + address: "0x...", +}); + +function TokenBalance() { + const account = useActiveAccount(); + const { data: balance } = useReadContract({ + contract, + method: "function balanceOf(address) returns (uint256)", + params: [account?.address!], + queryOptions: { enabled: !!account }, + }); + + return Balance: {balance?.toString()}; +} + +function TransferButton() { + const { mutate: sendTransaction, isPending } = useSendTransaction(); + + const handleTransfer = () => { + const transaction = prepareContractCall({ + contract, + method: "function transfer(address to, uint256 amount)", + params: ["0x...", 1000000000000000000n], // 1 token + }); + + sendTransaction(transaction); + }; + + return ( + + + {isPending ? "Sending..." : "Send Token"} + + + ); +} ``` -// file: package.json -"main": "./app/index", +## Configuration Notes + +### Android Requirements + +- **Minimum SDK**: React Native AES GCM Crypto requires `minSdkVersion 26`. Update your `android/build.gradle`: + +```gradle +// android/build.gradle +buildscript { + ext { + minSdkVersion = 26 // Required for encryption + compileSdkVersion = 34 + targetSdkVersion = 34 + } +} ``` -### Additional notes +### iOS Requirements + +- **iOS 13+**: Some cryptographic functions require iOS 13 or higher +- **Capability Entitlements**: Ensure proper entitlements for network and keychain access + +### Common Issues and Solutions + +#### Metro Resolution Warnings -1. `react-native-aes-gcm-crypto` requires `minSDK 26` for android, you can edit this in your `build.gradle` file -2. You will get some warnings about unresolved exports, this is normal and will get better as the libraries get updated. +You may see warnings about unresolved exports. This is normal and will improve as libraries update to support newer Metro versions. -### Use the `thirdweb` package in React Native +#### Build Errors -Once all the setup above is all done, you can use the most of functionality in the `thirdweb` package out of the box, without having to do any react native specific code. +If you encounter build errors: -This means that you can follow all the React documentation and expect it all to be exactly the same. +1. Clear Metro cache: `npx expo start --clear` +2. Clean and reinstall: `rm -rf node_modules && npm install` +3. For iOS: `cd ios && pod install` (if using bare React Native) -Examples: +#### Performance Optimization -```tsx -import { ThirdwebProvider } form "thirdweb/react"; +For better performance, consider lazy loading the thirdweb SDK: + +```typescript +import { lazy, Suspense } from "react"; + +const ThirdwebApp = lazy(() => import("./ThirdwebApp")); + +export default function App() { + return ( + }> + + + ); +} +``` + +## Examples + +### Complete React Native DApp + +```typescript +// App.tsx +import "@thirdweb-dev/react-native-adapter"; +import React from "react"; +import { + View, + Text, + StyleSheet, + SafeAreaView, + TouchableOpacity, +} from "react-native"; +import { + ThirdwebProvider, + ConnectButton, + useActiveAccount, + useReadContract, + useSendTransaction, +} from "thirdweb/react"; +import { createThirdwebClient, getContract, prepareContractCall } from "thirdweb"; +import { polygon } from "thirdweb/chains"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", +}); + +const contract = getContract({ + client, + chain: polygon, + address: "0x...", // Your contract address +}); + +function WalletSection() { + const account = useActiveAccount(); + + return ( + + Wallet Connection + + {account && ( + + Connected: {account.address.slice(0, 6)}...{account.address.slice(-4)} + + )} + + ); +} + +function ContractInteraction() { + const account = useActiveAccount(); + const { data: balance } = useReadContract({ + contract, + method: "function balanceOf(address) returns (uint256)", + params: [account?.address!], + queryOptions: { enabled: !!account }, + }); + + const { mutate: sendTransaction, isPending } = useSendTransaction(); + + const handleMint = () => { + const transaction = prepareContractCall({ + contract, + method: "function mint(address to, uint256 amount)", + params: [account!.address, 1000000000000000000n], + }); + sendTransaction(transaction); + }; + + if (!account) return null; + + return ( + + Contract Interaction + Balance: {balance?.toString() || "0"} + + + {isPending ? "Minting..." : "Mint Token"} + + + + ); +} + +export default function App() { + return ( + + + My Web3 App + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + backgroundColor: "#f5f5f5", + }, + header: { + fontSize: 24, + fontWeight: "bold", + textAlign: "center", + marginBottom: 30, + }, + section: { + backgroundColor: "white", + padding: 20, + borderRadius: 10, + marginBottom: 20, + }, + title: { + fontSize: 18, + fontWeight: "600", + marginBottom: 15, + }, + address: { + marginTop: 10, + fontSize: 14, + color: "#666", + }, + button: { + backgroundColor: "#007AFF", + padding: 15, + borderRadius: 8, + marginTop: 10, + }, + buttonDisabled: { + backgroundColor: "#ccc", + }, + buttonText: { + color: "white", + textAlign: "center", + fontWeight: "600", + }, +}); ``` -### Resources +## API Reference + +### Core Import + +```typescript +import "@thirdweb-dev/react-native-adapter"; +``` + +This single import provides: + +- **Crypto Polyfills**: `crypto.getRandomValues()`, `crypto.subtle` +- **Buffer Polyfill**: Global `Buffer` object +- **URL Polyfill**: `URL` and `URLSearchParams` constructors +- **Storage Polyfills**: LocalStorage and SessionStorage implementations +- **Network Polyfills**: Fetch and WebSocket implementations +- **Text Encoding**: TextEncoder and TextDecoder + +### Metro Configuration + +Required metro.config.js settings: + +```javascript +config.resolver.unstable_enablePackageExports = true; +config.resolver.unstable_conditionNames = [ + "react-native", + "browser", + "require", +]; +``` -- [Full working demo](https://github.com/thirdweb-dev/expo-starter) -- [React docs](https://portal.thirdweb.com/typescript/v5/react) -- [TypeScript docs](https://portal.thirdweb.com/typescript/v5) +## References + +### Documentation +- [React Native Integration Guide](https://portal.thirdweb.com/react-native) - Complete setup guide +- [thirdweb React Native Docs](https://portal.thirdweb.com/typescript/v5/react) - React Native specific documentation +- [Metro Configuration Guide](https://metrobundler.dev/docs/resolution) - Metro resolver documentation + +### Examples and Templates +- [Full Working Demo](https://github.com/thirdweb-dev/expo-starter) - Complete React Native example +- [Expo Router Example](https://github.com/thirdweb-example/expo-router-starter) - Expo Router integration +- [React Native Templates](https://thirdweb.com/templates?framework=react-native) - Ready-to-use templates + +### Platform-Specific Guides +- [iOS Setup Guide](https://portal.thirdweb.com/react-native/ios) - iOS specific configuration +- [Android Setup Guide](https://portal.thirdweb.com/react-native/android) - Android specific configuration +- [Expo Integration](https://portal.thirdweb.com/react-native/expo) - Expo specific setup + +### Dependencies Documentation +- [react-native-quick-crypto](https://github.com/margelo/react-native-quick-crypto) - Cryptographic operations +- [react-native-aes-gcm-crypto](https://github.com/craftzdog/react-native-aes-gcm-crypto) - AES-GCM encryption +- [Expo Web Browser](https://docs.expo.dev/versions/latest/sdk/webbrowser/) - OAuth flows +- [React Native AsyncStorage](https://react-native-async-storage.github.io/async-storage/) - Persistent storage + +### Troubleshooting +- [Common Issues](https://portal.thirdweb.com/react-native/troubleshooting) - Solutions to common problems +- [Metro Resolution Issues](https://portal.thirdweb.com/react-native/metro-issues) - Metro configuration problems +- [Build Errors](https://portal.thirdweb.com/react-native/build-errors) - Platform-specific build issues + +### Community Support +- [Discord #react-native](https://discord.gg/thirdweb) - React Native specific help +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Bug reports and feature requests +- [Stack Overflow](https://stackoverflow.com/questions/tagged/thirdweb) - Community Q&A diff --git a/packages/service-utils/README.md b/packages/service-utils/README.md index 189c8f1a2a6..9d8bf44b43a 100644 --- a/packages/service-utils/README.md +++ b/packages/service-utils/README.md @@ -1,7 +1,997 @@ # Service Utils -This repository contains utilities that handle common requirements for thirdweb services. +## Description -- `/cf-worker`: for use only in Cloudflare Worker services -- `/node`: for use in self-hosted services -- `/core`: for use in any service +The **@thirdweb-dev/service-utils** package provides a comprehensive collection of utilities, types, and helper functions used across thirdweb's backend services and infrastructure. This package contains shared functionality for authentication, data validation, error handling, logging, caching, and other common service operations used internally by thirdweb services. + +### Key Features + +- **Authentication Utilities**: JWT token handling, signature verification, and session management +- **Data Validation**: Zod schemas and validation utilities for API inputs and outputs +- **Error Handling**: Standardized error types and error handling utilities +- **Logging**: Structured logging utilities with multiple output formats +- **Caching**: Redis and in-memory caching utilities with TTL support +- **Database Utilities**: Database connection helpers and query utilities +- **Queue Management**: Job queue utilities with retry mechanisms +- **Cryptographic Functions**: Secure hashing, encryption, and signing utilities +- **Rate Limiting**: Request rate limiting and throttling utilities +- **Configuration Management**: Environment-based configuration loading + +## Installation + +```bash +npm install @thirdweb-dev/service-utils +``` + +### Platform-Specific Exports + +The package provides different exports for different environments: + +```bash +# For general Node.js environments +import { ... } from "@thirdweb-dev/service-utils" + +# For Cloudflare Workers +import { ... } from "@thirdweb-dev/service-utils/cf-worker" + +# For Node.js specific features +import { ... } from "@thirdweb-dev/service-utils/node" +``` + +## Usage + +### Authentication Utilities + +#### JWT Token Management + +```typescript +import { + generateJWT, + verifyJWT, + refreshJWT, + JWTPayload +} from "@thirdweb-dev/service-utils"; + +// Generate JWT token +const payload: JWTPayload = { + userId: "user123", + walletAddress: "0x...", + permissions: ["read", "write"], + exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour +}; + +const token = await generateJWT(payload, "your-secret-key"); +console.log("Generated token:", token); + +// Verify JWT token +try { + const decoded = await verifyJWT(token, "your-secret-key"); + console.log("Decoded payload:", decoded); +} catch (error) { + console.error("Invalid token:", error); +} + +// Refresh JWT token +const refreshedToken = await refreshJWT(token, "your-secret-key", { + extendExpiry: 3600, // Extend by 1 hour +}); +``` + +#### Signature Verification + +```typescript +import { + verifySignature, + verifyEIP712Signature, + recoverAddress +} from "@thirdweb-dev/service-utils"; + +// Verify simple message signature +const isValid = await verifySignature({ + message: "Please sign this message", + signature: "0x...", + address: "0x...", +}); + +console.log("Signature valid:", isValid); + +// Verify EIP-712 typed data signature +const eip712Valid = await verifyEIP712Signature({ + domain: { + name: "MyApp", + version: "1", + chainId: 1, + verifyingContract: "0x...", + }, + types: { + Login: [ + { name: "user", type: "address" }, + { name: "timestamp", type: "uint256" }, + ], + }, + value: { + user: "0x...", + timestamp: Date.now(), + }, + signature: "0x...", + expectedAddress: "0x...", +}); + +// Recover address from signature +const recoveredAddress = await recoverAddress({ + message: "Please sign this message", + signature: "0x...", +}); + +console.log("Recovered address:", recoveredAddress); +``` + +### Data Validation + +#### Zod Schema Utilities + +```typescript +import { + createAPISchema, + validateAddress, + validateChainId, + PaginationSchema, + AddressSchema, + ChainIdSchema +} from "@thirdweb-dev/service-utils"; +import { z } from "zod"; + +// Create API endpoint schema +const CreateContractSchema = createAPISchema({ + body: z.object({ + name: z.string().min(1).max(100), + symbol: z.string().min(1).max(10), + ownerAddress: AddressSchema, + chainId: ChainIdSchema, + metadata: z.object({ + description: z.string().optional(), + image: z.string().url().optional(), + }).optional(), + }), + query: PaginationSchema.optional(), +}); + +// Validate request data +try { + const validatedData = CreateContractSchema.parse({ + body: { + name: "My NFT Collection", + symbol: "MNC", + ownerAddress: "0x1234567890123456789012345678901234567890", + chainId: 1, + }, + }); + + console.log("Valid data:", validatedData); +} catch (error) { + console.error("Validation error:", error.errors); +} + +// Address validation utility +const isValidAddress = validateAddress("0x1234567890123456789012345678901234567890"); +console.log("Address valid:", isValidAddress); + +// Chain ID validation +const isValidChain = validateChainId(1); +console.log("Chain ID valid:", isValidChain); +``` + +#### Custom Validation Schemas + +```typescript +import { z } from "zod"; +import { + createPaginatedResponse, + createErrorResponse, + NFTMetadataSchema +} from "@thirdweb-dev/service-utils"; + +// NFT Collection schema +const NFTCollectionSchema = z.object({ + address: z.string().regex(/^0x[a-fA-F0-9]{40}$/), + name: z.string(), + symbol: z.string(), + totalSupply: z.string().regex(/^\d+$/), + metadata: NFTMetadataSchema.optional(), +}); + +// API Response schemas +const NFTCollectionListResponse = createPaginatedResponse(NFTCollectionSchema); +const NFTCollectionErrorResponse = createErrorResponse(); + +// Type inference +type NFTCollection = z.infer; +type NFTCollectionList = z.infer; +``` + +### Error Handling + +#### Standardized Error Types + +```typescript +import { + ServiceError, + ValidationError, + AuthenticationError, + NotFoundError, + RateLimitError, + createErrorHandler +} from "@thirdweb-dev/service-utils"; + +// Create custom errors +throw new ValidationError("Invalid wallet address format"); +throw new AuthenticationError("JWT token expired"); +throw new NotFoundError("Contract not found"); +throw new RateLimitError("Rate limit exceeded", { retryAfter: 60 }); + +// Generic service error +throw new ServiceError("Database connection failed", { + code: "DB_CONNECTION_ERROR", + statusCode: 500, + context: { host: "db.example.com", port: 5432 }, +}); + +// Error handler middleware +const errorHandler = createErrorHandler({ + logger: console, + includeStackTrace: process.env.NODE_ENV === "development", + sanitizeErrors: true, +}); + +// Express.js usage +app.use(errorHandler); +``` + +#### Error Response Formatting + +```typescript +import { + formatErrorResponse, + isServiceError, + sanitizeError +} from "@thirdweb-dev/service-utils"; + +function handleError(error: unknown) { + if (isServiceError(error)) { + // Handle known service errors + return formatErrorResponse({ + error: error.message, + code: error.code, + statusCode: error.statusCode, + context: error.context, + }); + } + + // Handle unknown errors + const sanitized = sanitizeError(error); + return formatErrorResponse({ + error: "Internal server error", + code: "INTERNAL_ERROR", + statusCode: 500, + details: process.env.NODE_ENV === "development" ? sanitized : undefined, + }); +} +``` + +### Logging Utilities + +#### Structured Logging + +```typescript +import { + createLogger, + LogLevel, + createRequestLogger +} from "@thirdweb-dev/service-utils"; + +// Create structured logger +const logger = createLogger({ + service: "contract-service", + level: LogLevel.INFO, + format: "json", // or "text" + outputs: ["console", "file"], + metadata: { + version: "1.0.0", + environment: process.env.NODE_ENV, + }, +}); + +// Log with context +logger.info("Contract deployed", { + contractAddress: "0x...", + chainId: 1, + deployerAddress: "0x...", + transactionHash: "0x...", +}); + +logger.error("Deployment failed", { + error: error.message, + contractType: "ERC721", + chainId: 1, +}); + +// Request logging middleware +const requestLogger = createRequestLogger({ + logger, + includeBody: false, + includeHeaders: ["user-agent", "x-forwarded-for"], + excludePaths: ["/health", "/metrics"], +}); + +// Express.js usage +app.use(requestLogger); +``` + +#### Performance Monitoring + +```typescript +import { + createPerformanceTimer, + trackMetric, + createMetricsCollector +} from "@thirdweb-dev/service-utils"; + +// Performance timing +const timer = createPerformanceTimer(); +timer.start("database-query"); + +// ... perform database query +const result = await queryDatabase(); + +timer.end("database-query"); +const duration = timer.getDuration("database-query"); + +logger.info("Database query completed", { + duration: `${duration}ms`, + resultCount: result.length, +}); + +// Metrics tracking +trackMetric("contracts.deployed", 1, { + chainId: "1", + contractType: "ERC721", +}); + +trackMetric("api.response_time", duration, { + endpoint: "/api/contracts", + status: "success", +}); + +// Metrics collector +const metricsCollector = createMetricsCollector({ + prefix: "thirdweb_service", + labels: { + service: "contract-api", + version: "1.0.0", + }, +}); + +metricsCollector.incrementCounter("requests_total", { + method: "POST", + endpoint: "/deploy", +}); +``` + +### Caching Utilities + +#### Redis Caching + +```typescript +import { + createRedisCache, + createMemoryCache, + CacheConfig +} from "@thirdweb-dev/service-utils"; + +// Redis cache configuration +const redisCache = createRedisCache({ + host: "localhost", + port: 6379, + password: "redis-password", + db: 0, + keyPrefix: "thirdweb:", + defaultTTL: 300, // 5 minutes +}); + +// Set cache value +await redisCache.set("contract:0x123", { + name: "My Contract", + symbol: "MC", + totalSupply: "1000", +}, { ttl: 600 }); // 10 minutes + +// Get cache value +const cached = await redisCache.get("contract:0x123"); +console.log("Cached data:", cached); + +// Cache with automatic serialization +await redisCache.setJSON("user:123:profile", { + walletAddress: "0x...", + preferences: { theme: "dark" }, +}); + +const profile = await redisCache.getJSON("user:123:profile"); + +// Batch operations +await redisCache.mset({ + "contract:0x123": contractData, + "contract:0x456": anotherContract, +}); + +const contracts = await redisCache.mget(["contract:0x123", "contract:0x456"]); +``` + +#### Memory Caching + +```typescript +import { createMemoryCache } from "@thirdweb-dev/service-utils"; + +// In-memory cache for development or small-scale usage +const memoryCache = createMemoryCache({ + maxSize: 1000, // Maximum number of items + defaultTTL: 300, // 5 minutes + cleanupInterval: 60, // Cleanup every minute +}); + +// Same API as Redis cache +await memoryCache.set("key", "value", { ttl: 120 }); +const value = await memoryCache.get("key"); + +// Memory usage monitoring +const stats = memoryCache.getStats(); +console.log("Cache stats:", { + size: stats.size, + hitRate: stats.hitRate, + memoryUsage: stats.memoryUsage, +}); +``` + +### Queue Management + +#### Job Queue Utilities + +```typescript +import { + createJobQueue, + JobProcessor, + JobConfig +} from "@thirdweb-dev/service-utils"; + +// Define job processor +const contractDeploymentProcessor: JobProcessor<{ + contractType: string; + metadata: any; + chainId: number; +}> = async (job) => { + logger.info("Processing contract deployment", { + jobId: job.id, + contractType: job.data.contractType, + chainId: job.data.chainId, + }); + + try { + // Simulate contract deployment + const result = await deployContract(job.data); + + return { + success: true, + contractAddress: result.address, + transactionHash: result.txHash, + }; + } catch (error) { + logger.error("Contract deployment failed", { + jobId: job.id, + error: error.message, + }); + throw error; + } +}; + +// Create job queue +const deploymentQueue = createJobQueue({ + name: "contract-deployment", + processor: contractDeploymentProcessor, + config: { + concurrency: 5, // Process 5 jobs concurrently + retries: 3, + backoff: "exponential", + removeOnComplete: 100, // Keep last 100 completed jobs + removeOnFail: 50, // Keep last 50 failed jobs + }, + redis: { + host: "localhost", + port: 6379, + }, +}); + +// Add job to queue +const job = await deploymentQueue.add("deploy-nft-collection", { + contractType: "ERC721", + metadata: { + name: "My Collection", + symbol: "MC", + }, + chainId: 1, +}, { + delay: 5000, // Delay processing by 5 seconds + priority: 1, // Higher priority +}); + +console.log("Job added:", job.id); + +// Monitor queue events +deploymentQueue.on("completed", (job, result) => { + logger.info("Job completed", { + jobId: job.id, + result, + }); +}); + +deploymentQueue.on("failed", (job, error) => { + logger.error("Job failed", { + jobId: job.id, + error: error.message, + }); +}); +``` + +### Cryptographic Utilities + +#### Hashing and Encryption + +```typescript +import { + hashData, + verifyHash, + encryptData, + decryptData, + generateSecureToken +} from "@thirdweb-dev/service-utils"; + +// Secure hashing +const hashedPassword = await hashData("user-password", { + algorithm: "argon2", // or "bcrypt", "scrypt" + saltLength: 32, +}); + +const isValidPassword = await verifyHash("user-password", hashedPassword); +console.log("Password valid:", isValidPassword); + +// Data encryption +const encryptedData = await encryptData({ + message: "sensitive information", + key: "encryption-key-32-bytes-long!", + algorithm: "aes-256-gcm", +}); + +const decryptedData = await decryptData({ + encryptedMessage: encryptedData.encryptedData, + key: "encryption-key-32-bytes-long!", + iv: encryptedData.iv, + tag: encryptedData.tag, + algorithm: "aes-256-gcm", +}); + +console.log("Decrypted:", decryptedData); + +// Secure token generation +const apiKey = generateSecureToken(64); // 64 bytes = 128 hex characters +const sessionId = generateSecureToken(32); // 32 bytes = 64 hex characters + +console.log("API Key:", apiKey); +console.log("Session ID:", sessionId); +``` + +### Rate Limiting + +#### Request Rate Limiting + +```typescript +import { + createRateLimiter, + RateLimitConfig, + createRateLimitMiddleware +} from "@thirdweb-dev/service-utils"; + +// Create rate limiter +const rateLimiter = createRateLimiter({ + windowMs: 60 * 1000, // 1 minute window + max: 100, // Maximum 100 requests per window + keyGenerator: (req) => req.ip, // Rate limit by IP + skipSuccessfulRequests: false, + skipFailedRequests: false, + store: "redis", // or "memory" + redis: { + host: "localhost", + port: 6379, + }, +}); + +// Rate limit middleware for Express.js +const rateLimitMiddleware = createRateLimitMiddleware(rateLimiter); +app.use("/api", rateLimitMiddleware); + +// Custom rate limiting +app.post("/api/deploy", async (req, res) => { + const identifier = `deploy:${req.user.id}`; + + const result = await rateLimiter.consume(identifier, 1); + + if (!result.allowed) { + return res.status(429).json({ + error: "Rate limit exceeded", + retryAfter: result.retryAfter, + resetTime: result.resetTime, + }); + } + + // Process deployment request + const deployment = await processDeployment(req.body); + res.json(deployment); +}); + +// Different rate limits for different endpoints +const deploymentRateLimit = createRateLimiter({ + windowMs: 60 * 1000, // 1 minute + max: 5, // 5 deployments per minute +}); + +const readRateLimit = createRateLimiter({ + windowMs: 60 * 1000, // 1 minute + max: 1000, // 1000 reads per minute +}); +``` + +## Configuration Management + +### Environment Configuration + +```typescript +import { + loadConfig, + validateConfig, + ConfigSchema +} from "@thirdweb-dev/service-utils"; +import { z } from "zod"; + +// Define configuration schema +const ServiceConfigSchema = z.object({ + port: z.number().default(3000), + database: z.object({ + host: z.string(), + port: z.number().default(5432), + name: z.string(), + username: z.string(), + password: z.string(), + }), + redis: z.object({ + host: z.string().default("localhost"), + port: z.number().default(6379), + password: z.string().optional(), + }), + jwt: z.object({ + secret: z.string().min(32), + expiresIn: z.string().default("1h"), + }), + logging: z.object({ + level: z.enum(["debug", "info", "warn", "error"]).default("info"), + format: z.enum(["json", "text"]).default("json"), + }), +}); + +// Load and validate configuration +const config = loadConfig(ServiceConfigSchema, { + envPrefix: "THIRDWEB_", + configFiles: ["config.json", "config.local.json"], + overrides: { + port: process.env.PORT ? parseInt(process.env.PORT) : undefined, + }, +}); + +console.log("Service configuration:", config); + +// Type-safe configuration access +const dbConfig = config.database; +const jwtSecret = config.jwt.secret; +``` + +## API Reference + +### Authentication + +- `generateJWT(payload, secret, options?)` - Generate JWT token +- `verifyJWT(token, secret)` - Verify JWT token +- `refreshJWT(token, secret, options)` - Refresh JWT token +- `verifySignature(options)` - Verify message signature +- `verifyEIP712Signature(options)` - Verify EIP-712 signature + +### Validation + +- `createAPISchema(schema)` - Create API endpoint schema +- `validateAddress(address)` - Validate Ethereum address +- `validateChainId(chainId)` - Validate chain ID +- `createPaginatedResponse(schema)` - Create paginated response schema + +### Error Handling + +- `ServiceError` - Base service error class +- `ValidationError` - Data validation error +- `AuthenticationError` - Authentication error +- `NotFoundError` - Resource not found error +- `RateLimitError` - Rate limit exceeded error + +### Logging + +- `createLogger(config)` - Create structured logger +- `createRequestLogger(config)` - Create request logging middleware +- `createPerformanceTimer()` - Create performance timer +- `trackMetric(name, value, labels?)` - Track application metrics + +### Caching + +- `createRedisCache(config)` - Create Redis cache instance +- `createMemoryCache(config)` - Create in-memory cache instance +- `cache.set(key, value, options?)` - Set cache value +- `cache.get(key)` - Get cache value +- `cache.del(key)` - Delete cache value + +### Queue Management + +- `createJobQueue(config)` - Create job queue +- `queue.add(name, data, options?)` - Add job to queue +- `queue.process(processor)` - Process jobs +- `queue.on(event, handler)` - Listen to queue events + +### Cryptography + +- `hashData(data, options)` - Hash data securely +- `verifyHash(data, hash)` - Verify hashed data +- `encryptData(options)` - Encrypt data +- `decryptData(options)` - Decrypt data +- `generateSecureToken(bytes)` - Generate secure random token + +### Rate Limiting + +- `createRateLimiter(config)` - Create rate limiter +- `createRateLimitMiddleware(limiter)` - Create Express middleware +- `limiter.consume(key, tokens)` - Consume rate limit tokens + +## Examples + +### Complete Service Setup + +```typescript +import { + createLogger, + createRedisCache, + createRateLimiter, + createJobQueue, + createAPISchema, + ServiceError, + loadConfig, +} from "@thirdweb-dev/service-utils"; +import { z } from "zod"; + +class ContractService { + private logger; + private cache; + private rateLimiter; + private deploymentQueue; + + constructor(config: any) { + // Initialize logger + this.logger = createLogger({ + service: "contract-service", + level: config.logging.level, + format: config.logging.format, + }); + + // Initialize cache + this.cache = createRedisCache({ + host: config.redis.host, + port: config.redis.port, + password: config.redis.password, + keyPrefix: "contracts:", + defaultTTL: 300, + }); + + // Initialize rate limiter + this.rateLimiter = createRateLimiter({ + windowMs: 60 * 1000, + max: 10, // 10 deployments per minute + store: "redis", + redis: config.redis, + }); + + // Initialize job queue + this.deploymentQueue = createJobQueue({ + name: "contract-deployment", + processor: this.processDeployment.bind(this), + config: { + concurrency: 3, + retries: 3, + backoff: "exponential", + }, + redis: config.redis, + }); + + this.setupEventHandlers(); + } + + async deployContract(userId: string, contractData: any) { + // Check rate limit + const rateLimitResult = await this.rateLimiter.consume( + `deploy:${userId}`, + 1 + ); + + if (!rateLimitResult.allowed) { + throw new ServiceError("Rate limit exceeded", { + code: "RATE_LIMIT_EXCEEDED", + statusCode: 429, + context: { retryAfter: rateLimitResult.retryAfter }, + }); + } + + // Check cache for existing deployment + const cacheKey = `deployment:${userId}:${JSON.stringify(contractData)}`; + const cached = await this.cache.get(cacheKey); + + if (cached) { + this.logger.info("Returning cached deployment", { + userId, + cacheKey, + }); + return cached; + } + + // Queue deployment job + const job = await this.deploymentQueue.add("deploy", { + userId, + contractData, + timestamp: Date.now(), + }); + + this.logger.info("Contract deployment queued", { + userId, + jobId: job.id, + contractType: contractData.type, + }); + + return { + jobId: job.id, + status: "queued", + estimatedCompletion: Date.now() + 60000, // 1 minute + }; + } + + private async processDeployment(job: any) { + const { userId, contractData } = job.data; + + this.logger.info("Processing contract deployment", { + jobId: job.id, + userId, + contractType: contractData.type, + }); + + try { + // Simulate deployment process + await new Promise(resolve => setTimeout(resolve, 5000)); + + const result = { + contractAddress: "0x" + Math.random().toString(16).substr(2, 40), + transactionHash: "0x" + Math.random().toString(16).substr(2, 64), + blockNumber: Math.floor(Math.random() * 1000000), + deployedAt: new Date().toISOString(), + }; + + // Cache the result + const cacheKey = `deployment:${userId}:${JSON.stringify(contractData)}`; + await this.cache.set(cacheKey, result, { ttl: 3600 }); // 1 hour + + this.logger.info("Contract deployment completed", { + jobId: job.id, + userId, + contractAddress: result.contractAddress, + }); + + return result; + } catch (error) { + this.logger.error("Contract deployment failed", { + jobId: job.id, + userId, + error: error.message, + }); + throw error; + } + } + + private setupEventHandlers() { + this.deploymentQueue.on("completed", (job, result) => { + this.logger.info("Deployment job completed", { + jobId: job.id, + contractAddress: result.contractAddress, + }); + }); + + this.deploymentQueue.on("failed", (job, error) => { + this.logger.error("Deployment job failed", { + jobId: job.id, + error: error.message, + }); + }); + } + + async getDeploymentStatus(jobId: string) { + const job = await this.deploymentQueue.getJob(jobId); + + if (!job) { + throw new ServiceError("Job not found", { + code: "JOB_NOT_FOUND", + statusCode: 404, + }); + } + + return { + id: job.id, + status: await job.getState(), + progress: job.progress(), + result: job.returnvalue, + error: job.failedReason, + createdAt: new Date(job.timestamp), + processedAt: job.processedOn ? new Date(job.processedOn) : null, + finishedAt: job.finishedOn ? new Date(job.finishedOn) : null, + }; + } +} + +// Usage +const config = loadConfig(ServiceConfigSchema); +const contractService = new ContractService(config); + +// Deploy contract +const deployment = await contractService.deployContract("user123", { + type: "ERC721", + name: "My NFT Collection", + symbol: "MNC", +}); + +console.log("Deployment queued:", deployment); +``` + +## References + +### Documentation +- [Service Utils Guide](https://portal.thirdweb.com/infrastructure/service-utils) - Complete service utilities guide +- [Authentication Utilities](https://portal.thirdweb.com/infrastructure/auth-utils) - Authentication helper documentation +- [Caching Strategies](https://portal.thirdweb.com/infrastructure/caching) - Caching best practices + +### Platform-Specific Guides +- [Cloudflare Workers Setup](https://portal.thirdweb.com/infrastructure/cloudflare-workers) - Using service-utils in Cloudflare Workers +- [Node.js Integration](https://portal.thirdweb.com/infrastructure/nodejs) - Node.js specific utilities and patterns +- [Docker Deployment](https://portal.thirdweb.com/infrastructure/docker) - Containerized service deployment + +### Integration Examples +- [Service Utils Examples](https://github.com/thirdweb-example/service-utils-examples) - Example implementations +- [Microservice Template](https://github.com/thirdweb-example/microservice-template) - Complete microservice template +- [API Gateway Pattern](https://github.com/thirdweb-example/api-gateway) - API gateway implementation + +### Advanced Topics +- [Error Handling Patterns](https://portal.thirdweb.com/infrastructure/error-handling) - Error handling best practices +- [Logging and Monitoring](https://portal.thirdweb.com/infrastructure/logging) - Structured logging and monitoring +- [Performance Optimization](https://portal.thirdweb.com/infrastructure/performance) - Service performance optimization + +### Related Packages +- [Zod Documentation](https://zod.dev/) - Schema validation library +- [Redis Documentation](https://redis.io/docs) - Redis caching and data structures +- [Bull Queue](https://github.com/OptimalBits/bull) - Job queue processing + +### Community and Support +- [Discord #infrastructure](https://discord.gg/thirdweb) - Infrastructure and backend help +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report service-utils issues +- [Service Uptime](https://status.thirdweb.com/) - thirdweb services status and uptime diff --git a/packages/thirdweb/README.md b/packages/thirdweb/README.md index b959008f41f..8a1c2fc8324 100644 --- a/packages/thirdweb/README.md +++ b/packages/thirdweb/README.md @@ -8,7 +8,22 @@ npm version Build Status

-

All-in-one web3 SDK for Browser, Node and Mobile apps

+ +## Description + +The **thirdweb** SDK is a comprehensive web3 development toolkit that provides everything you need to build decentralized applications. It offers type-safe APIs for smart contract interactions, embedded wallets with social login, account abstraction support, React hooks and UI components, and cross-platform compatibility for web, React Native, and Node.js applications. + +### Key Features + +- **Type-safe APIs**: Fully typed contract and wallet interactions +- **Embedded Wallets**: Social login (Google, Facebook, etc.) and email authentication +- **Account Abstraction**: ERC-4337 smart accounts with gas sponsorship +- **React Integration**: Hooks and UI components for seamless frontend development +- **React Native Support**: Cross-platform mobile app development +- **Automatic ABI Resolution**: Smart contract ABIs resolved automatically +- **IPFS Integration**: Built-in decentralized storage capabilities +- **Multi-chain Support**: Connect to any EVM-compatible blockchain +- **Auth System**: Sign-in with Ethereum (SIWE) support ## Installation @@ -16,40 +31,376 @@ npm install thirdweb ``` -## Features +### For TypeScript Projects +```bash +npm install thirdweb typescript +``` + +### For React Applications +```bash +npm install thirdweb react react-dom +``` + +### For React Native Applications +```bash +npm install thirdweb @thirdweb-dev/react-native-adapter +# Additional React Native dependencies required - see React Native Adapter docs +``` + +## Usage + +### Basic Setup + +#### 1. Create a Thirdweb Client + +```typescript +import { createThirdwebClient } from "thirdweb"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", // Get from thirdweb.com/dashboard +}); +``` + +#### 2. Connect to a Blockchain + +```typescript +import { defineChain } from "thirdweb/chains"; + +// Use a built-in chain +import { ethereum, polygon } from "thirdweb/chains"; + +// Or define a custom chain +const customChain = defineChain({ + id: 1234, + name: "My Custom Chain", + rpc: "https://my-rpc-url.com", +}); +``` + +### React Integration + +#### ThirdwebProvider Setup + +```tsx +import { ThirdwebProvider } from "thirdweb/react"; +import { createThirdwebClient } from "thirdweb"; + +const client = createThirdwebClient({ + clientId: "YOUR_CLIENT_ID", +}); + +function App() { + return ( + + + + ); +} +``` + +#### Connect Wallet Button + +```tsx +import { ConnectButton } from "thirdweb/react"; +import { createWallet } from "thirdweb/wallets"; + +const wallets = [ + createWallet("io.metamask"), + createWallet("com.coinbase.wallet"), + createWallet("walletConnect"), + createWallet("inApp", { + auth: { + options: ["email", "google", "apple", "facebook"], + }, + }), +]; + +function MyComponent() { + return ( + + ); +} +``` + +### Smart Contract Interactions + +#### Reading from a Contract + +```typescript +import { getContract } from "thirdweb"; +import { readContract } from "thirdweb"; +import { ethereum } from "thirdweb/chains"; + +const contract = getContract({ + client, + chain: ethereum, + address: "0x...", +}); + +// Read with automatic ABI resolution +const result = await readContract({ + contract, + method: "function balanceOf(address owner) view returns (uint256)", + params: ["0x..."], +}); +``` + +#### Writing to a Contract + +```typescript +import { prepareContractCall, sendTransaction } from "thirdweb"; +import { useSendTransaction } from "thirdweb/react"; + +// In a React component +function TransferButton() { + const { mutate: sendTransaction } = useSendTransaction(); + + const handleTransfer = async () => { + const transaction = prepareContractCall({ + contract, + method: "function transfer(address to, uint256 amount)", + params: ["0x...", 100n], + }); + + sendTransaction(transaction); + }; + + return ; +} +``` + +### Embedded Wallets (In-App Wallets) + +```typescript +import { createWallet } from "thirdweb/wallets"; + +const embeddedWallet = createWallet("inApp", { + auth: { + options: ["email", "google", "apple", "facebook"], + }, +}); + +// Connect with email +await embeddedWallet.connect({ + client, + strategy: "email", + email: "user@example.com", +}); +``` + +### Account Abstraction (Smart Accounts) + +```typescript +import { createWallet } from "thirdweb/wallets"; + +const smartWallet = createWallet("smart", { + chain: ethereum, + sponsorGas: true, // Enable gas sponsorship +}); + +const personalWallet = createWallet("inApp"); +await personalWallet.connect({ client, strategy: "email", email: "user@example.com" }); -| | thirdweb | Wagmi | Viem | Ethers@6 | -| ----------------------------------------- | -------- | ------------------ | ------------------ | -------- | -| Type safe contract API | βœ… | βœ… | βœ… | βœ… | -| Type safe wallet API | βœ… | βœ… | βœ… | βœ… | -| EVM utils | βœ… | ❌ | βœ… | βœ… | -| RPC for any EVM | βœ…Β  | ⚠️ public RPC only | ⚠️ public RPC only | ❌ | -| Automatic ABI Resolution | βœ… | ❌ | ❌ | ❌ | -| IPFS Upload/Download | βœ… | ❌ | ❌ | ❌ | -| Embedded wallet (email/ social login) | βœ… | ⚠️ via 3rd party | ❌ | ❌ | -| Account abstraction (ERC4337) support | βœ… | ⚠️ via 3rd party | ⚠️ via 3rd party | ❌ | -| Web3 wallet connectors | βœ… | βœ… | ❌ | ❌ | -| Local wallet creation | βœ… | ❌ | βœ… | βœ… | -| Auth (SIWE) | βœ… | ⚠️ via 3rd party | ❌ | ❌ | -| Extensions functions for common standards | βœ… | ❌ | ❌ | ❌ | -| React Hooks | βœ… | βœ… | ❌ | ❌ | -| React UI components | βœ… | ❌ | ❌ | ❌ | -| React Native Hooks | βœ… | ❌ | ❌ | ❌ | -| React Native UI Components | βœ… | ❌ | ❌ | ❌ | +await smartWallet.connect({ + client, + personalWallet, +}); +``` + +### Storage and IPFS + +```typescript +import { upload, download } from "thirdweb/storage"; + +// Upload to IPFS +const file = new File(["content"], "example.txt"); +const uri = await upload({ + client, + files: [file], +}); + +// Download from IPFS +const response = await download({ + client, + uri: "ipfs://...", +}); +``` -## Documentation +### Node.js Backend Usage -Visit [the thirdweb developer portal](https://portal.thirdweb.com/typescript/v5?ref=github.com) to view the full documentation. +```typescript +import { createThirdwebClient } from "thirdweb"; +import { privateKeyToAccount } from "thirdweb/wallets"; + +const client = createThirdwebClient({ + secretKey: "YOUR_SECRET_KEY", // Use secret key for backend +}); + +const account = privateKeyToAccount({ + client, + privateKey: "0x...", +}); + +// Send transactions from backend +const transaction = prepareContractCall({ + contract, + method: "function mint(address to, uint256 amount)", + params: [account.address, 100n], +}); + +const result = await sendTransaction({ + transaction, + account, +}); +``` + +### CLI Usage + +The thirdweb package also includes a CLI for project scaffolding and contract deployment: + +```bash +# Create a new project +npx thirdweb create + +# Deploy contracts +npx thirdweb deploy + +# Generate contract bindings +npx thirdweb generate +``` + +## API Reference + +### Core Functions + +- `createThirdwebClient(options)` - Create a thirdweb client instance +- `getContract(options)` - Get a contract instance for interactions +- `readContract(options)` - Read data from a smart contract +- `prepareContractCall(options)` - Prepare a contract transaction +- `sendTransaction(options)` - Send a prepared transaction + +### React Hooks + +- `useActiveAccount()` - Get the currently connected account +- `useActiveWallet()` - Get the currently connected wallet +- `useReadContract(options)` - Read contract data with caching +- `useSendTransaction()` - Send transactions with loading states +- `useContractEvents(options)` - Listen to contract events + +### React Components + +- `` - Wallet connection button with modal +- `` - Button that executes transactions +- `` - Render NFT media (images, videos, etc.) +- `` - Button that requires wallet connection + +### Wallet Types + +- `"io.metamask"` - MetaMask wallet +- `"com.coinbase.wallet"` - Coinbase Wallet +- `"walletConnect"` - WalletConnect protocol +- `"inApp"` - Embedded wallet with social login +- `"smart"` - Smart account with account abstraction + +## Examples + +### Complete DApp Example + +```tsx +import { ThirdwebProvider, ConnectButton, useActiveAccount, useReadContract } from "thirdweb/react"; +import { createThirdwebClient, getContract } from "thirdweb"; +import { ethereum } from "thirdweb/chains"; + +const client = createThirdwebClient({ clientId: "YOUR_CLIENT_ID" }); + +const contract = getContract({ + client, + chain: ethereum, + address: "0x...", +}); + +function TokenBalance() { + const account = useActiveAccount(); + const { data: balance } = useReadContract({ + contract, + method: "function balanceOf(address owner) view returns (uint256)", + params: [account?.address!], + queryOptions: { enabled: !!account }, + }); + + return
Balance: {balance?.toString()}
; +} + +function App() { + return ( + + + + + ); +} +``` + +### NFT Minting Example + +```tsx +import { prepareContractCall, sendTransaction } from "thirdweb"; +import { upload } from "thirdweb/storage"; + +async function mintNFT() { + // Upload metadata to IPFS + const metadata = { + name: "My NFT", + description: "An awesome NFT", + image: file, // File object + }; + + const uri = await upload({ + client, + files: [metadata], + }); + + // Mint NFT + const transaction = prepareContractCall({ + contract, + method: "function mint(address to, string uri)", + params: [account.address, uri], + }); + + await sendTransaction({ transaction, account }); +} +``` -## Migrating from previous versions +## References -Follow the [migration guide](https://portal.thirdweb.com/typescript/v5/migrate?ref=github.com) to learn how to progrssively upgrade to the unified thirdweb SDK from previous versions. +### Documentation +- [Main Documentation](https://portal.thirdweb.com/typescript/v5) - Complete SDK documentation +- [React Documentation](https://portal.thirdweb.com/typescript/v5/react) - React-specific guides +- [Getting Started Guide](https://portal.thirdweb.com/typescript/v5/getting-started) - Step-by-step setup +- [Migration Guide](https://portal.thirdweb.com/typescript/v5/migrate) - Upgrading from v4 -## Starter kits +### Examples and Templates +- [Starter Templates](https://thirdweb.com/templates) - Ready-to-use project templates +- [Next.js Starter](https://github.com/thirdweb-example/next-starter) - Next.js template +- [Vite Starter](https://github.com/thirdweb-example/vite-starter) - Vite template +- [Code Examples](https://github.com/thirdweb-example) - Example repositories -- [Next.js starter](https://github.com/thirdweb-example/next-starter) -- [Vite starter](https://github.com/thirdweb-example/vite-starter) +### Tools and Services +- [thirdweb Dashboard](https://thirdweb.com/dashboard) - Manage your projects and API keys +- [Contracts Hub](https://thirdweb.com/explore) - Pre-built smart contracts +- [Chain List](https://thirdweb.com/chainlist) - Supported blockchain networks -## Contributing +### Community and Support +- [Discord Community](https://discord.gg/thirdweb) - Join the community +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report bugs and feature requests +- [Support Center](https://thirdweb.com/support) - Get help and support +- [YouTube Channel](https://www.youtube.com/c/thirdweb) - Video tutorials and guides -We welcome contributions from all developers, regardless of experience level. If you are interested in contributing, please read our [Contributing Guide](https://github.com/thirdweb-dev/js/blob/main/.github/contributing.md) where you'll learn how the repo works, how to test your changes, and how to submit a pull request. +### Additional Resources +- [Blog](https://blog.thirdweb.com/) - Latest news and tutorials +- [Twitter](https://twitter.com/thirdweb) - Follow for updates +- [Changelog](https://portal.thirdweb.com/changelog) - Latest features and fixes diff --git a/packages/vault-sdk/README.md b/packages/vault-sdk/README.md index 610166b5fb5..0f41b6e2e17 100644 --- a/packages/vault-sdk/README.md +++ b/packages/vault-sdk/README.md @@ -1,5 +1,637 @@ # Vault SDK -This package contains utilities to interact with Vault, thirdweb's key management servive. +## Description -[View documentation](https://portal.thirdweb.com/vault) +The **@thirdweb-dev/vault-sdk** package provides a TypeScript SDK for interacting with thirdweb's Vault service, a secure key management solution for web3 applications. Vault offers enterprise-grade security for managing private keys, signing transactions, and handling sensitive cryptographic operations without exposing private keys to your application code. + +### Key Features + +- **Secure Key Management**: Store and manage private keys in a secure, isolated environment +- **Multi-Signature Support**: Configure multi-signature wallets for enhanced security +- **Hardware Security Modules (HSM)**: Integration with hardware-based security modules +- **Key Derivation**: Hierarchical deterministic (HD) wallet support with BIP-32/BIP-44 +- **Transaction Signing**: Sign transactions without exposing private keys +- **Access Control**: Role-based access control and permission management +- **Audit Logging**: Complete audit trail of all cryptographic operations +- **Cross-Platform**: Works in Node.js, browser, and React Native environments + +## Installation + +```bash +npm install @thirdweb-dev/vault-sdk +``` + +### Prerequisites + +To use the Vault SDK, you need: + +1. **Vault Service Access**: Access to a thirdweb Vault instance +2. **Authentication Credentials**: Valid JWT tokens or API keys +3. **Vault Configuration**: Properly configured vault policies and access permissions + +## Usage + +### Basic Setup + +#### 1. Initialize Vault Client + +```typescript +import { createVaultClient } from "@thirdweb-dev/vault-sdk"; + +const vaultClient = createVaultClient({ + vaultUrl: "https://vault.thirdweb.com", // Your Vault instance URL + accessToken: "your-jwt-token", // JWT token for authentication +}); +``` + +#### 2. Alternative Setup with API Key + +```typescript +import { createVaultClient } from "@thirdweb-dev/vault-sdk"; + +const vaultClient = createVaultClient({ + vaultUrl: "https://vault.thirdweb.com", + apiKey: "your-api-key", + organizationId: "your-org-id", +}); +``` + +### Key Management + +#### Create New Wallet + +```typescript +import { generateWallet } from "@thirdweb-dev/vault-sdk"; + +const wallet = await generateWallet(vaultClient, { + name: "My Secure Wallet", + description: "Primary wallet for production use", + keyType: "secp256k1", // or "ed25519" + metadata: { + environment: "production", + purpose: "primary-signer", + }, +}); + +console.log("Wallet created:", { + id: wallet.id, + address: wallet.address, + publicKey: wallet.publicKey, +}); +``` + +#### Import Existing Wallet + +```typescript +import { importWallet } from "@thirdweb-dev/vault-sdk"; + +const importedWallet = await importWallet(vaultClient, { + name: "Imported Wallet", + privateKey: "0x...", // Private key to import + encryptionKey: "your-encryption-key", // Optional additional encryption +}); +``` + +#### List Wallets + +```typescript +import { listWallets } from "@thirdweb-dev/vault-sdk"; + +const wallets = await listWallets(vaultClient, { + limit: 50, + offset: 0, + filter: { + keyType: "secp256k1", + status: "active", + }, +}); + +console.log("Available wallets:", wallets); +``` + +### Transaction Signing + +#### Sign Transaction + +```typescript +import { signTransaction } from "@thirdweb-dev/vault-sdk"; + +const signature = await signTransaction(vaultClient, { + walletId: "wallet-id-123", + transaction: { + to: "0x742d35Cc06C94a2E0b2dE76D63CB8d35e3Ae1B1a", + value: "1000000000000000000", // 1 ETH in wei + data: "0x", // Contract call data + gasLimit: "21000", + gasPrice: "20000000000", // 20 gwei + nonce: 42, + chainId: 1, // Ethereum mainnet + }, + approvalType: "automatic", // or "manual" for multi-sig +}); + +console.log("Transaction signed:", signature); +``` + +#### Sign Message + +```typescript +import { signMessage } from "@thirdweb-dev/vault-sdk"; + +const messageSignature = await signMessage(vaultClient, { + walletId: "wallet-id-123", + message: "Hello, Web3!", + encoding: "utf8", // or "hex" +}); + +console.log("Message signature:", messageSignature); +``` + +#### Sign Typed Data (EIP-712) + +```typescript +import { signTypedData } from "@thirdweb-dev/vault-sdk"; + +const typedDataSignature = await signTypedData(vaultClient, { + walletId: "wallet-id-123", + domain: { + name: "MyDApp", + version: "1", + chainId: 1, + verifyingContract: "0x...", + }, + types: { + Transfer: [ + { name: "from", type: "address" }, + { name: "to", type: "address" }, + { name: "amount", type: "uint256" }, + ], + }, + value: { + from: "0x...", + to: "0x...", + amount: "1000000000000000000", + }, +}); +``` + +### Multi-Signature Wallets + +#### Create Multi-Sig Wallet + +```typescript +import { createMultiSigWallet } from "@thirdweb-dev/vault-sdk"; + +const multiSigWallet = await createMultiSigWallet(vaultClient, { + name: "Treasury Multi-Sig", + signers: [ + { address: "0x...", weight: 1 }, + { address: "0x...", weight: 1 }, + { address: "0x...", weight: 2 }, // Higher weight for admin + ], + threshold: 2, // Require 2 signatures + policy: { + requireAllForHighValue: true, + highValueThreshold: "10000000000000000000", // 10 ETH + }, +}); +``` + +#### Submit Transaction for Approval + +```typescript +import { submitTransactionProposal } from "@thirdweb-dev/vault-sdk"; + +const proposal = await submitTransactionProposal(vaultClient, { + multiSigWalletId: "multisig-wallet-id", + transaction: { + to: "0x...", + value: "5000000000000000000", // 5 ETH + data: "0x", + }, + description: "Treasury payout for Q4 operations", + executionDeadline: Date.now() + 7 * 24 * 60 * 60 * 1000, // 7 days +}); + +console.log("Proposal submitted:", proposal.id); +``` + +#### Approve Transaction + +```typescript +import { approveTransaction } from "@thirdweb-dev/vault-sdk"; + +await approveTransaction(vaultClient, { + proposalId: "proposal-id-123", + signature: "optional-signature-if-required", + comment: "Approved for Q4 operations", +}); +``` + +### HD Wallet Support + +#### Create HD Wallet + +```typescript +import { createHDWallet } from "@thirdweb-dev/vault-sdk"; + +const hdWallet = await createHDWallet(vaultClient, { + name: "HD Master Wallet", + entropy: "high", // Security level + derivationPath: "m/44'/60'/0'/0", // Ethereum standard path + seedPhraseBackup: { + enabled: true, + encryptionKey: "backup-encryption-key", + }, +}); +``` + +#### Derive Child Wallet + +```typescript +import { deriveChildWallet } from "@thirdweb-dev/vault-sdk"; + +const childWallet = await deriveChildWallet(vaultClient, { + parentWalletId: "hd-master-wallet-id", + derivationPath: "m/44'/60'/0'/0/5", // 6th account + name: "User Account 5", +}); +``` + +### Access Control and Policies + +#### Create Access Policy + +```typescript +import { createAccessPolicy } from "@thirdweb-dev/vault-sdk"; + +const policy = await createAccessPolicy(vaultClient, { + name: "Production Signing Policy", + rules: [ + { + resource: "wallet:*", + actions: ["read", "sign"], + conditions: { + ipAllowlist: ["192.168.1.0/24"], + timeWindow: { + start: "09:00", + end: "17:00", + timezone: "UTC", + }, + }, + }, + { + resource: "wallet:high-value-*", + actions: ["sign"], + conditions: { + requireMultiApproval: true, + maxTransactionValue: "1000000000000000000", // 1 ETH + }, + }, + ], +}); +``` + +#### Assign Policy to User + +```typescript +import { assignPolicy } from "@thirdweb-dev/vault-sdk"; + +await assignPolicy(vaultClient, { + userId: "user-123", + policyId: policy.id, + validUntil: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days +}); +``` + +### Audit and Monitoring + +#### Get Audit Logs + +```typescript +import { getAuditLogs } from "@thirdweb-dev/vault-sdk"; + +const auditLogs = await getAuditLogs(vaultClient, { + startTime: Date.now() - 24 * 60 * 60 * 1000, // Last 24 hours + endTime: Date.now(), + walletId: "wallet-id-123", // Optional filter + action: "sign", // Optional filter + limit: 100, +}); + +console.log("Recent signing activities:", auditLogs); +``` + +#### Set Up Monitoring Alerts + +```typescript +import { createAlert } from "@thirdweb-dev/vault-sdk"; + +const alert = await createAlert(vaultClient, { + name: "High Value Transaction Alert", + conditions: { + transactionValue: { + greaterThan: "5000000000000000000", // > 5 ETH + }, + frequency: { + threshold: 5, + timeWindow: "1h", // 5 transactions in 1 hour + }, + }, + notifications: [ + { + type: "email", + recipients: ["security@company.com"], + }, + { + type: "webhook", + url: "https://api.company.com/vault-alerts", + }, + ], +}); +``` + +## Configuration Options + +### Client Configuration + +```typescript +import { createVaultClient } from "@thirdweb-dev/vault-sdk"; + +const client = createVaultClient({ + vaultUrl: "https://vault.thirdweb.com", + accessToken: "jwt-token", + + // Optional configuration + timeout: 30000, // Request timeout + retries: 3, // Number of retries + retryDelay: 1000, // Delay between retries + + // TLS configuration for self-hosted instances + tls: { + rejectUnauthorized: true, + certificatePath: "/path/to/cert.pem", + }, + + // Logging configuration + logging: { + level: "info", // debug, info, warn, error + redactSensitiveData: true, + }, +}); +``` + +### Security Configuration + +```typescript +const secureClient = createVaultClient({ + vaultUrl: "https://vault.thirdweb.com", + accessToken: "jwt-token", + + // Enhanced security options + security: { + encryptionAtRest: true, + encryptionInTransit: true, + keyRotationInterval: "30d", + sessionTimeout: "15m", + + // Hardware security module settings + hsm: { + enabled: true, + provider: "aws-cloudhsm", // or "azure-keyvault" + keyId: "hsm-key-id", + }, + }, +}); +``` + +## API Reference + +### Core Functions + +- `createVaultClient(config)` - Initialize Vault client +- `generateWallet(client, options)` - Create new wallet +- `importWallet(client, options)` - Import existing wallet +- `listWallets(client, options)` - List available wallets +- `deleteWallet(client, walletId)` - Securely delete wallet + +### Signing Functions + +- `signTransaction(client, options)` - Sign blockchain transaction +- `signMessage(client, options)` - Sign arbitrary message +- `signTypedData(client, options)` - Sign EIP-712 typed data +- `batchSign(client, operations)` - Sign multiple operations atomically + +### Multi-Signature Functions + +- `createMultiSigWallet(client, options)` - Create multi-sig wallet +- `submitTransactionProposal(client, options)` - Submit transaction for approval +- `approveTransaction(client, options)` - Approve pending transaction +- `rejectTransaction(client, options)` - Reject pending transaction + +### HD Wallet Functions + +- `createHDWallet(client, options)` - Create HD master wallet +- `deriveChildWallet(client, options)` - Derive child wallet +- `getDerivationPath(client, walletId)` - Get wallet derivation path + +### Access Control Functions + +- `createAccessPolicy(client, policy)` - Create access policy +- `assignPolicy(client, assignment)` - Assign policy to user +- `revokePolicy(client, assignment)` - Revoke policy assignment + +## Examples + +### Enterprise Wallet Service + +```typescript +import { + createVaultClient, + generateWallet, + signTransaction, + createAccessPolicy +} from "@thirdweb-dev/vault-sdk"; + +class EnterpriseWalletService { + private vaultClient; + + constructor(vaultUrl: string, accessToken: string) { + this.vaultClient = createVaultClient({ + vaultUrl, + accessToken, + security: { + encryptionAtRest: true, + sessionTimeout: "15m", + }, + }); + } + + async createUserWallet(userId: string, userRole: string) { + // Create wallet for user + const wallet = await generateWallet(this.vaultClient, { + name: `Wallet for ${userId}`, + metadata: { + userId, + userRole, + createdAt: new Date().toISOString(), + }, + }); + + // Create appropriate access policy + const policy = await createAccessPolicy(this.vaultClient, { + name: `${userRole} Policy for ${userId}`, + rules: this.getPolicyRulesForRole(userRole), + }); + + // Assign policy to user + await assignPolicy(this.vaultClient, { + userId, + policyId: policy.id, + }); + + return wallet; + } + + async executeSecureTransaction(walletId: string, transaction: any) { + try { + const signature = await signTransaction(this.vaultClient, { + walletId, + transaction, + approvalType: "automatic", + }); + + return { + success: true, + signature, + timestamp: new Date().toISOString(), + }; + } catch (error) { + console.error("Transaction signing failed:", error); + throw error; + } + } + + private getPolicyRulesForRole(role: string) { + const baseRules = [ + { + resource: "wallet:own", + actions: ["read", "sign"], + conditions: { + maxTransactionValue: "1000000000000000000", // 1 ETH + }, + }, + ]; + + if (role === "admin") { + baseRules.push({ + resource: "wallet:*", + actions: ["read", "sign", "manage"], + conditions: { + requireMultiApproval: true, + }, + }); + } + + return baseRules; + } +} +``` + +### DeFi Integration with Multi-Sig + +```typescript +import { + createMultiSigWallet, + submitTransactionProposal, + approveTransaction +} from "@thirdweb-dev/vault-sdk"; + +class DeFiMultiSigManager { + private vaultClient; + private treasuryWalletId: string; + + constructor(vaultClient: any) { + this.vaultClient = vaultClient; + } + + async initializeTreasury() { + const treasuryWallet = await createMultiSigWallet(this.vaultClient, { + name: "DeFi Treasury", + signers: [ + { address: "0x...", weight: 1, role: "cto" }, + { address: "0x...", weight: 1, role: "cfo" }, + { address: "0x...", weight: 2, role: "ceo" }, + ], + threshold: 2, + policy: { + requireAllForHighValue: true, + highValueThreshold: "50000000000000000000", // 50 ETH + dailyLimit: "10000000000000000000", // 10 ETH per day + }, + }); + + this.treasuryWalletId = treasuryWallet.id; + return treasuryWallet; + } + + async proposeYieldFarmingInvestment( + protocolAddress: string, + amount: string, + description: string + ) { + const proposal = await submitTransactionProposal(this.vaultClient, { + multiSigWalletId: this.treasuryWalletId, + transaction: { + to: protocolAddress, + value: "0", + data: this.encodeStakeTransaction(amount), + }, + description: `Yield farming investment: ${description}`, + category: "defi-investment", + riskLevel: "medium", + executionDeadline: Date.now() + 48 * 60 * 60 * 1000, // 48 hours + }); + + return proposal; + } + + private encodeStakeTransaction(amount: string): string { + // Encode the staking transaction data + // This would typically use a library like ethers.js + return "0x..."; // Encoded transaction data + } +} +``` + +## References + +### Documentation +- [Vault Documentation](https://portal.thirdweb.com/vault) - Complete Vault guide +- [Key Management Best Practices](https://portal.thirdweb.com/vault/security) - Security guidelines +- [Multi-Signature Setup](https://portal.thirdweb.com/vault/multisig) - Multi-sig configuration + +### Security Resources +- [Vault Security Model](https://portal.thirdweb.com/vault/security-model) - Understanding Vault's security architecture +- [Access Control Guide](https://portal.thirdweb.com/vault/access-control) - Setting up permissions and policies +- [Audit Logging](https://portal.thirdweb.com/vault/audit-logs) - Monitoring and compliance + +### Integration Examples +- [Vault Examples](https://github.com/thirdweb-example/vault-examples) - Example implementations +- [Enterprise Integration](https://github.com/thirdweb-example/vault-enterprise) - Enterprise use cases +- [DeFi Integration](https://github.com/thirdweb-example/vault-defi) - DeFi protocol integration + +### Advanced Topics +- [Hardware Security Modules](https://portal.thirdweb.com/vault/hsm) - HSM integration +- [Key Derivation](https://portal.thirdweb.com/vault/hd-wallets) - HD wallet implementation +- [Disaster Recovery](https://portal.thirdweb.com/vault/disaster-recovery) - Backup and recovery procedures + +### API References +- [Vault API Reference](https://vault-api.thirdweb.com/docs) - Complete API documentation +- [Authentication Guide](https://portal.thirdweb.com/vault/authentication) - Authentication methods +- [Webhook Integration](https://portal.thirdweb.com/vault/webhooks) - Real-time notifications + +### Community and Support +- [Discord #vault](https://discord.gg/thirdweb) - Vault specific help +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report Vault SDK issues +- [Security Disclosures](mailto:security@thirdweb.com) - Report security vulnerabilities diff --git a/packages/wagmi-adapter/README.md b/packages/wagmi-adapter/README.md index 9b513578fbf..50b87385159 100644 --- a/packages/wagmi-adapter/README.md +++ b/packages/wagmi-adapter/README.md @@ -1,3 +1,579 @@ # Wagmi Adapter -This package enables the use of thirdweb's in-app wallets with wagmi. +## Description + +The **@thirdweb-dev/wagmi-adapter** package provides a seamless integration layer that enables you to use thirdweb's powerful in-app wallets and smart account features within the wagmi ecosystem. This adapter allows developers to leverage thirdweb's embedded wallets, social login capabilities, and account abstraction while maintaining compatibility with the extensive wagmi tooling and ecosystem. + +### Key Features + +- **Wagmi Integration**: Use thirdweb wallets as wagmi connectors +- **In-App Wallets**: Social login (Google, Facebook, Apple) and email authentication in wagmi apps +- **Smart Accounts**: Account abstraction (ERC-4337) support with gas sponsorship +- **Type Safety**: Full TypeScript support with wagmi's type system +- **Ecosystem Compatibility**: Works with all wagmi-compatible tools and libraries +- **Seamless Migration**: Easy integration into existing wagmi applications + +## Installation + +```bash +npm install @thirdweb-dev/wagmi-adapter @wagmi/core thirdweb +``` + +### Peer Dependencies + +The wagmi adapter requires these peer dependencies: + +```bash +npm install @wagmi/core@^2.16.0 thirdweb@^5.85.0 +``` + +For React applications, also install: + +```bash +npm install wagmi @tanstack/react-query +``` + +## Usage + +### Basic Setup + +#### 1. Configure Wagmi with Thirdweb Wallets + +```typescript +import { createConfig, http } from '@wagmi/core' +import { mainnet, polygon } from '@wagmi/core/chains' +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' + +// Create thirdweb client +import { createThirdwebClient } from 'thirdweb' + +const thirdwebClient = createThirdwebClient({ + clientId: 'YOUR_CLIENT_ID', +}) + +// Configure wagmi with thirdweb wallets +const config = createConfig({ + chains: [mainnet, polygon], + connectors: [ + // Add thirdweb in-app wallet as wagmi connector + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { + options: ['email', 'google', 'apple', 'facebook'], + }, + }), + // Add smart wallet connector + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'smart', + sponsorGas: true, + }), + ], + transports: { + [mainnet.id]: http(), + [polygon.id]: http(), + }, +}) +``` + +#### 2. React Integration + +```tsx +import { WagmiProvider } from 'wagmi' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { config } from './wagmi-config' + +const queryClient = new QueryClient() + +function App() { + return ( + + + + + + ) +} +``` + +### Wallet Connection Examples + +#### In-App Wallet with Social Login + +```typescript +import { connect } from '@wagmi/core' +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' + +const inAppConnector = thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { + options: ['email', 'google', 'apple', 'facebook'], + }, +}) + +// Connect with email +await connect(config, { + connector: inAppConnector, + authOptions: { + strategy: 'email', + email: 'user@example.com', + }, +}) + +// Connect with Google +await connect(config, { + connector: inAppConnector, + authOptions: { + strategy: 'google', + }, +}) +``` + +#### Smart Account Setup + +```typescript +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' + +const smartAccountConnector = thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'smart', + sponsorGas: true, // Enable gas sponsorship + factoryAddress: '0x...', // Optional: custom factory + accountSalt: 'unique-salt', // Optional: deterministic addresses +}) + +await connect(config, { + connector: smartAccountConnector, + personalWallet: inAppConnector, // Use in-app wallet as signer +}) +``` + +### React Hooks Usage + +#### Connection Management + +```tsx +import { useConnect, useDisconnect, useAccount } from 'wagmi' + +function WalletConnection() { + const { connectors, connect } = useConnect() + const { disconnect } = useDisconnect() + const { address, isConnected } = useAccount() + + const thirdwebConnectors = connectors.filter( + connector => connector.id.startsWith('thirdweb') + ) + + return ( +
+ {isConnected ? ( +
+

Connected: {address}

+ +
+ ) : ( +
+ {thirdwebConnectors.map((connector) => ( + + ))} +
+ )} +
+ ) +} +``` + +#### Contract Interactions + +```tsx +import { useReadContract, useWriteContract } from 'wagmi' +import { parseEther } from 'viem' + +const contractConfig = { + address: '0x...', + abi: [ + { + name: 'balanceOf', + type: 'function', + stateMutability: 'view', + inputs: [{ name: 'owner', type: 'address' }], + outputs: [{ name: '', type: 'uint256' }], + }, + { + name: 'transfer', + type: 'function', + stateMutability: 'nonpayable', + inputs: [ + { name: 'to', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + outputs: [{ name: '', type: 'bool' }], + }, + ], +} as const + +function TokenInteraction() { + const { address } = useAccount() + + const { data: balance } = useReadContract({ + ...contractConfig, + functionName: 'balanceOf', + args: [address!], + query: { enabled: !!address }, + }) + + const { writeContract, isPending } = useWriteContract() + + const handleTransfer = () => { + writeContract({ + ...contractConfig, + functionName: 'transfer', + args: ['0x...', parseEther('1')], + }) + } + + return ( +
+

Balance: {balance?.toString()}

+ +
+ ) +} +``` + +### Advanced Configuration + +#### Custom Connector Configuration + +```typescript +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' + +const customConnector = thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { + options: ['email', 'google'], + // Custom auth configuration + redirectUrl: 'https://myapp.com/auth', + loginUrl: 'https://myapp.com/login', + }, + // Wallet display options + metadata: { + name: 'My App Wallet', + description: 'Secure wallet for My App', + url: 'https://myapp.com', + icons: ['https://myapp.com/icon.png'], + }, +}) +``` + +#### Multi-Chain Smart Accounts + +```typescript +import { mainnet, polygon, arbitrum } from '@wagmi/core/chains' + +const createSmartAccountConnector = (chainId: number) => + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'smart', + chain: chainId, + sponsorGas: true, + factoryAddress: getFactoryAddress(chainId), + }) + +const config = createConfig({ + chains: [mainnet, polygon, arbitrum], + connectors: [ + // In-app wallet for signing + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { options: ['email', 'google'] }, + }), + // Smart accounts for each chain + createSmartAccountConnector(mainnet.id), + createSmartAccountConnector(polygon.id), + createSmartAccountConnector(arbitrum.id), + ], + transports: { + [mainnet.id]: http(), + [polygon.id]: http(), + [arbitrum.id]: http(), + }, +}) +``` + +### Migration from Wagmi Connectors + +#### Replace Existing Connectors + +```typescript +// Before: Standard wagmi connectors +import { metaMask, walletConnect } from '@wagmi/connectors' + +const oldConfig = createConfig({ + connectors: [ + metaMask(), + walletConnect({ projectId: 'YOUR_PROJECT_ID' }), + ], +}) + +// After: Enhanced with thirdweb capabilities +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' + +const newConfig = createConfig({ + connectors: [ + metaMask(), // Keep existing connectors + walletConnect({ projectId: 'YOUR_PROJECT_ID' }), + // Add thirdweb enhanced wallets + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { options: ['email', 'google', 'apple'] }, + }), + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'smart', + sponsorGas: true, + }), + ], +}) +``` + +## API Reference + +### thirdwebWalletConnect + +Main function to create thirdweb wallet connectors for wagmi. + +```typescript +function thirdwebWalletConnect(options: ThirdwebWalletOptions): Connector +``` + +#### Options + +```typescript +interface ThirdwebWalletOptions { + client: ThirdwebClient + walletId: 'inApp' | 'smart' | string + chain?: number + auth?: { + options: AuthOption[] + redirectUrl?: string + loginUrl?: string + } + sponsorGas?: boolean + factoryAddress?: string + accountSalt?: string + metadata?: { + name: string + description?: string + url?: string + icons?: string[] + } +} +``` + +#### Auth Options + +- `'email'` - Email-based authentication +- `'google'` - Google OAuth +- `'apple'` - Apple OAuth +- `'facebook'` - Facebook OAuth +- `'discord'` - Discord OAuth +- `'twitter'` - Twitter OAuth + +### Connector Methods + +```typescript +// Standard wagmi connector interface +connector.connect(options?) +connector.disconnect() +connector.getAccount() +connector.getChainId() +connector.switchChain(chainId) +``` + +## Examples + +### Complete wagmi + thirdweb Application + +```tsx +import { createConfig, http } from '@wagmi/core' +import { mainnet, polygon } from '@wagmi/core/chains' +import { WagmiProvider, useAccount, useConnect, useReadContract } from 'wagmi' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { thirdwebWalletConnect } from '@thirdweb-dev/wagmi-adapter' +import { createThirdwebClient } from 'thirdweb' + +const thirdwebClient = createThirdwebClient({ + clientId: 'YOUR_CLIENT_ID', +}) + +const config = createConfig({ + chains: [mainnet, polygon], + connectors: [ + thirdwebWalletConnect({ + client: thirdwebClient, + walletId: 'inApp', + auth: { + options: ['email', 'google'], + }, + }), + ], + transports: { + [mainnet.id]: http(), + [polygon.id]: http(), + }, +}) + +const queryClient = new QueryClient() + +function WalletStatus() { + const { address, isConnected } = useAccount() + const { connect, connectors } = useConnect() + + if (isConnected) { + return
Connected: {address}
+ } + + return ( +
+ {connectors.map((connector) => ( + + ))} +
+ ) +} + +function TokenBalance() { + const { address } = useAccount() + + const { data: balance } = useReadContract({ + address: '0xA0b86a33E6441e13C7C95C5D6b55b7cE06eB6a9D', // USDC + abi: [ + { + name: 'balanceOf', + type: 'function', + stateMutability: 'view', + inputs: [{ name: 'account', type: 'address' }], + outputs: [{ name: '', type: 'uint256' }], + }, + ], + functionName: 'balanceOf', + args: [address!], + query: { enabled: !!address }, + }) + + return
USDC Balance: {balance?.toString()}
+} + +export default function App() { + return ( + + +
+

Wagmi + thirdweb Example

+ + +
+
+
+ ) +} +``` + +### Smart Account with Gas Sponsorship + +```tsx +import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi' + +function GaslessTransaction() { + const { + writeContract, + data: hash, + isPending + } = useWriteContract() + + const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ + hash, + }) + + const handleMint = async () => { + // This transaction will be sponsored (no gas required) + writeContract({ + address: '0x...', + abi: [ + { + name: 'mint', + type: 'function', + inputs: [ + { name: 'to', type: 'address' }, + { name: 'amount', type: 'uint256' }, + ], + }, + ], + functionName: 'mint', + args: ['0x...', 1000000000000000000n], // 1 token + }) + } + + return ( +
+ + {isSuccess &&
Transaction successful!
} +
+ ) +} +``` + +## References + +### Documentation +- [Wagmi Documentation](https://wagmi.sh/) - Official wagmi docs +- [thirdweb wagmi Integration](https://portal.thirdweb.com/typescript/v5/wagmi) - Integration guide +- [Wagmi Connectors Guide](https://wagmi.sh/core/api/connectors) - Understanding wagmi connectors + +### Examples and Templates +- [wagmi + thirdweb Template](https://github.com/thirdweb-example/wagmi-starter) - Complete example +- [Smart Account wagmi Example](https://github.com/thirdweb-example/smart-wallet-wagmi) - Account abstraction +- [Multi-chain wagmi App](https://github.com/thirdweb-example/multi-chain-wagmi) - Cross-chain functionality + +### Related Libraries +- [@wagmi/core](https://www.npmjs.com/package/@wagmi/core) - Core wagmi functionality +- [@tanstack/react-query](https://www.npmjs.com/package/@tanstack/react-query) - Data fetching for React +- [viem](https://www.npmjs.com/package/viem) - Low-level Ethereum library + +### Advanced Topics +- [Custom Connectors](https://wagmi.sh/dev/creating-connectors) - Creating custom wagmi connectors +- [Account Abstraction Guide](https://portal.thirdweb.com/wallet/smart-wallet) - Understanding smart accounts +- [Gas Sponsorship Setup](https://portal.thirdweb.com/engine/features/gasless-transactions) - Configuring gasless transactions + +### Community and Support +- [wagmi Discord](https://discord.gg/wagmi) - wagmi community support +- [thirdweb Discord](https://discord.gg/thirdweb) - thirdweb specific help +- [GitHub Issues](https://github.com/thirdweb-dev/js/issues) - Report integration issues