diff --git a/.env.example b/.env.example index ce4ec8799..b410bf3fd 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,12 @@ # MAIN XMTP_ENV="dev" # xmtp environment (dev,production,local,multinode) LOGGING_LEVEL="error" # rust library logs + +# D14N MODE (V4) +# Set both to enable D14N mode: +# XMTP_D14N="true" # Enable D14N mode +# XMTP_API_URL="https://grpc.testnet-staging.xmtp.network:443" # D14N gateway URL + +# V3 MODE (default) +# Set only XMTP_API_URL without XMTP_D14N to use custom V3 endpoint: +# XMTP_API_URL="https://custom-v3-endpoint.example.com" diff --git a/helpers/versions.ts b/helpers/versions.ts index 5b805c4ea..8c7972e82 100644 --- a/helpers/versions.ts +++ b/helpers/versions.ts @@ -161,6 +161,15 @@ export const checkNoNameContains = (versionList: typeof VersionList) => { } }; +/** + * Check if D14N mode is enabled via environment variable + * Set XMTP_D14N=true to enable D14N mode + */ +export const isD14NEnabled = (): boolean => { + const d14nEnv = process.env.XMTP_D14N; + return d14nEnv === "true" || d14nEnv === "1"; +}; + export const regressionClient = async ( nodeBindings: string, walletKey: `0x${string}`, @@ -171,12 +180,6 @@ export const regressionClient = async ( ): Promise => { const loggingLevel = (process.env.LOGGING_LEVEL || "warn") as unknown as LogLevel; - const apiUrl = apiURL; - if (apiUrl) { - console.debug( - `Creating API client with: SDK version: ${nodeBindings} walletKey: ${String(walletKey)} API URL: ${String(apiUrl)}`, - ); - } // Ensure the database directory exists const dbDir = path.dirname(dbPath); @@ -193,18 +196,40 @@ export const regressionClient = async ( const signer = createSigner(walletKey); + // Check if D14N mode is explicitly enabled + const d14nEnabled = isD14NEnabled(); + const apiUrl = apiURL || process.env.XMTP_API_URL; + + const clientOptions: any = { + dbEncryptionKey, + dbPath, + env: env as unknown as XmtpEnv, + loggingLevel, + appVersion: APP_VERSION, + disableDeviceSync: true, + codecs: [new ReactionCodec(), new ReplyCodec()], + }; + + // D14N mode: Use d14nHost parameter + // V3 mode: Use apiUrl parameter (or default endpoints) + if (d14nEnabled) { + if (!apiUrl) { + throw new Error( + "XMTP_D14N=true requires XMTP_API_URL to be set with the D14N gateway URL", + ); + } + clientOptions.d14nHost = apiUrl; + console.log(`[D14N] Using D14N gateway: ${apiUrl}`); + } else if (apiUrl) { + clientOptions.apiUrl = apiUrl; + console.log(`[V3] Using custom API URL: ${apiUrl}`); + } else { + console.log(`[V3] Using default network endpoint for env: ${env}`); + } + try { - // @ts-expect-error - TODO: fix this - client = await ClientClass.create(signer, { - dbEncryptionKey, - dbPath, - env: env as unknown as XmtpEnv, - loggingLevel, - apiUrl, - appVersion: APP_VERSION, - disableDeviceSync: true, - codecs: [new ReactionCodec(), new ReplyCodec()], - }); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + client = await ClientClass.create(signer as any, clientOptions); } catch (error) { // If database file is corrupted, try using a different path if ( @@ -222,17 +247,24 @@ export const regressionClient = async ( console.debug(`Using alternative database path: ${alternativeDbPath}`); // Try to create the client with the alternative path - // @ts-expect-error - TODO: fix this - client = await ClientClass.create(signer, { + const retryOptions: any = { dbEncryptionKey, dbPath: alternativeDbPath, env, loggingLevel, - apiUrl, appVersion: APP_VERSION, disableDeviceSync: true, codecs: [new ReactionCodec(), new ReplyCodec()], - }); + }; + + if (d14nEnabled && apiUrl) { + retryOptions.d14nHost = apiUrl; + } else if (apiUrl) { + retryOptions.apiUrl = apiUrl; + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + client = await ClientClass.create(signer as any, retryOptions); } else { throw error; } diff --git a/workers/manager.ts b/workers/manager.ts index e2890f3a3..ca160c649 100644 --- a/workers/manager.ts +++ b/workers/manager.ts @@ -153,8 +153,9 @@ export class WorkerManager implements IWorkerManager { for (const worker of this.getAll()) { const groups = await worker.client.conversations.list(); await Promise.all( - groups.flat().map(async (g) => { - const debugInfo = await g.debugInfo(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + groups.flat().map(async (g: any) => { + const debugInfo = await (g as Group).debugInfo(); if (debugInfo.maybeForked || debugInfo.isCommitLogForked) { throw new Error( `${forkDetectedString} Stopping test, group id ${g.id} may have forked`, @@ -450,12 +451,15 @@ export class WorkerManager implements IWorkerManager { encryptionKey, }; + // Use provided apiUrl, or fallback to XMTP_API_URL environment variable + const effectiveApiUrl = apiUrl || process.env.XMTP_API_URL; + // Create and initialize the worker const workerClient = new WorkerClient( workerData, this.env, {}, - apiUrl, + effectiveApiUrl, undefined, );