@phantom/embedded-provider-core
Version:
Platform-agnostic embedded provider core logic for Phantom Wallet SDK
350 lines (266 loc) • 9.33 kB
Markdown
# /embedded-provider-core
Platform-agnostic embedded provider core logic for Phantom Wallet SDK.
## Overview
This package contains the core business logic for Phantom's embedded wallet provider, designed to be shared across different platforms (browser, React Native, etc.). It provides a unified interface for wallet operations while allowing platform-specific implementations through adapters.
## Architecture
The embedded provider core follows a platform adapter pattern:
```
┌─────────────────────────────────────┐
│ Platform SDK │
│ (browser-sdk, react-native) │
└─────────────┬───────────────────────┘
│
┌─────────────▼───────────────────────┐
│ EmbeddedProvider (Core) │
│ - Authentication flows │
│ - Session management │
│ - Wallet operations │
│ - Business logic │
└─────────────┬───────────────────────┘
│
┌─────────────▼───────────────────────┐
│ Platform Adapters │
│ - Storage (IndexedDB/AsyncStorage) │
│ - Auth (redirects/deep links) │
│ - URL params (window/linking) │
│ - Logger (debug/console) │
└─────────────────────────────────────┘
```
## Key Features
- **Cross-platform compatibility**: Share 90%+ of wallet logic across platforms
- **Clean separation of concerns**: Platform-specific code isolated in adapters
- **Multiple auth flows**: JWT, Google OAuth, Apple OAuth, app-wallet creation
- **Session management**: Persistent sessions with validation and recovery
- **Retry logic**: Built-in retry with exponential backoff for network operations
- **Type safety**: Full TypeScript support with comprehensive interfaces
## Usage
### Basic Setup
```typescript
import {
EmbeddedProvider,
EmbeddedProviderConfig,
PlatformAdapter,
DebugLogger,
} from "@phantom/embedded-provider-core";
// 1. Define your configuration
const config: EmbeddedProviderConfig = {
apiBaseUrl: "https://api.phantom.app",
organizationId: "your-org-id",
embeddedWalletType: "user-wallet", // or 'app-wallet'
addressTypes: ["solana", "ethereum"],
solanaProvider: "web3js",
authOptions: {
authUrl: "https://auth.phantom.app",
redirectUrl: "https://your-app.com/callback",
},
};
// 2. Implement platform adapters (see examples below)
const platform: PlatformAdapter = {
storage: new YourStorageAdapter(),
authProvider: new YourAuthProvider(),
urlParamsAccessor: new YourURLParamsAccessor(),
};
// 3. Implement logger
const logger: DebugLogger = new YourLogger();
// 4. Create provider instance
const provider = new EmbeddedProvider(config, platform, logger);
// 5. Use the provider
const result = await provider.connect();
console.log("Connected addresses:", result.addresses);
```
## Platform Adapter Interfaces
### Storage Adapter
Handles persistent session storage:
```typescript
import { EmbeddedStorage, Session } from "@phantom/embedded-provider-core";
export class YourStorageAdapter implements EmbeddedStorage {
async getSession(): Promise<Session | null> {
// Platform-specific session retrieval
// Browser: IndexedDB, React Native: AsyncStorage
}
async saveSession(session: Session): Promise<void> {
// Platform-specific session storage
}
async clearSession(): Promise<void> {
// Platform-specific session cleanup
}
}
```
### Auth Provider
Handles authentication flows:
```typescript
import { AuthProvider, AuthResult, PhantomConnectOptions, JWTAuthOptions } from "@phantom/embedded-provider-core";
export class YourAuthProvider implements AuthProvider {
async authenticate(options: PhantomConnectOptions | JWTAuthOptions): Promise<void | AuthResult> {
// Platform-specific authentication
// Browser: window redirects, React Native: deep links
}
resumeAuthFromRedirect?(): AuthResult | null {
// Resume authentication after redirect/deep link
}
}
```
### URL Params Accessor
Handles URL parameter access:
```typescript
import { URLParamsAccessor } from "@phantom/embedded-provider-core";
export class YourURLParamsAccessor implements URLParamsAccessor {
getParam(key: string): string | null {
// Platform-specific URL parameter access
// Browser: window.location.search, React Native: Linking.getInitialURL()
}
}
```
### Debug Logger
Handles logging:
```typescript
import { DebugLogger } from "@phantom/embedded-provider-core";
export class YourLogger implements DebugLogger {
info(category: string, message: string, data?: any): void {
// Platform-specific logging
}
warn(category: string, message: string, data?: any): void {
// Platform-specific warning
}
error(category: string, message: string, data?: any): void {
// Platform-specific error logging
}
log(category: string, message: string, data?: any): void {
// Platform-specific debug logging
}
}
```
## Authentication Flows
### JWT Authentication
For server-side authenticated users:
```typescript
const authOptions = {
provider: "jwt",
jwtToken: "your-jwt-token",
customAuthData: { userId: "user123" },
};
const result = await provider.connect(authOptions);
```
### OAuth Authentication
For social login flows:
```typescript
// Google OAuth
const authOptions = {
provider: "google",
customAuthData: { referrer: "landing-page" },
};
await provider.connect(authOptions); // Will redirect/deep link
// Apple OAuth
const authOptions = {
provider: "apple",
};
await provider.connect(authOptions); // Will redirect/deep link
```
### App Wallet
For application-controlled wallets:
```typescript
const config = {
// ... other config
embeddedWalletType: "app-wallet",
};
const result = await provider.connect(); // No auth needed
```
## Session Management
Sessions are automatically managed by the core provider:
```typescript
// Check connection status
if (provider.isConnected()) {
const addresses = provider.getAddresses();
console.log("Available addresses:", addresses);
}
// Sign a message
const signature = await provider.signMessage({
message: "Hello, world!",
networkId: "solana:mainnet",
});
// Sign and send transaction
const result = await provider.signAndSendTransaction({
transaction: transactionBytes,
networkId: "solana:mainnet",
});
// Disconnect
await provider.disconnect();
```
## Error Handling
The core provider provides detailed error messages:
```typescript
try {
await provider.connect();
} catch (error) {
if (error.message.includes("JWT")) {
// Handle JWT authentication errors
} else if (error.message.includes("Storage")) {
// Handle storage errors
} else if (error.message.includes("Network")) {
// Handle network errors
}
}
```
## Configuration Options
```typescript
interface EmbeddedProviderConfig {
// Required
apiBaseUrl: string; // Phantom API base URL
organizationId: string; // Your organization ID
embeddedWalletType: "app-wallet" | "user-wallet";
addressTypes: [AddressType, ...AddressType[]]; // Supported blockchain addresses
// Optional
solanaProvider?: "web3js" | "kit"; // Solana library preference
authOptions?: {
authUrl?: string; // Custom auth URL
redirectUrl?: string; // OAuth redirect URL
};
}
```
## Session Object
```typescript
interface Session {
sessionId: string; // Unique session identifier
walletId: string; // Phantom wallet ID
organizationId: string; // Organization ID
keypair: {
// Cryptographic keypair
publicKey: string;
secretKey: string;
};
authProvider: string; // Auth method used
userInfo: Record<string, any>; // User information
status: "pending" | "completed"; // Session status
createdAt: number; // Creation timestamp
lastUsed: number; // Last access timestamp
}
```
## Best Practices
1. **Platform Adapters**: Keep platform-specific code in adapters only
2. **Error Handling**: Always handle authentication and network errors
3. **Session Validation**: The core automatically validates sessions
4. **Logging**: Use structured logging with categories for debugging
5. **Security**: Never log sensitive data like private keys
## Examples
See the `/browser-sdk` package for a complete implementation example using this core package with browser-specific adapters.
## Development
```bash
# Install dependencies
yarn install
# Build the package
yarn build
# Run tests
yarn test
# Run linting
yarn lint
# Format code
yarn prettier
```
## Contributing
This package is designed to be extended for new platforms. When adding support for a new platform:
1. Implement all required platform adapter interfaces
2. Add comprehensive tests for your adapters
3. Update documentation with platform-specific examples
4. Ensure error handling covers platform-specific edge cases
## License
MIT