WDK logoWDK documentation

Candide Smart Deposit Addresses Configuration

Configure API access, recovery withdrawal, deployment verification, and caching for Candide forwarding addresses.

Community modules are developed and maintained independently by third-party contributors.

Tether and the WDK Team do not endorse or assume responsibility for their code, security, or maintenance. Use your own judgment and proceed at your own risk.

Configure CandideForwardingProtocol with an optional WDK account and the Forwarding Address API URL from the Candide dashboard. This page documents @candidelabs/wdk-protocol-sda-candide@1.0.0-beta.1; see installation.

Configuration Fields

FieldTypeRequirementDefaultEffect
apiUrlstringRequiredNoneForwarding Address API URL shown in the Candide dashboard; used verbatim for JSON-RPC requests and contains the team API key for usage and billing.
policySecretstringRequired for creation, renewal, and reactivationNoneSent as a bearer token for activation requests. Keep it on the server.
recoveryWithdrawerstringOptionalRecipientEVM wallet with time-delayed withdrawal rights. A per-call value overrides this default.
verifyAddressesbooleanOptionaltrueCompare the created address with local derivation. Renewal also checks stored derivation inputs when the API supplies the relayer.
deployParamsPartial<CandideDeployParams>OptionalPackage pins plus API-reported relayerOverride deployment inputs. Supplying allowedRelayer skips the deployment API call.
deployParamsTtlMsnumberOptional600000Milliseconds to cache the API-reported deployment inputs and relayer.
routesCacheTtlMsnumberOptional600000Milliseconds to cache routes separately for each source chain.

The module validates the API URL as a non-empty string, rather than checking its origin or scheme. Use the Forwarding Address HTTPS API URL shown in the dashboard and protect it according to your team's API-key policy. A cache TTL of 0 prevents reuse on subsequent calls. Cached route data does not make estimates binding.

Client and Server Credentials

A client instance can discover routes, estimate deposits, derive addresses, and read forwarding history without a forwarding policy secret. The API URL identifies your team for usage and billing. Its team API key cannot activate addresses or move funds, so the URL can be used client-side. Rotate the key in the dashboard if it leaks. Keep the forwarding policy secret on the server.

Only your server should hold policySecret. Validate the requesting user and their intended recipient before calling creation or renewal endpoints, and do not accept an unrestricted recipient from an unauthenticated request. Check wallet control separately: EVM address syntax does not prove ownership or the ability to recover funds.

You can construct a server instance using environment-backed credentials and a validated recovery wallet:

import CandideForwardingProtocol from '@candidelabs/wdk-protocol-sda-candide'

const apiUrl = process.env.CANDIDE_FORWARDING_API_URL
const policySecret = process.env.CANDIDE_FORWARDING_POLICY_SECRET
const recoveryWithdrawer = process.env.CANDIDE_RECOVERY_WITHDRAWER

if (!apiUrl || new URL(apiUrl).protocol !== 'https:') {
  throw new Error('Configure the dashboard HTTPS API URL')
}
if (!policySecret) throw new Error('Configure the server policy secret')
if (!recoveryWithdrawer || !/^0x[0-9a-fA-F]{40}$/.test(recoveryWithdrawer)
  || recoveryWithdrawer.toLowerCase() === '0x0000000000000000000000000000000000000000') {
  throw new Error('Configure a valid recovery wallet')
}

const sda = new CandideForwardingProtocol(undefined, {
  apiUrl,
  policySecret,
  recoveryWithdrawer,
})

Keep policySecret out of source files, screenshots, client bundles, and logs. Avoid logging the full API URL or using a real team key in public examples. Route application requests through an authenticated backend if your team's API-key policy requires the URL to remain private.

Recipient and Recovery Withdrawer

The optional constructor account accepts a full or read-only WDK account. Its EVM address becomes the default recipient when destinationAddress is omitted. A full signing account is not required by the module's API operations.

The recovery wallet selection follows this order:

  1. The call's recoveryWithdrawer.
  2. The constructor configuration's recoveryWithdrawer.
  3. The resolved recipient address.

Candide calls the recovery withdrawer custodialWithdrawer in its API and contracts. The SDK handles that mapping. The recipient can withdraw any token immediately by sending a transaction on the source chain. The recovery withdrawer can withdraw after a 48-hour timelock that the recipient can cancel. If the recipient cannot transact there, such as an exchange-controlled address or a smart account not deployed on that chain, configure a recovery withdrawer that can. The SDK does not expose withdrawal or cancellation methods.

Store the recipient, destination chain, recovery withdrawer, salt, and returned descriptor. Changing those address inputs creates a different address. Keep the salt stable for each user or order whose deposits you attribute to that address. Renewal reuses the stored inputs rather than the current constructor defaults.

Deployment Verification

getDeployParams() returns the derivation inputs:

FieldMeaning
factoryForwarding address factory contract.
singletonDelegate target embedded in the proxy; Candide uses a beacon.
proxyCreationCodeProxy creation bytecode.
allowedRelayerRelayer allowed to trigger forwarding.
versionOptional provider deployment identifier.

The package pins factory, singleton, and proxyCreationCode. Without overrides, it compares those fields with the API before using the API's relayer. A mismatch throws DEPLOYMENT_CHANGED.

An overridden deployment field is no longer compared with the API. Supplying allowedRelayer skips the deployment API call entirely. Use overrides only after independently verifying the deployment; do not use them to silence an unexplained mismatch.

deriveDepositAddress() becomes offline when deployParams.allowedRelayer is supplied. Creation still sends an activation request. verifyAddresses: false skips local derivation comparison during creation; renewal always rejects a different address returned by activation.

Candide administers the upgradeable beacon. Address verification checks derivation inputs and the resulting address; it does not inspect the beacon's current implementation code or prevent future upgrades. It also does not undo a remote activation: ADDRESS_MISMATCH can be thrown after the API has activated its returned address. Do not fund either address while investigating.

Next Steps


Need Help?

On this page