Skip to content

Add DFX.swiss native ramp plugin#5985

Open
TaprootFreak wants to merge 1 commit intoEdgeApp:developfrom
DFXswiss:dfx-ramp-plugin
Open

Add DFX.swiss native ramp plugin#5985
TaprootFreak wants to merge 1 commit intoEdgeApp:developfrom
DFXswiss:dfx-ramp-plugin

Conversation

@TaprootFreak
Copy link

Summary

  • Add DFX.swiss as a native Direct API ramp provider for buying (SEPA) and selling (SEPA) crypto with EUR/CHF
  • Authentication via wallet signature, no API key required
  • Cached provider config (fiat currencies, assets, countries) with 2min TTL

Supported flows

  • Buy SEPA: native flow with InfoDisplayScene showing bank transfer details
  • Sell SEPA: native SendScene2 flow with TX hash confirmation
  • KYC: handled via DFX webview when required, with deeplink callback for automatic resume

Supported blockchains

Bitcoin, Ethereum, Arbitrum, Optimism, Polygon, Base, BSC, Solana, Tron, Monero, Cardano, Zano

Region constraints

Blocked for IR, KP, MM, US, IL

Test plan

  • Buy crypto via SEPA bank transfer through DFX
  • Sell crypto via SEPA through DFX
  • KYC flow triggers and resumes correctly
  • Region blocking works for restricted countries
  • Settlement time displays correctly (0–2 days)
  • Provider config caching works (no excessive API calls)

* Add DFX.swiss native ramp plugin

Implement DFX.swiss as a Direct API ramp provider for buying (SEPA + Card)
and selling (SEPA) crypto with EUR/CHF. Authentication via wallet signature,
no API key required.

- Buy SEPA: native flow with InfoDisplayScene showing bank transfer details
- Buy Card: DFX webview with 3DS and deeplink callback
- Sell SEPA: native SendScene2 flow with TX hash confirmation
- KYC handling via DFX webview when required
- Cached provider config (fiat/assets/countries) with 2min TTL
- Region constraints: blocked for IR, KP, MM, US, IL
- Supports Bitcoin, Ethereum, Arbitrum, Optimism, Polygon, Base, BSC,
  Solana, Tron, Monero, Cardano

* Fix DFX plugin: API format and native asset detection

- Fix quote/paymentInfos API calls to use object refs ({id, blockchain})
  instead of string names — DFX API requires structured parameters
- Fix native coin detection: DFX returns wrapped-token contract addresses
  for native coins (WETH for ETH, etc.), now detected by name match
- Fix country cleaner field names: locationAllowed/bankAllowed/cardAllowed
  instead of mapi-prefixed names
- Fix chainId cleaner to accept null values from API (asEither(asString, asNull))

* Fix native coin detection: only match by name, not null chainId

Assets with chainId=null that aren't the native coin (e.g. MATIC on
Arbitrum) were incorrectly treated as native. Now only assets whose
name matches the blockchain's native coin name get tokenId=null.
Assets without chainId that aren't native are skipped.

* Add Zano blockchain support to DFX ramp plugin

* Remove card payment from DFX plugin, fix SEPA settlement range

DFX only supports bank transfers, not credit cards. Remove the
card payment type, constraints, and webview flow.

Update SEPA settlement range to 0-2 days and fix the display
logic so a zero minimum shows "0 - 2 days" instead of "Instant".

* Fix DFX auth message, wallet ID, and buy payment response parsing

Fix auth signature message to match DFX API ("Blockchain" not
"blockchain"). Use wallet ID 'arkade' for auth requests.

Update buy paymentInfos response parsing for new DFX API format:
iban/bic are now top-level fields, currency is a FiatDto object.
Handle isValid/error fields and include response body in error
messages for easier debugging.

* Add buy confirm flow, email collection, support link, and fix logo

On buy completion ("Done" button):
- Check if user has email registered via GET /v2/user
- If not, show email input modal and submit via PUT /v2/user/mail
- Confirm buy order via PUT /buy/paymentInfos/{id}/confirm
- Navigate back to previous scene

Add optional support URL button to InfoDisplayScene, used by DFX
to link to support page with auth session token.

Fix partner icon URL to use app.dfx.swiss/logo.png.

* Improve DFX plugin: spinner, address selection, error handling, KYC redirect

- Add loading spinner (showToastSpinner) during buy paymentInfos call
- Prefer segwit/transparent addresses via getBestAddress() helper
  for auth, buy, and sell flows
- Replace silent catch blocks with console.warn logging
- Include response body in sell error messages for debugging
- Redirect to DFX KYC webview on LimitExceeded and other KYC errors
- Use wallet ID 'edge' for auth requests
- Open /kyc path in KYC webview for direct KYC flow

* Harden DFX plugin: sell validation, address guard, cleanup

- Add isValid/error check to sell paymentInfos response with KYC
  redirect (matching buy flow behavior)
- Guard against empty address array in getBestAddress()
- Remove console.warn statements (not allowed in production code)
- Add isValid/error fields to sell payment info type

* Remove unused asDfxQuoteError type

* Use navigation.pop() consistently in buy flow

Match the pattern used by sell flow and all other ramp plugins.

* Add KYC deeplink callback for automatic resume after completion

Use openExternalWebView with kyc-redirect parameter pointing to
https://deep.edge.app/ramp/{direction}/dfx. After KYC completion,
DFX web app redirects back to Edge via deeplink, which dismisses
the browser and shows a success toast.

Register deeplink handler via rampDeeplinkManager for proper
lifecycle management. Pass direction to handleKycRequired for
correct deeplink routing.

* Fix limit check for crypto amount type

Limit checks were only applied when amountType was 'fiat'. When
the user enters a crypto amount, the estimated fiat equivalent
from the quote is now checked against minVolume/maxVolume.

* Fix amount calculation and limit checks for crypto input and sell direction

DFX API returns amounts in source currency (fiat for buy, crypto
for sell). Fix three logic errors:

- Buy + crypto input: fiatAmount was set to crypto exchangeAmount
  instead of dfxQuote.amount (the fiat cost from API)
- Sell + crypto input: limit check was comparing fiat against
  crypto min/max volumes
- Limit error display code now shows correct currency per direction

Rename minFiat/maxFiat to minSource/maxSource to clarify that
these values are in source currency, not always fiat.

* Fix quote request: use targetAmount as number, not boolean

DFX API expects targetAmount as a numeric amount in target asset,
not a boolean flag. Previously sent targetAmount: true which was
interpreted as 1 unit. Now correctly sends the crypto amount as
targetAmount when amountType is crypto.

* Fix auth cache, empty catches, types, and hardcoded values

- Auth cache keyed per address instead of global (prevents
  cross-wallet token reuse when switching between wallets)
- Replace 3 empty catch {} with showError() for email flow,
  buy confirm, and sell confirm
- Replace Record<string, unknown> quoteBody with typed
  DfxQuoteBody interface
- Extract EVM_CHAINS as module-level constant
- Derive settlement days display string from getSettlementRange()
  instead of hardcoded '1-2'

* Fix sell quote amount mapping and add supportedAmountTypes

- Fix amount/targetAmount assignment for sell direction:
  buy sends fiat as amount, crypto as targetAmount;
  sell sends crypto as amount, fiat as targetAmount
  (was direction-agnostic, causing wrong quotes for sell)
- Fix max-amount underLimit error to show crypto currency
  for sell direction instead of always showing fiat
- Add supportedAmountTypes: ['fiat', 'crypto'] to checkSupport
  return value (consistent with other ramp plugins)

* Avoid replacing urls at runtime

* Fixed amount calculation

* Show SEPA form in sell flow

* Improved sell flow

* Fixed transaction status page

---------

Co-authored-by: Daniel Padrino <danswarrior1@gmail.com>
Co-authored-by: David May <david.leo.may@gmail.com>
@TaprootFreak TaprootFreak marked this pull request as ready for review March 24, 2026 18:48
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.

1 participant