UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

104 lines 3.5 kB
import { ApiKeyStamper } from '@turnkey/api-key-stamper'; import { TurnkeyServerClient } from '@turnkey/sdk-server'; import { deepCopy, rootLogger } from '@hyperlane-xyz/utils'; const logger = rootLogger.child({ module: 'sdk:turnkey-client' }); /** * Extract safe error message from error object * Avoids logging sensitive data like API keys, stack traces, etc. * Handles TurnkeyActivityError, TurnkeyRequestError, and standard Error types */ function getSafeErrorMessage(error) { if (error instanceof Error) { return error.message; } return 'Unknown error'; } /** * Log Turnkey operation error safely without exposing sensitive data * Accepts unknown errors from catch blocks and safely extracts error messages */ export function logTurnkeyError(operation, error) { const errorMessage = getSafeErrorMessage(error); logger.error(`${operation}:`, errorMessage); } /** * Validate that a Turnkey activity completed successfully * The Turnkey SDK polls internally until the activity completes or max retries are reached. * If we receive a non-completed status, it indicates an SDK bug or request error. */ export function validateTurnkeyActivityCompleted(activity, operationType) { if (activity.status !== 'ACTIVITY_STATUS_COMPLETED') { throw new Error(`${operationType} activity did not complete. Status: ${activity.status}`); } } /** * Default Turnkey API base URL */ export const DEFAULT_TURNKEY_API_BASE_URL = 'https://api.turnkey.com'; /** * Shared Turnkey client manager * Handles initialization, health checks, and provides access to the Turnkey client * * This class is used by all VM-specific signers via composition rather than inheritance, * allowing each signer to extend/implement their VM-specific base classes while * still sharing common Turnkey functionality. * * @example * ```typescript * const manager = new TurnkeyClientManager(config); * await manager.healthCheck(); * const client = manager.getClient(); * ``` */ export class TurnkeyClientManager { client; config; constructor(config) { this.config = config; const stamper = new ApiKeyStamper({ apiPublicKey: config.apiPublicKey, apiPrivateKey: config.apiPrivateKey, }); this.client = new TurnkeyServerClient({ organizationId: config.organizationId, stamper, apiBaseUrl: config.apiBaseUrl || DEFAULT_TURNKEY_API_BASE_URL, }); } /** * Get a copy of the configuration (for creating new signer instances) */ getConfig() { return deepCopy(this.config); } /** * Get the Turnkey client (for signing operations) */ getClient() { return this.client; } /** * Get organization ID */ getOrganizationId() { return this.config.organizationId; } /** * Check if Turnkey is properly configured and accessible */ async healthCheck() { try { logger.debug('Running Turnkey health check...'); const whoami = await this.client.getWhoami({ organizationId: this.config.organizationId, }); logger.debug(`Turnkey health check passed. Organization ID: ${whoami.organizationId}`); return true; } catch (error) { logTurnkeyError('Turnkey health check failed', error); return false; } } } //# sourceMappingURL=turnkeyClient.js.map