UNPKG

@coinbase/cdp-sdk

Version:

SDK for interacting with the Coinbase Developer Platform Wallet API

154 lines (134 loc) 4.31 kB
import { generateWalletJwt, generateJwt } from "./jwt.js"; import { version } from "../../version.js"; /** * Options for generating authentication headers for API requests. */ export interface GetAuthHeadersOptions { /** * The API key ID * * Examples: * 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' * 'organizations/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/apiKeys/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' */ apiKeyId: string; /** * The API key secret * * Examples: * 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==' (Edwards key (Ed25519)) * '-----BEGIN EC PRIVATE KEY-----\n...\n...\n...==\n-----END EC PRIVATE KEY-----\n' (EC key (ES256)) */ apiKeySecret: string; /** * The HTTP method for the request (e.g. 'GET', 'POST') */ requestMethod: string; /** * The host for the request (e.g. 'api.cdp.coinbase.com') */ requestHost: string; /** * The path for the request (e.g. '/platform/v1/wallets') */ requestPath: string; /** * Optional request body data */ requestBody?: unknown; /** * The Wallet Secret for wallet authentication */ walletSecret?: string; /** * The source identifier for the request */ source?: string; /** * The version of the source making the request */ sourceVersion?: string; /** * Optional expiration time in seconds (defaults to 120) */ expiresIn?: number; /** * Optional audience claim for the JWT */ audience?: string[]; } /** * Gets authentication headers for a request. * * @param options - The configuration options for generating auth headers * @returns Object containing the authentication headers */ export async function getAuthHeaders( options: GetAuthHeadersOptions, ): Promise<Record<string, string>> { const headers: Record<string, string> = {}; // Generate and add JWT token const jwt = await generateJwt({ apiKeyId: options.apiKeyId, apiKeySecret: options.apiKeySecret, requestMethod: options.requestMethod, requestHost: options.requestHost, requestPath: options.requestPath, expiresIn: options.expiresIn, audience: options.audience, }); headers["Authorization"] = `Bearer ${jwt}`; headers["Content-Type"] = "application/json"; // Add wallet auth if needed if (requiresWalletAuth(options.requestMethod, options.requestPath)) { if (!options.walletSecret) { throw new Error( "Wallet Secret not configured. Please set the CDP_WALLET_SECRET environment variable, or pass it as an option to the CdpClient constructor.", ); } const walletAuthToken = await generateWalletJwt({ walletSecret: options.walletSecret, requestMethod: options.requestMethod, requestHost: options.requestHost, requestPath: options.requestPath, requestData: options.requestBody || {}, }); headers["X-Wallet-Auth"] = walletAuthToken; } // Add correlation data headers["Correlation-Context"] = getCorrelationData(options.source, options.sourceVersion); return headers; } /** * Returns true if the request indicated by the method and URL requires wallet authentication. * * @param requestMethod - The HTTP method of the request * @param requestPath - The URL path of the request * @returns True if the request requires wallet authentication, false otherwise */ function requiresWalletAuth(requestMethod: string, requestPath: string): boolean { return ( (requestPath?.includes("/accounts") || requestPath?.includes("/spend-permissions")) && (requestMethod === "POST" || requestMethod === "DELETE" || requestMethod === "PUT") ); } /** * Returns encoded correlation data including the SDK version and language. * * @param source - The source identifier for the request * @param sourceVersion - The version of the source making the request * @returns Encoded correlation data as a query string */ export function getCorrelationData(source?: string, sourceVersion?: string): string { const data = { sdk_version: version, sdk_language: "typescript", source: source || "sdk-auth", }; if (sourceVersion) { data["source_version"] = sourceVersion; } return Object.keys(data) .map(key => `${key}=${encodeURIComponent(data[key])}`) .join(","); }