From 062cd462222bc1e0f2b05717d24530b2d108ccca Mon Sep 17 00:00:00 2001 From: waterWang Date: Wed, 29 Jul 2026 19:50:05 +0800 Subject: [PATCH] feat: add WalletConnect connector support (#298) - Add 'walletConnect' to SUPPORTED_CONNECTOR_NAMES in validation.js - Update validation.d.ts type to include 'walletConnect' - Fix connectors.ts: remove corrupted local declaration, re-export from validation.js - Fix config.ts: add missing splitCsv import, replace fail() with throw ConfigError - Add WalletConnect parsing and config tests Closes #298 --- lib/wallet/config.ts | 3 +- lib/wallet/connectors.ts | 53 +++------------------------------- lib/wallet/validation.d.ts | 2 +- lib/wallet/validation.js | 2 +- test/wallet-config.test.ts | 33 +++++++++++++++++++++ test/wallet-connectors.test.ts | 11 +++++++ 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/lib/wallet/config.ts b/lib/wallet/config.ts index 59d8318..28a03b6 100644 --- a/lib/wallet/config.ts +++ b/lib/wallet/config.ts @@ -11,6 +11,7 @@ import { parseConnectorNames as parseConnectorNamesCsv, parseWalletChainNames, rpcEnvNameFromChainName, + splitCsv, validateBrowserUrl, type SupportedWalletChainName, type WalletConnectorName, @@ -134,7 +135,7 @@ function buildConnectors(connectorNames: readonly WalletConnectorName[]): Create case 'walletConnect': { const projectId = env('NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID') if (!projectId) { - fail( + throw new ConfigError( 'NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID is required when using the walletConnect connector.', ) } diff --git a/lib/wallet/connectors.ts b/lib/wallet/connectors.ts index 58696dd..46bcea5 100644 --- a/lib/wallet/connectors.ts +++ b/lib/wallet/connectors.ts @@ -1,63 +1,18 @@ /** * lib/wallet/connectors.ts * - * Parsing and validation for NEXT_PUBLIC_WALLET_CONNECTORS, kept free of - * wagmi imports so it can be unit tested. lib/wallet/config.ts maps the - * validated names to actual wagmi connector factories. + * Re-exports from the compiled validation layer (validation.js). + * TypeScript types are resolved via validation.d.ts. * * To add support for a new connector (e.g. walletConnect): - * 1. Add its name to SUPPORTED_CONNECTOR_NAMES below. + * 1. Add its name to SUPPORTED_CONNECTOR_NAMES in validation.js and validation.d.ts. * 2. Handle it in buildConnectors() in lib/wallet/config.ts. * 3. Document it in README.md ("Wallet connectors") and .env.example. */ - -import { ConfigError } from '../config' - -export const SUPPORTED_CONNECTOR_NAMESinjected', 'walletConnect'] as const - -export type WalletConnectorName = (typeof SUPPORTED_CONNECTOR_NAMES)[number] - -export const CONNECTOR_DOCS_URL = - 'https://github.com/Adamantine-Guild/guildpass-integrations#wallet-connectors' - -export function unsupportedConnectorMessage(name: string): string { - return [ - `NEXT_PUBLIC_WALLET_CONNECTORS contains unsupported connector "${name}".`, - '', - ` Supported values: ${SUPPORTED_CONNECTOR_NAMES.join(', ')}.`, - '', - ' To add support for a new connector, see the "Wallet connectors"', - ` section of the README (${CONNECTOR_DOCS_URL})`, - ' and extend lib/wallet/config.ts.', - ].join('\n') -} - -/** - * Parse the comma-separated NEXT_PUBLIC_WALLET_CONNECTORS value into a list - * of supported connector names. Defaults to ['injected'] when unset/empty; - * throws a ConfigError naming the offending value for anything unsupported. - */ -export function parseConnectorNames( - csv: string | undefined, -): readonly WalletConnectorName[] { - const configuredNames = - csv - ?.split(',') - .map((part) => part.trim()) - .filter(Boolean) ?? [] - const names = configuredNames.length > 0 ? configuredNames : ['injected'] - - return names.map((name) => { - if (!(SUPPORTED_CONNECTOR_NAMES as readonly string[]).includes(name)) { - throw new ConfigError(unsupportedConnectorMessage(name)) - } - return name as WalletConnectorName - }) -} export { CONNECTOR_DOCS_URL, SUPPORTED_CONNECTOR_NAMES, parseConnectorNames, unsupportedConnectorMessage, } from './validation.js' -export type { WalletConnectorName } from './validation.js' +export type { WalletConnectorName } from './validation.js' \ No newline at end of file diff --git a/lib/wallet/validation.d.ts b/lib/wallet/validation.d.ts index 783c506..8c62e20 100644 --- a/lib/wallet/validation.d.ts +++ b/lib/wallet/validation.d.ts @@ -3,7 +3,7 @@ export const SUPPORTED_CHAIN_NAMES: readonly ['mainnet', 'base', 'sepolia'] export type SupportedWalletChainName = (typeof SUPPORTED_CHAIN_NAMES)[number] -export const SUPPORTED_CONNECTOR_NAMES: readonly ['injected'] +export const SUPPORTED_CONNECTOR_NAMES: readonly ['injected', 'walletConnect'] export type WalletConnectorName = (typeof SUPPORTED_CONNECTOR_NAMES)[number] export const CONNECTOR_DOCS_URL: string diff --git a/lib/wallet/validation.js b/lib/wallet/validation.js index d2b7c2a..a5b64ae 100644 --- a/lib/wallet/validation.js +++ b/lib/wallet/validation.js @@ -2,7 +2,7 @@ const { ConfigError } = require('../config-validation.js') const DEFAULT_CHAIN_NAMES = Object.freeze(['mainnet', 'base', 'sepolia']) const SUPPORTED_CHAIN_NAMES = DEFAULT_CHAIN_NAMES -const SUPPORTED_CONNECTOR_NAMES = Object.freeze(['injected']) +const SUPPORTED_CONNECTOR_NAMES = Object.freeze(['injected', 'walletConnect']) const CONNECTOR_DOCS_URL = 'https://github.com/Adamantine-Guild/guildpass-integrations#wallet-connectors' diff --git a/test/wallet-config.test.ts b/test/wallet-config.test.ts index 66192ca..0db99ee 100644 --- a/test/wallet-config.test.ts +++ b/test/wallet-config.test.ts @@ -61,6 +61,7 @@ function setEnv(overrides: Record): void { const walletKeys = [ 'NEXT_PUBLIC_WALLET_CHAINS', 'NEXT_PUBLIC_WALLET_CONNECTORS', + 'NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID', 'NEXT_PUBLIC_WALLET_RPC_MAINNET', 'NEXT_PUBLIC_WALLET_RPC_BASE', 'NEXT_PUBLIC_WALLET_RPC_SEPOLIA', @@ -383,6 +384,38 @@ describe('NEXT_PUBLIC_WALLET_CONNECTORS — valid connector', () => { assert.deepEqual(config.connectorNames, ['injected']) assert.equal(config.connectors.length, 1) }) + + test('accepts "walletConnect" explicitly and reflects it in connectorNames', () => { + setEnv({ + NEXT_PUBLIC_WALLET_CONNECTORS: 'walletConnect', + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: 'test-project-id', + }) + const config = loadWalletConfig() + assert.deepEqual(config.connectorNames, ['walletConnect']) + assert.equal(config.connectors.length, 1) + }) + + test('accepts "injected,walletConnect" combined', () => { + setEnv({ + NEXT_PUBLIC_WALLET_CONNECTORS: 'injected,walletConnect', + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: 'test-project-id', + }) + const config = loadWalletConfig() + assert.deepEqual(config.connectorNames, ['injected', 'walletConnect']) + assert.equal(config.connectors.length, 2) + }) + + test('rejects walletConnect without NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID', () => { + setEnv({ NEXT_PUBLIC_WALLET_CONNECTORS: 'walletConnect' }) + assert.throws( + () => loadWalletConfig(), + (err: Error) => { + assert.equal(err.name, 'ConfigError') + assert.ok(err.message.includes('NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID')) + return true + }, + ) + }) }) // ── RPC URL: transport wiring ───────────────────────────────────────────────── diff --git a/test/wallet-connectors.test.ts b/test/wallet-connectors.test.ts index 259e5df..1d8f9a9 100644 --- a/test/wallet-connectors.test.ts +++ b/test/wallet-connectors.test.ts @@ -58,6 +58,17 @@ describe('NEXT_PUBLIC_WALLET_CONNECTORS parsing', () => { ) }) + test('accepts the supported "walletConnect" value', () => { + assert.deepEqual(parseConnectorNames('walletConnect'), ['walletConnect']) + }) + + test('accepts "injected,walletConnect" combined', () => { + assert.deepEqual(parseConnectorNames('injected,walletConnect'), [ + 'injected', + 'walletConnect', + ]) + }) + test('unsupportedConnectorMessage interpolates the supported list', () => { const message = unsupportedConnectorMessage('safe') assert.match(message, /"safe"/)