Problem Statement
Developers using the Radix dApp Toolkit cannot configure a custom Radix Connect Relay server URL. The relay base URL (https://radix-connect-relay.radixdlt.com) and wallet deep link URL (radixWallet://connect) are hardcoded. This prevents developers from running self-hosted relay infrastructure or pointing to alternative relay environments during development and testing.
The wallet also has no way to know which relay server the dApp is using, because the relay URL is not included in the request metadata. If a developer were to hack around the hardcoded URL on the dApp side, the wallet would still post responses to the default relay server, breaking the round trip.
Solution
Allow developers to configure the Radix Connect Relay server URL (and wallet deep link URL) via a new optional radixConnectRelay config object on RadixDappToolkitOptions. The configured relay base URL is:
- Used by the dApp's relay transport to poll for wallet responses (replacing the hardcoded value)
- Included in the wallet request metadata as a
relayUrl field, so the wallet knows where to post its encrypted responses
When the config is not provided, the current default URLs are used, making this a fully backward-compatible change.
User Stories
- As a dApp developer, I want to configure a custom relay server URL, so that I can use self-hosted relay infrastructure
- As a dApp developer, I want the wallet to know which relay server my dApp uses, so that the wallet posts responses to the correct server
- As a dApp developer, I want sensible defaults when I don't configure a relay URL, so that existing integrations continue to work without changes
- As a dApp developer, I want to configure the wallet deep link URL, so that I can target alternative wallet builds during development
- As a dApp developer, I want to provide relay configuration at the top-level toolkit options, so that I don't have to understand the internal module structure
- As a dApp developer, I want the relay URL to appear in every wallet interaction's metadata, so that the wallet can always determine the correct relay server regardless of transport
- As a wallet implementor, I want to read the relay URL from the request metadata, so that I can post encrypted responses to the correct relay server
- As a wallet implementor, I want the metadata version to remain at 2, so that the new field is treated as an additive backward-compatible change and older wallets are not broken
Implementation Decisions
Config API
A new optional field radixConnectRelay is added to OptionalRadixDappToolkitOptions:
radixConnectRelay?: {
baseUrl: string // Relay server URL (default: 'https://radix-connect-relay.radixdlt.com')
walletUrl: string // Wallet deep link URL (default: 'radixWallet://connect')
}
Metadata Schema
A new required field relayUrl: string is added to the Metadata valibot schema. It is always populated — either with the developer-provided value or the default. The metadata version stays at 2 (additive, backward-compatible change).
API Contract: dApp Toolkit ↔ Wallet
The WalletInteraction is the wire format exchanged between the dApp and the wallet. The metadata object within it is changing.
Before:
{
"interactionId": "abc-123",
"metadata": {
"version": 2,
"networkId": 1,
"dAppDefinitionAddress": "account_rdx...",
"origin": "https://my-dapp.com"
},
"items": { ... }
}
After:
{
"interactionId": "abc-123",
"metadata": {
"version": 2,
"networkId": 1,
"dAppDefinitionAddress": "account_rdx...",
"origin": "https://my-dapp.com",
"relayUrl": "https://radix-connect-relay.radixdlt.com"
},
"items": { ... }
}
Contract details:
relayUrl is always present in the metadata (never omitted)
- Contains the base URL only (e.g.,
https://radix-connect-relay.radixdlt.com), not the versioned API path (/api/v1)
- The wallet should use this URL to determine where to post its encrypted response
- If the wallet does not recognize the
relayUrl field (older wallet versions), it falls back to its own hardcoded default — this is the backward-compatible path
- The
version field remains 2 — this is an additive change, not a breaking one
Plumbing Path
The config flows through existing module boundaries with no new modules:
RadixDappToolkit reads options.radixConnectRelay, resolves defaults
- Passes the resolved
baseUrl and walletUrl to WalletRequestModule
WalletRequestModule fans out:
baseUrl and walletUrl to RadixConnectRelayModule (transport-side, replacing hardcoded values)
relayUrl (the baseUrl) to WalletRequestSdk (metadata-side)
WalletRequestSdk bakes relayUrl into the Metadata object attached to every WalletInteraction
No New Modules
RadixConnectRelayModule already accepts baseUrl and walletUrl as constructor params. The change is purely about threading configurable values instead of hardcoded ones.
Testing Decisions
Tests should focus on config plumbing — verifying that a relay URL configured at the top flows correctly to both the metadata and the transport layer. Tests should verify external behavior (the metadata object contents, the URLs reaching the relay module) rather than internal wiring details.
Modules to test
- Metadata schema: Validate that the
Metadata schema accepts and requires relayUrl
- Config-to-metadata plumbing: Given
radixConnectRelay.baseUrl at the toolkit level, verify the correct relayUrl appears in the WalletInteraction metadata
- Default behavior: When no
radixConnectRelay config is provided, verify the default relay URL appears in metadata
- Transport plumbing: Verify the configured URLs reach the
RadixConnectRelayModule
Prior art
schemas.spec.ts — valibot schema validation tests using parse()
wallet-request.spec.ts — integration tests using WalletRequestModule with TestingTransportModule and mock WalletRequestSdk
radix-dapp-toolkit.spec.ts — top-level bootstrap test
A new dedicated test file should be added for relay URL configuration tests, following the patterns in wallet-request.spec.ts.
Out of Scope
- Wallet-side implementation of reading and using the
relayUrl from metadata
- Configurability of other transport parameters (polling interval, encryption settings)
- Making the connector extension transport configurable
- Migration tooling or version negotiation for the metadata change
Further Notes
- The
requestInterceptor hook already allows developers to modify the entire WalletInteraction before sending, which could theoretically be used to inject a relayUrl. However, this is fragile (bypasses schema validation, requires knowledge of internals) and doesn't affect the relay transport's polling URL. A first-class config option is the correct approach.
Problem Statement
Developers using the Radix dApp Toolkit cannot configure a custom Radix Connect Relay server URL. The relay base URL (
https://radix-connect-relay.radixdlt.com) and wallet deep link URL (radixWallet://connect) are hardcoded. This prevents developers from running self-hosted relay infrastructure or pointing to alternative relay environments during development and testing.The wallet also has no way to know which relay server the dApp is using, because the relay URL is not included in the request metadata. If a developer were to hack around the hardcoded URL on the dApp side, the wallet would still post responses to the default relay server, breaking the round trip.
Solution
Allow developers to configure the Radix Connect Relay server URL (and wallet deep link URL) via a new optional
radixConnectRelayconfig object onRadixDappToolkitOptions. The configured relay base URL is:relayUrlfield, so the wallet knows where to post its encrypted responsesWhen the config is not provided, the current default URLs are used, making this a fully backward-compatible change.
User Stories
Implementation Decisions
Config API
A new optional field
radixConnectRelayis added toOptionalRadixDappToolkitOptions:Metadata Schema
A new required field
relayUrl: stringis added to theMetadatavalibot schema. It is always populated — either with the developer-provided value or the default. The metadataversionstays at2(additive, backward-compatible change).API Contract: dApp Toolkit ↔ Wallet
The
WalletInteractionis the wire format exchanged between the dApp and the wallet. Themetadataobject within it is changing.Before:
{ "interactionId": "abc-123", "metadata": { "version": 2, "networkId": 1, "dAppDefinitionAddress": "account_rdx...", "origin": "https://my-dapp.com" }, "items": { ... } }After:
{ "interactionId": "abc-123", "metadata": { "version": 2, "networkId": 1, "dAppDefinitionAddress": "account_rdx...", "origin": "https://my-dapp.com", "relayUrl": "https://radix-connect-relay.radixdlt.com" }, "items": { ... } }Contract details:
relayUrlis always present in the metadata (never omitted)https://radix-connect-relay.radixdlt.com), not the versioned API path (/api/v1)relayUrlfield (older wallet versions), it falls back to its own hardcoded default — this is the backward-compatible pathversionfield remains2— this is an additive change, not a breaking onePlumbing Path
The config flows through existing module boundaries with no new modules:
RadixDappToolkitreadsoptions.radixConnectRelay, resolves defaultsbaseUrlandwalletUrltoWalletRequestModuleWalletRequestModulefans out:baseUrlandwalletUrltoRadixConnectRelayModule(transport-side, replacing hardcoded values)relayUrl(thebaseUrl) toWalletRequestSdk(metadata-side)WalletRequestSdkbakesrelayUrlinto theMetadataobject attached to everyWalletInteractionNo New Modules
RadixConnectRelayModulealready acceptsbaseUrlandwalletUrlas constructor params. The change is purely about threading configurable values instead of hardcoded ones.Testing Decisions
Tests should focus on config plumbing — verifying that a relay URL configured at the top flows correctly to both the metadata and the transport layer. Tests should verify external behavior (the metadata object contents, the URLs reaching the relay module) rather than internal wiring details.
Modules to test
Metadataschema accepts and requiresrelayUrlradixConnectRelay.baseUrlat the toolkit level, verify the correctrelayUrlappears in theWalletInteractionmetadataradixConnectRelayconfig is provided, verify the default relay URL appears in metadataRadixConnectRelayModulePrior art
schemas.spec.ts— valibot schema validation tests usingparse()wallet-request.spec.ts— integration tests usingWalletRequestModulewithTestingTransportModuleand mockWalletRequestSdkradix-dapp-toolkit.spec.ts— top-level bootstrap testA new dedicated test file should be added for relay URL configuration tests, following the patterns in
wallet-request.spec.ts.Out of Scope
relayUrlfrom metadataFurther Notes
requestInterceptorhook already allows developers to modify the entireWalletInteractionbefore sending, which could theoretically be used to inject arelayUrl. However, this is fragile (bypasses schema validation, requires knowledge of internals) and doesn't affect the relay transport's polling URL. A first-class config option is the correct approach.