Skip to content

Document Candide smart deposit addresses - #283

Open
ihsraham wants to merge 2 commits into
developfrom
feat/candide-sda-docs
Open

ihsraham wants to merge 2 commits into
developfrom
feat/candide-sda-docs

Conversation

@ihsraham

@ihsraham ihsraham commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Adds overview, usage, configuration and API reference pages for @candidelabs/wdk-protocol-sda-candide@1.0.0-beta.1, plus SDA navigation, module catalogs, the October 5 release entry and refreshed LLM feeds. The docs cover deterministic forwarding addresses, activation expiry, non-binding estimates, delivery tracking, recovery rights and beacon upgrade trust.

Source: the published release commit and exact npm version.

Draft readiness: confirm WDK maintainer review of the exact release commit. The earlier package review approved an older tree; the newer commit changes declarations and release packaging without changing executable runtime statements. Published installation, imports and strict direct-construction TypeScript checks pass. Generic registration with WDK beta.18 still fails its optional-config constructor type (TS2345), so the docs use direct construction and state that limitation.

Local validation: full Node 22 docs quality workflow, internal/external links, production build, generated-source parity and rendered routes; clean published-package installation with exact wallet peer beta.19, entrypoint/error identity, strict TypeScript without skipLibCheck, 127 source tests, mocked usage and method contracts, and offline Bare derivation. No live activation or deposits were performed.

Hosted validation: Quality Gates passed dependency installation and the full docs quality workflow at commit 95bfbd72566d1556c356c51f6de243251125ed93.

Shared navigation and SDA chooser setup also appears in the separate Rhino.fi docs PR. Whichever PR lands second will need a rebase to retain both provider entries.

@ihsraham
ihsraham marked this pull request as ready for review October 5, 2026 10:40

@Sednaoui Sednaoui left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! this matches the SDK and API closely. A few accuracy and wording suggestions inline, plus some details that will help integrators avoid stuck funds.


## 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 still contains the team API key. Confirm with Candide which access and exposure model is appropriate for your app; do not describe this API URL as credential-free.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API key works like an RPC provider key: it identifies the team for usage and billing, and it can't activate addresses or move funds. Suggest: "The API URL identifies your team for usage and billing. It cannot activate addresses or move funds, so it can be used client side. Rotate it in the dashboard if it leaks. Keep the policy secret on the server."

Candide documents recipient withdrawal rights on the source chain and an optional recovery withdrawer that can act after a timelock, subject to recipient veto. A depositor who funds the address from an exchange may not control the recipient's key on that source chain. Decide who can recover stuck funds before creating the address; the recovery withdrawer is a derivation input.

<Callout type="warn">
The forwarding contracts use an upgradeable beacon controlled by Candide. Client-side address verification compares derivation inputs and addresses; it does not prove that the implementation behind the beacon cannot change. Review Candide's contract and recovery model before accepting funds.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small accuracy points: the beacon is upgradeable by Candide, and recovery withdrawals carry a 48h timelock that the recipient can cancel. Suggest: "Forwarding addresses delegate to an upgradeable beacon administered by Candide. Recovery withdrawals are timelocked and cancellable by the recipient. Address verification confirms derivation inputs, not the implementation behind the beacon."


Discover routes per source chain using `getSupportedRoutes({ sourceChain })`. Candide controls the current EVM chain and token set. A route delivers each accepted input token as its corresponding destination token; `outputAsset` is not a token-selection filter in this implementation.

Only tokens returned for the route are forwarded. If a route advertises native ETH, Candide identifies it with the zero-address sentinel; other tokens use their ERC-20 contract address. The sender pays the source wallet's applicable gas fee separately from forwarding fees. Unsupported tokens or deposits below the provider's minimum may require manual recovery.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest replacing "may require manual recovery" with: "Unsupported tokens, and balances below the minimum, stay in the contract. A balance below the minimum is forwarded once later deposits bring it above the minimum. The recipient can withdraw any token immediately, and the recovery withdrawer can after the timelock."

| `destinationAddress` | `string` | Optional with a bound account | EVM recipient; required when no account is bound. |
| `outputAsset` | `string` | Optional in shared type | Ignored; each supported token forwards as its own equivalent. |
| `recoveryWithdrawer` | `string` | Optional | Override the configured recovery wallet. Defaults to the recipient if neither value is supplied. |
| `salt` | `string` | Optional | 32-byte hex value; defaults to exported `ZERO_SALT`. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add the use case? Different salts give one recipient several addresses, for example one per user or per order, so deposits into a single treasury can be attributed.

})
```

Inspect `addressQuote.sponsored` and each fee's `included` flag. With sponsorship, the fees are paid under the policy rather than deducted from delivery. The estimate remains non-binding. Do not fund an address after an `ADDRESS_MISMATCH` or unexplained `DEPLOYMENT_CHANGED` error.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest adding how sponsorship is enabled: it's a toggle on the forwarding policy in the Candide dashboard. Sponsored forwards deliver the full deposit, and the fees are billed to the policy.

- An EVM recipient address. Binding a WDK account supplies its address as the default recipient; an unbound instance requires an explicit recipient.
- Explicit disabling is unsupported. Activations expire according to the provider's lifecycle.

Transfer history tracks forwards, rather than every raw deposit transaction. Candide's `pending` and `unknown` provider statuses map to WDK `processing`; an unrecognized status maps to WDK `pending`. See [transfer fields and status mapping](/sdk/sda-modules/sda-candide/api-reference#transfer-fields-and-status) before using them for UI decisions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth noting that one forward can combine several deposits to the same address. sourceAddresses lists the contributing senders and amounts.

sourceToken: token.token,
})
const minimum = tokenRoute?.limits?.min
if (minimum !== undefined && inputAmount <= BigInt(minimum)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: an amount equal to minAmount is accepted (it's the smallest viable input), so this should be inputAmount < BigInt(minimum)


## Recovery and Provider Trust

Candide documents recipient withdrawal rights on the source chain and an optional recovery withdrawer that can act after a timelock, subject to recipient veto. A depositor who funds the address from an exchange may not control the recipient's key on that source chain. Decide who can recover stuck funds before creating the address; the recovery withdrawer is a derivation input.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding that the recipient withdraws by sending a transaction on the source chain, so a recipient that can't transact there (for example an exchange-controlled address or a smart account not deployed on that chain) should be paired with a recovery withdrawer.

}
```

Use bounded polling with a delay and cancellation in your application. An empty history is not proof that the depositor never sent funds: history contains detected forwards, rather than every raw deposit. Preserve the transfer's opaque `id` for [`getTransfer()`](/sdk/sda-modules/sda-candide/api-reference#gettransfer), and use [`getTransfersByRecipient()`](/sdk/sda-modules/sda-candide/api-reference#gettransfersbyrecipient) for history across that recipient's addresses.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest: "Candide typically detects a deposit within seconds. Delivery time then depends on the route; show the transfer as processing until it completes."

This branch had an error being deployed

1 failed deployment
preview — 95bfbd72 Deployed Oct 5, 2026 by kinsta[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants