Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/wallet/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
parseConnectorNames as parseConnectorNamesCsv,
parseWalletChainNames,
rpcEnvNameFromChainName,
splitCsv,
validateBrowserUrl,
type SupportedWalletChainName,
type WalletConnectorName,
Expand Down Expand Up @@ -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.',
)
}
Expand Down
53 changes: 4 additions & 49 deletions lib/wallet/connectors.ts
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 1 addition & 1 deletion lib/wallet/validation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/wallet/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down
33 changes: 33 additions & 0 deletions test/wallet-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function setEnv(overrides: Record<string, string | undefined>): 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',
Expand Down Expand Up @@ -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 ─────────────────────────────────────────────────
Expand Down
11 changes: 11 additions & 0 deletions test/wallet-connectors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"/)
Expand Down