From fd53a98fb5e243ab7d4e910f57bd48eea1bae6a9 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:02:47 +0200 Subject: [PATCH 01/24] docs: add WalletConnect Pay homepage at /payments New landing frame page mirroring the root homepage, scoped to Pay: product cards for Wallets, PSPs, Ecommerce, and Merchant Dashboard. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- ...hants-merchantid-settlements-crypto-id.mdx | 0 .../delete-v1-merchants-merchantid.mdx | 0 .../get-v1-gateway-payment-id-status.mdx | 0 .../2026-02-18/get-v1-gateway-payment-id.mdx | 0 .../get-v1-merchants-merchant-id-payments.mdx | 0 ...et-v1-merchants-merchantid-settlements.mdx | 0 .../get-v1-merchants-merchantid.mdx | 0 .../2026-02-18/get-v1-merchants-payments.mdx | 0 .../2026-02-18/get-v1-merchants.mdx | 0 .../2026-02-18/get-v1-payments-id-status.mdx | 0 .../2026-02-18/get-v1-payments-id.mdx | 0 .../2026-02-18/get-v1-payments.mdx | 0 .../patch-v1-merchants-merchantid.mdx | 0 .../post-v1-gateway-payment-id-cancel.mdx | 0 .../post-v1-gateway-payment-id-confirm.mdx | 0 .../post-v1-gateway-payment-id-fetch.mdx | 0 .../post-v1-gateway-payment-id-options.mdx | 0 ...erchants-merchantid-settlements-crypto.mdx | 0 .../2026-02-18/post-v1-merchants.mdx | 0 .../2026-02-18/post-v1-payments-id-cancel.mdx | 0 .../2026-02-18/post-v1-payments.mdx | 0 .../2026-02-18/post-v1-refunds.mdx | 0 ...hants-merchantid-settlements-crypto-id.mdx | 0 ...hants-merchantid-settlements-crypto-id.mdx | 0 .../delete-v1-merchants-merchantid.mdx | 0 .../get-v1-gateway-payment-id-status.mdx | 0 .../get-v1-gateway-payment-id.mdx | 0 .../get-v1-merchants-merchant-id-payments.mdx | 0 ...et-v1-merchants-merchantid-settlements.mdx | 0 .../get-v1-merchants-merchantid.mdx | 0 .../get-v1-merchants-payments.mdx | 0 .../2026-02-19.preview/get-v1-merchants.mdx | 0 .../get-v1-payments-id-status.mdx | 0 .../2026-02-19.preview/get-v1-payments-id.mdx | 0 .../2026-02-19.preview/get-v1-payments.mdx | 0 .../patch-v1-merchants-merchantid.mdx | 0 .../post-v1-gateway-payment-id-cancel.mdx | 0 .../post-v1-gateway-payment-id-confirm.mdx | 0 .../post-v1-gateway-payment-id-fetch.mdx | 0 .../post-v1-gateway-payment-id-options.mdx | 0 ...erchants-merchantid-settlements-crypto.mdx | 0 .../2026-02-19.preview/post-v1-merchants.mdx | 0 .../post-v1-payments-id-cancel.mdx | 0 .../2026-02-19.preview/post-v1-payments.mdx | 0 .../2026-02-19.preview/post-v1-refunds.mdx | 0 ...hants-merchantid-settlements-crypto-id.mdx | 0 .../api-reference}/authentication.mdx | 0 .../api-reference}/index.mdx | 0 .../api-reference}/versioning.mdx | 0 payments/index.mdx | 121 ++++++++++++++++++ 50 files changed, 121 insertions(+) rename {api-reference => payments/api-reference}/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/delete-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-gateway-payment-id-status.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-gateway-payment-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-merchants-merchant-id-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-merchants-merchantid-settlements.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-merchants-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-merchants.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-payments-id-status.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-payments-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/get-v1-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/patch-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-gateway-payment-id-cancel.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-gateway-payment-id-confirm.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-gateway-payment-id-fetch.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-gateway-payment-id-options.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-merchants-merchantid-settlements-crypto.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-merchants.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-payments-id-cancel.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/post-v1-refunds.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/delete-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-gateway-payment-id-status.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-gateway-payment-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-merchants-merchant-id-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-merchants-merchantid-settlements.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-merchants-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-merchants.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-payments-id-status.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-payments-id.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/get-v1-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/patch-v1-merchants-merchantid.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-gateway-payment-id-cancel.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-gateway-payment-id-confirm.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-gateway-payment-id-fetch.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-gateway-payment-id-options.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-merchants.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-payments-id-cancel.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-payments.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/post-v1-refunds.mdx (100%) rename {api-reference => payments/api-reference}/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id.mdx (100%) rename {api-reference => payments/api-reference}/authentication.mdx (100%) rename {api-reference => payments/api-reference}/index.mdx (100%) rename {api-reference => payments/api-reference}/versioning.mdx (100%) create mode 100644 payments/index.mdx diff --git a/api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id.mdx b/payments/api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id.mdx similarity index 100% rename from api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id.mdx rename to payments/api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id.mdx diff --git a/api-reference/2026-02-18/delete-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-18/delete-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-18/delete-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-18/delete-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-18/get-v1-gateway-payment-id-status.mdx b/payments/api-reference/2026-02-18/get-v1-gateway-payment-id-status.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-gateway-payment-id-status.mdx rename to payments/api-reference/2026-02-18/get-v1-gateway-payment-id-status.mdx diff --git a/api-reference/2026-02-18/get-v1-gateway-payment-id.mdx b/payments/api-reference/2026-02-18/get-v1-gateway-payment-id.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-gateway-payment-id.mdx rename to payments/api-reference/2026-02-18/get-v1-gateway-payment-id.mdx diff --git a/api-reference/2026-02-18/get-v1-merchants-merchant-id-payments.mdx b/payments/api-reference/2026-02-18/get-v1-merchants-merchant-id-payments.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-merchants-merchant-id-payments.mdx rename to payments/api-reference/2026-02-18/get-v1-merchants-merchant-id-payments.mdx diff --git a/api-reference/2026-02-18/get-v1-merchants-merchantid-settlements.mdx b/payments/api-reference/2026-02-18/get-v1-merchants-merchantid-settlements.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-merchants-merchantid-settlements.mdx rename to payments/api-reference/2026-02-18/get-v1-merchants-merchantid-settlements.mdx diff --git a/api-reference/2026-02-18/get-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-18/get-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-18/get-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-18/get-v1-merchants-payments.mdx b/payments/api-reference/2026-02-18/get-v1-merchants-payments.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-merchants-payments.mdx rename to payments/api-reference/2026-02-18/get-v1-merchants-payments.mdx diff --git a/api-reference/2026-02-18/get-v1-merchants.mdx b/payments/api-reference/2026-02-18/get-v1-merchants.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-merchants.mdx rename to payments/api-reference/2026-02-18/get-v1-merchants.mdx diff --git a/api-reference/2026-02-18/get-v1-payments-id-status.mdx b/payments/api-reference/2026-02-18/get-v1-payments-id-status.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-payments-id-status.mdx rename to payments/api-reference/2026-02-18/get-v1-payments-id-status.mdx diff --git a/api-reference/2026-02-18/get-v1-payments-id.mdx b/payments/api-reference/2026-02-18/get-v1-payments-id.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-payments-id.mdx rename to payments/api-reference/2026-02-18/get-v1-payments-id.mdx diff --git a/api-reference/2026-02-18/get-v1-payments.mdx b/payments/api-reference/2026-02-18/get-v1-payments.mdx similarity index 100% rename from api-reference/2026-02-18/get-v1-payments.mdx rename to payments/api-reference/2026-02-18/get-v1-payments.mdx diff --git a/api-reference/2026-02-18/patch-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-18/patch-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-18/patch-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-18/patch-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-18/post-v1-gateway-payment-id-cancel.mdx b/payments/api-reference/2026-02-18/post-v1-gateway-payment-id-cancel.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-gateway-payment-id-cancel.mdx rename to payments/api-reference/2026-02-18/post-v1-gateway-payment-id-cancel.mdx diff --git a/api-reference/2026-02-18/post-v1-gateway-payment-id-confirm.mdx b/payments/api-reference/2026-02-18/post-v1-gateway-payment-id-confirm.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-gateway-payment-id-confirm.mdx rename to payments/api-reference/2026-02-18/post-v1-gateway-payment-id-confirm.mdx diff --git a/api-reference/2026-02-18/post-v1-gateway-payment-id-fetch.mdx b/payments/api-reference/2026-02-18/post-v1-gateway-payment-id-fetch.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-gateway-payment-id-fetch.mdx rename to payments/api-reference/2026-02-18/post-v1-gateway-payment-id-fetch.mdx diff --git a/api-reference/2026-02-18/post-v1-gateway-payment-id-options.mdx b/payments/api-reference/2026-02-18/post-v1-gateway-payment-id-options.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-gateway-payment-id-options.mdx rename to payments/api-reference/2026-02-18/post-v1-gateway-payment-id-options.mdx diff --git a/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto.mdx b/payments/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto.mdx rename to payments/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto.mdx diff --git a/api-reference/2026-02-18/post-v1-merchants.mdx b/payments/api-reference/2026-02-18/post-v1-merchants.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-merchants.mdx rename to payments/api-reference/2026-02-18/post-v1-merchants.mdx diff --git a/api-reference/2026-02-18/post-v1-payments-id-cancel.mdx b/payments/api-reference/2026-02-18/post-v1-payments-id-cancel.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-payments-id-cancel.mdx rename to payments/api-reference/2026-02-18/post-v1-payments-id-cancel.mdx diff --git a/api-reference/2026-02-18/post-v1-payments.mdx b/payments/api-reference/2026-02-18/post-v1-payments.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-payments.mdx rename to payments/api-reference/2026-02-18/post-v1-payments.mdx diff --git a/api-reference/2026-02-18/post-v1-refunds.mdx b/payments/api-reference/2026-02-18/post-v1-refunds.mdx similarity index 100% rename from api-reference/2026-02-18/post-v1-refunds.mdx rename to payments/api-reference/2026-02-18/post-v1-refunds.mdx diff --git a/api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id.mdx b/payments/api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id.mdx similarity index 100% rename from api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id.mdx rename to payments/api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id.mdx diff --git a/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id.mdx b/payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id.mdx similarity index 100% rename from api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id.mdx rename to payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id.mdx diff --git a/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-19.preview/delete-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status.mdx b/payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-gateway-payment-id.mdx b/payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-gateway-payment-id.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments.mdx b/payments/api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements.mdx b/payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-merchants-payments.mdx b/payments/api-reference/2026-02-19.preview/get-v1-merchants-payments.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-merchants-payments.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-merchants-payments.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-merchants.mdx b/payments/api-reference/2026-02-19.preview/get-v1-merchants.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-merchants.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-merchants.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-payments-id-status.mdx b/payments/api-reference/2026-02-19.preview/get-v1-payments-id-status.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-payments-id-status.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-payments-id-status.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-payments-id.mdx b/payments/api-reference/2026-02-19.preview/get-v1-payments-id.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-payments-id.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-payments-id.mdx diff --git a/api-reference/2026-02-19.preview/get-v1-payments.mdx b/payments/api-reference/2026-02-19.preview/get-v1-payments.mdx similarity index 100% rename from api-reference/2026-02-19.preview/get-v1-payments.mdx rename to payments/api-reference/2026-02-19.preview/get-v1-payments.mdx diff --git a/api-reference/2026-02-19.preview/patch-v1-merchants-merchantid.mdx b/payments/api-reference/2026-02-19.preview/patch-v1-merchants-merchantid.mdx similarity index 100% rename from api-reference/2026-02-19.preview/patch-v1-merchants-merchantid.mdx rename to payments/api-reference/2026-02-19.preview/patch-v1-merchants-merchantid.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel.mdx b/payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm.mdx b/payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch.mdx b/payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options.mdx b/payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto.mdx b/payments/api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-merchants.mdx b/payments/api-reference/2026-02-19.preview/post-v1-merchants.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-merchants.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-merchants.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-payments-id-cancel.mdx b/payments/api-reference/2026-02-19.preview/post-v1-payments-id-cancel.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-payments-id-cancel.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-payments-id-cancel.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-payments.mdx b/payments/api-reference/2026-02-19.preview/post-v1-payments.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-payments.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-payments.mdx diff --git a/api-reference/2026-02-19.preview/post-v1-refunds.mdx b/payments/api-reference/2026-02-19.preview/post-v1-refunds.mdx similarity index 100% rename from api-reference/2026-02-19.preview/post-v1-refunds.mdx rename to payments/api-reference/2026-02-19.preview/post-v1-refunds.mdx diff --git a/api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id.mdx b/payments/api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id.mdx similarity index 100% rename from api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id.mdx rename to payments/api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id.mdx diff --git a/api-reference/authentication.mdx b/payments/api-reference/authentication.mdx similarity index 100% rename from api-reference/authentication.mdx rename to payments/api-reference/authentication.mdx diff --git a/api-reference/index.mdx b/payments/api-reference/index.mdx similarity index 100% rename from api-reference/index.mdx rename to payments/api-reference/index.mdx diff --git a/api-reference/versioning.mdx b/payments/api-reference/versioning.mdx similarity index 100% rename from api-reference/versioning.mdx rename to payments/api-reference/versioning.mdx diff --git a/payments/index.mdx b/payments/index.mdx new file mode 100644 index 0000000..e793b60 --- /dev/null +++ b/payments/index.mdx @@ -0,0 +1,121 @@ +--- +mode: "frame" +title: "WalletConnect Pay Documentation" +sidebarTitle: "Home" +description: "Documentation for WalletConnect Pay. Integrate secure crypto payments into your app with step-by-step guides, APIs, and best practices." +--- + +import { Container, Title } from '/snippets/home/utility.mdx'; +import { ProductCard } from '/snippets/home/product-cards.mdx'; + +
+ +
+
+
+ WalletConnect Pay +
+

+ WalletConnect Pay is a complete, end-to-end stablecoin and crypto payment solution that allows PSPs and merchants to enable crypto payments from any wallet and any asset through a single, familiar integration. +

+
+
+
+ + +
+

+ WalletConnect Pay serves Merchants, PSPs, Wallets and eCommerce. Choose your integration method below to quickstart. +

+
+ + + + + + +
    + + + +
    + + How does WalletConnect Pay work? + +
    + +
    + + +
    + + Resources + +

    + Learn more about WalletConnect Pay and the wider WalletConnect brand. +

    +
    + + + Dive into the API reference to explore more + + + Read the latest news and updates from the WalletConnect team + + +
    +
From c5971e1de3460cae3a7348112bbdc3fbc984fed0 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:02:49 +0200 Subject: [PATCH 02/24] docs: add security information page Standalone page at /security covering SOC2 Type II certification, the wallet SDK's Trail of Bits audit, third-party audit history, and the bug bounty disclosure process. Not wired into sidebar nav, same pattern as license-update.mdx. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- security.mdx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 security.mdx diff --git a/security.mdx b/security.mdx new file mode 100644 index 0000000..cd2e6a9 --- /dev/null +++ b/security.mdx @@ -0,0 +1,28 @@ +--- +title: "Security Information" +--- + +Security is not just a feature but a fundamental aspect of WalletConnect's architecture. The infrastructure has undergone multiple rounds of third-party security reviews, audits, penetration testing, and threat modeling to ensure the highest standards of protection. Security is viewed as a continuously evolving discipline, with regular system audits to identify and address potential vulnerabilities. The entire WalletConnect system underwent Threat Modeling by Spearbit in 2024, and then an entire ecosystem audit in 2026 to reach SOC2 Type II Certification. + +## SOC2 Type II Certification + +WalletConnect underwent SOC2 Type II certification in 2026, demonstrating robust security controls and the ability to secure user data from unauthorized access - using it solely for its intended purpose and with confidentiality, as well as providing consistent availability on all systems and processing data appropriately and within time limits. As a Type II certification, WalletConnect displayed its security and data controls work over a period of time rather than simply on the spot. + +## SDK for Wallets + +WalletConnect's SDK for wallets is an open-source SDK, supporting multiple transport methods, from WebSockets to Universal Links. Its design philosophy prioritizes minimizing third-party dependencies to reduce the attack surface area. To ensure its reliability and security, the SDK for wallets was audited by Trail of Bits. The audit report is available here. This comprehensive security review covered the source code and included a lightweight Threat Model covering upstream and downstream dependencies. + +## Third-Party Reviews + +The security infrastructure of Reown has undergone multiple rounds of audits by independent security auditing firms, including Trail of Bits, Halborn, and Spearbit. These audits cover both AppKit and WalletKit, along with a comprehensive company-wide Threat Model. + +| Audit Scope | Auditor | Report | +| --- | --- | --- | +| WalletConnect SOC2 Type II Certification | AICPA | | +| WalletConnect Comprehensive Threat Model | Spearbit | View Report | +| SDK for Apps Embedded Wallet Integration Pentest | Halborn | View Report | +| SDK for wallets Security Review & Lightweight Threat Model | Trail of Bits | View Report | + +## Security disclosures + +WalletConnect maintains an active bug bounty program to encourage security researchers to responsibly disclose vulnerabilities and help strengthen the systems. To report a vulnerability, please fill out the disclosure form here. From a2b9ce908432db85ab4ee7a183a8f946a2c199d1 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:02:50 +0200 Subject: [PATCH 03/24] docs: add Network section overview page Adds /network with an overview of the WalletConnect Network's technology, permissioned architecture, and participants. Not yet wired into sidebar nav; links to /network/governance and /network/WCT-token, which don't exist in this repo yet. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- network/index.mdx | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 network/index.mdx diff --git a/network/index.mdx b/network/index.mdx new file mode 100644 index 0000000..85ab4c3 --- /dev/null +++ b/network/index.mdx @@ -0,0 +1,64 @@ +--- +title: "Network" +sidebarTitle: "Overview" +description: "An overview of the WalletConnect Network, its technology, participants, and permissioned architecture." +--- + +## Overview + +The WalletConnect Network is a network of apps, wallets and chains, facilitating end-users to connect to apps using any supported wallet on any supported chain. It is chain agnostic, working across ecosystems from EVM and its L2s, to Solana, Cosmos, Polkadot, Bitcoin and more. To date, it has facilitated more than 300+ million connections for 50+ million users between over 700+ different wallets and 80,000+ applications. + +Since its inception in 2018, the Network's design emphasizes interoperability and composability to efficiently enable interoperability between apps, wallets, fintechs, chains and TradFi. + +## Technology + +The WalletConnect Network's key components include: + +1. **Service Nodes**; database nodes that form the backbone of the network's storage layer. They operate on a consistent-hashing based distributed database. + +2. **Gateway Nodes**; responsible for facilitating encrypted communications and data routing between wallets and applications. + +3. **Relay Service**; connects users' wallets to dapps. + +## Permissioned Network + +The WalletConnect Network operates in a permissioned environment. This means: + +* Specific node operators manage the Service Nodes under service-level agreements. +* The Gateway Nodes are centralized and managed by WalletConnect. + +This allows WalletConnect to provide a secure and reliable service for enterprise-grade apps and wallets. + +## Network Participants + +WalletConnect Network Architecture + +The WalletConnect Network comprises various participants, each playing a crucial role in maintaining functionality and security: + +1. **Service Node Operators**: They run the service nodes (database nodes) that form the backbone of the network's storage layer. These nodes operate on a consistent-hashing based distributed database. + +2. **Gateway Node Operators**: They manage the gateway nodes, which are the entry points for apps and SDKs. Gateways facilitate encrypted communications and data routing between wallets and applications. + +3. **Wallets**: These allow end-users to manage their blockchain keys and interact with apps via the WalletConnect protocol. Most wallets integrate with the network using the WalletKit SDK. + +4. **Apps**: These are the products and services in the web3 space that drive traffic to the network. They can integrate directly or via available SDKs. + +5. **SDKs**: Software Development Kits that simplify the integration process for apps and wallets. + +6. **End Users**: The consumers of all services within the network, from wallets to apps, going through the relay and database nodes. + +Each of these participants contributes to the ecosystem in unique ways, ensuring the network's functionality, security, and continued growth. Their roles and interactions form the foundation of the WalletConnect Network's robust and interconnected infrastructure. + +## Learn more about the WalletConnect Network + + + + Learn about the WalletConnect network's governance model. + + + Learn how WCT powers the network's governance and incentivizes participants. + + + Read more about the network's design, architecture, and core principles. + + From 086d8e437ad2907cb2649de1becbf388ed5ab824 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:02:52 +0200 Subject: [PATCH 04/24] docs: update homepage to link out to Wallets, Apps, Payments, Network Replaces the WalletConnect Pay-specific homepage with a general WalletConnect ecosystem quickstart linking to Wallets, Apps, Payments, and the Network. /wallets and /apps don't exist in this repo yet. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- index.mdx | 215 +++++++++++++++--------------------------------------- 1 file changed, 59 insertions(+), 156 deletions(-) diff --git a/index.mdx b/index.mdx index bb687a5..20b315f 100644 --- a/index.mdx +++ b/index.mdx @@ -1,197 +1,100 @@ --- mode: "frame" -title: "WalletConnect Pay Documentation" +title: "WalletConnect Documentation" sidebarTitle: "Home" -description: "Documentation for WalletConnect Pay. Integrate secure crypto payments into your app with step-by-step guides, APIs, and best practices." +description: "The Connectivity Layer for the Financial Internet" --- -import { Container, Title} from '/snippets/home/utility.mdx'; -import { ProductTiles } from '/snippets/home/product-tiles.mdx'; -import { appCategories } from '/snippets/home/data.mdx'; +import { Container, Title } from '/snippets/home/utility.mdx'; import { ProductCard } from '/snippets/home/product-cards.mdx';
-
- WalletConnect Pay +
+ WalletConnect
-

- The easiest way to enable crypto payments from any wallet, any asset, anywhere. +

+ The Connectivity Layer for the Financial Internet

-
- - + +
-
- - Introducing WalletConnect Pay - -
-

- **[WalletConnect Pay](/payments/overview)** is a complete, end-to-end crypto payment solution that allows PSPs and merchants to enable crypto payments from any wallet and any asset through a single, familiar integration. + + WalletConnect Ecosystem Quickstart + +

+ WalletConnect powers apps, wallets and end-users via the WalletConnect network. +

+

+ Check out our quickstart guides to get started!

-
- - - - - -
-
- - - + - + type="Wallet SDK" + /> + + + -
-
    +
      - Learn more about WalletConnect Pay + Resources -

      - A curated list of educational resources about WalletConnect Pay and crypto payments. -

      -
      - A clear guide to how Stablecoin and Wallet payments work. - - - Learn what it takes to make crypto payments usable in the real world. - - - Learn how to accept USDC anywhere with WalletConnect Pay. + Read the latest news and updates from the WalletConnect team - A legal deep dive into why stablecoins are not yet mainstream. + Discord community for WalletConnect Network and WCT Token - Learn what’s hindering adoption today, what’s changing globally, and the infra behind crypto payments. + Follow WalletConnect on X (Twitter) to stay updated on the announcements
      - - - -
      - - Resources - - -
      - - - Read the latest news and updates from the WalletConnect team - - - Follow WalletConnect on X (Twitter) to stay updated on the announcements - - -
From 4624d0d3b2965cd7a105c5a937105f22156189b6 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:03:08 +0200 Subject: [PATCH 05/24] docs: migrate /api-reference to /payments/api-reference Repoints docs.json nav, inline links across payments docs, the generate-specs.mjs generator, and the update-specs CI workflow to the new location. Adds a catch-all redirect from the old /api-reference/* paths so existing bookmarks and search results keep working. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- .github/workflows/update-specs.yml | 2 +- docs.json | 112 +++++++++--------- payments/merchant-api/logo-specification.mdx | 2 +- payments/merchant/quickstart.mdx | 10 +- payments/psps/headless-sdk/implementation.mdx | 2 +- .../psps/headless-sdk/packages-reference.mdx | 2 +- payments/psps/overview.mdx | 2 +- payments/test-mode.mdx | 2 +- payments/token-and-chain-coverage.mdx | 2 +- payments/wallets/api-first.mdx | 2 +- payments/wallets/webview.mdx | 2 +- payments/webhooks.mdx | 6 +- scripts/generate-specs.mjs | 16 +-- 13 files changed, 83 insertions(+), 79 deletions(-) diff --git a/.github/workflows/update-specs.yml b/.github/workflows/update-specs.yml index d9459ad..26d593c 100644 --- a/.github/workflows/update-specs.yml +++ b/.github/workflows/update-specs.yml @@ -28,6 +28,6 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add api/ api-reference/ docs.json + git add api/ payments/api-reference/ docs.json git commit -m "chore: update OpenAPI specs" git push diff --git a/docs.json b/docs.json index 980b937..3287135 100644 --- a/docs.json +++ b/docs.json @@ -17,8 +17,12 @@ "destination": "/payments/merchant/quickstart" }, { - "source": "/api-reference/latest/:slug*", - "destination": "/api-reference/2026-02-18/:slug*" + "source": "/api-reference/:slug*", + "destination": "/payments/api-reference/:slug*" + }, + { + "source": "/payments/api-reference/latest/:slug*", + "destination": "/payments/api-reference/2026-02-18/:slug*" } ], "integrations": { @@ -139,52 +143,52 @@ { "group": "Overview", "pages": [ - "api-reference/index", - "api-reference/authentication", - "api-reference/versioning" + "payments/api-reference/index", + "payments/api-reference/authentication", + "payments/api-reference/versioning" ] }, { "group": "Gateway", "pages": [ - "api-reference/2026-02-18/get-v1-gateway-payment-id", - "api-reference/2026-02-18/post-v1-gateway-payment-id-cancel", - "api-reference/2026-02-18/post-v1-gateway-payment-id-confirm", - "api-reference/2026-02-18/post-v1-gateway-payment-id-fetch", - "api-reference/2026-02-18/post-v1-gateway-payment-id-options", - "api-reference/2026-02-18/get-v1-gateway-payment-id-status" + "payments/api-reference/2026-02-18/get-v1-gateway-payment-id", + "payments/api-reference/2026-02-18/post-v1-gateway-payment-id-cancel", + "payments/api-reference/2026-02-18/post-v1-gateway-payment-id-confirm", + "payments/api-reference/2026-02-18/post-v1-gateway-payment-id-fetch", + "payments/api-reference/2026-02-18/post-v1-gateway-payment-id-options", + "payments/api-reference/2026-02-18/get-v1-gateway-payment-id-status" ] }, { "group": "Payments", "pages": [ - "api-reference/2026-02-18/post-v1-payments", - "api-reference/2026-02-18/get-v1-payments", - "api-reference/2026-02-18/get-v1-payments-id", - "api-reference/2026-02-18/post-v1-payments-id-cancel", - "api-reference/2026-02-18/get-v1-payments-id-status" + "payments/api-reference/2026-02-18/post-v1-payments", + "payments/api-reference/2026-02-18/get-v1-payments", + "payments/api-reference/2026-02-18/get-v1-payments-id", + "payments/api-reference/2026-02-18/post-v1-payments-id-cancel", + "payments/api-reference/2026-02-18/get-v1-payments-id-status" ] }, { "group": "Refunds", "pages": [ - "api-reference/2026-02-18/post-v1-refunds" + "payments/api-reference/2026-02-18/post-v1-refunds" ] }, { "group": "Merchants", "pages": [ - "api-reference/2026-02-18/get-v1-merchants-payments", - "api-reference/2026-02-18/post-v1-merchants", - "api-reference/2026-02-18/get-v1-merchants", - "api-reference/2026-02-18/get-v1-merchants-merchantid", - "api-reference/2026-02-18/patch-v1-merchants-merchantid", - "api-reference/2026-02-18/delete-v1-merchants-merchantid", - "api-reference/2026-02-18/get-v1-merchants-merchantid-settlements", - "api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto", - "api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id", - "api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id", - "api-reference/2026-02-18/get-v1-merchants-merchant-id-payments" + "payments/api-reference/2026-02-18/get-v1-merchants-payments", + "payments/api-reference/2026-02-18/post-v1-merchants", + "payments/api-reference/2026-02-18/get-v1-merchants", + "payments/api-reference/2026-02-18/get-v1-merchants-merchantid", + "payments/api-reference/2026-02-18/patch-v1-merchants-merchantid", + "payments/api-reference/2026-02-18/delete-v1-merchants-merchantid", + "payments/api-reference/2026-02-18/get-v1-merchants-merchantid-settlements", + "payments/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto", + "payments/api-reference/2026-02-18/put-v1-merchants-merchantid-settlements-crypto-id", + "payments/api-reference/2026-02-18/delete-v1-merchants-merchantid-settlements-crypto-id", + "payments/api-reference/2026-02-18/get-v1-merchants-merchant-id-payments" ] } ] @@ -195,52 +199,52 @@ { "group": "Overview", "pages": [ - "api-reference/index", - "api-reference/authentication", - "api-reference/versioning" + "payments/api-reference/index", + "payments/api-reference/authentication", + "payments/api-reference/versioning" ] }, { "group": "Gateway", "pages": [ - "api-reference/2026-02-19.preview/get-v1-gateway-payment-id", - "api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel", - "api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm", - "api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch", - "api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options", - "api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status" + "payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id", + "payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-cancel", + "payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-confirm", + "payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-fetch", + "payments/api-reference/2026-02-19.preview/post-v1-gateway-payment-id-options", + "payments/api-reference/2026-02-19.preview/get-v1-gateway-payment-id-status" ] }, { "group": "Payments", "pages": [ - "api-reference/2026-02-19.preview/post-v1-payments", - "api-reference/2026-02-19.preview/get-v1-payments", - "api-reference/2026-02-19.preview/get-v1-payments-id", - "api-reference/2026-02-19.preview/post-v1-payments-id-cancel", - "api-reference/2026-02-19.preview/get-v1-payments-id-status" + "payments/api-reference/2026-02-19.preview/post-v1-payments", + "payments/api-reference/2026-02-19.preview/get-v1-payments", + "payments/api-reference/2026-02-19.preview/get-v1-payments-id", + "payments/api-reference/2026-02-19.preview/post-v1-payments-id-cancel", + "payments/api-reference/2026-02-19.preview/get-v1-payments-id-status" ] }, { "group": "Refunds", "pages": [ - "api-reference/2026-02-19.preview/post-v1-refunds" + "payments/api-reference/2026-02-19.preview/post-v1-refunds" ] }, { "group": "Merchants", "pages": [ - "api-reference/2026-02-19.preview/get-v1-merchants-payments", - "api-reference/2026-02-19.preview/post-v1-merchants", - "api-reference/2026-02-19.preview/get-v1-merchants", - "api-reference/2026-02-19.preview/get-v1-merchants-merchantid", - "api-reference/2026-02-19.preview/patch-v1-merchants-merchantid", - "api-reference/2026-02-19.preview/delete-v1-merchants-merchantid", - "api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements", - "api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto", - "api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id", - "api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id", - "api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments" + "payments/api-reference/2026-02-19.preview/get-v1-merchants-payments", + "payments/api-reference/2026-02-19.preview/post-v1-merchants", + "payments/api-reference/2026-02-19.preview/get-v1-merchants", + "payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid", + "payments/api-reference/2026-02-19.preview/patch-v1-merchants-merchantid", + "payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid", + "payments/api-reference/2026-02-19.preview/get-v1-merchants-merchantid-settlements", + "payments/api-reference/2026-02-19.preview/post-v1-merchants-merchantid-settlements-crypto", + "payments/api-reference/2026-02-19.preview/put-v1-merchants-merchantid-settlements-crypto-id", + "payments/api-reference/2026-02-19.preview/delete-v1-merchants-merchantid-settlements-crypto-id", + "payments/api-reference/2026-02-19.preview/get-v1-merchants-merchant-id-payments" ] } ] diff --git a/payments/merchant-api/logo-specification.mdx b/payments/merchant-api/logo-specification.mdx index 6a7704d..f9fde54 100644 --- a/payments/merchant-api/logo-specification.mdx +++ b/payments/merchant-api/logo-specification.mdx @@ -6,7 +6,7 @@ sidebarTitle: "Logo specification" The `iconUrl` field on the Merchant API accepts a public HTTPS URL pointing to a merchant logo. The logo renders at the moment of payment, so dimensions and format are a direct trust signal. A stretched or pixelated logo undermines buyer confidence at the exact step where confidence matters most. -This guide covers the recommended specification for the `iconUrl` field used by [`POST /v1/merchants`](/api-reference/2026-02-18/post-v1-merchants) (create) and [`PATCH /v1/merchants/{merchantId}`](/api-reference/2026-02-18/patch-v1-merchants-merchantid) (update). +This guide covers the recommended specification for the `iconUrl` field used by [`POST /v1/merchants`](/payments/api-reference/2026-02-18/post-v1-merchants) (create) and [`PATCH /v1/merchants/{merchantId}`](/payments/api-reference/2026-02-18/patch-v1-merchants-merchantid) (update). ## Where the logo appears diff --git a/payments/merchant/quickstart.mdx b/payments/merchant/quickstart.mdx index 2a90b63..4a1345c 100644 --- a/payments/merchant/quickstart.mdx +++ b/payments/merchant/quickstart.mdx @@ -50,7 +50,7 @@ curl "$WCP_BASE/v1/merchants" \ A `200 OK` with a (possibly empty) `data` array confirms the key works. A `401` means the key is wrong; a `403` means the key is valid but lacks permission for this account. -Pin requests to a specific API version with the `WCP-Version` header (for example, `WCP-Version: 2026-02-18`). Without it, your account's default version is used. See [Versioning](/api-reference/versioning) for the full policy. +Pin requests to a specific API version with the `WCP-Version` header (for example, `WCP-Version: 2026-02-18`). Without it, your account's default version is used. See [Versioning](/payments/api-reference/versioning) for the full policy. @@ -92,7 +92,7 @@ export WCP_MERCHANT_ID="mrch_7kBz2qR9xPvLmN4Yw" `Idempotency-Key` is required on this endpoint. Use a fresh UUID per merchant — replays with the same key return the original result instead of creating a duplicate. -See the full schema and field reference in [Create a merchant](/api-reference/latest/post-v1-merchants). +See the full schema and field reference in [Create a merchant](/payments/api-reference/latest/post-v1-merchants). @@ -118,10 +118,10 @@ curl -X POST "$WCP_BASE/v1/merchants/$WCP_MERCHANT_ID/settlements/crypto" \ The example above registers USDC on Base. For the full list of supported `asset` values and the chains we settle to, see [Token & Chain Coverage](/payments/token-and-chain-coverage). -Each `(merchant, asset)` pair must be unique — registering the same asset twice returns `settlement_asset_conflict`. To change a destination, use [Update a crypto settlement](/api-reference/latest/put-v1-merchants-merchantid-settlements-crypto-id) instead. +Each `(merchant, asset)` pair must be unique — registering the same asset twice returns `settlement_asset_conflict`. To change a destination, use [Update a crypto settlement](/payments/api-reference/latest/put-v1-merchants-merchantid-settlements-crypto-id) instead. -See the full schema in [Create crypto settlements](/api-reference/latest/post-v1-merchants-merchantid-settlements-crypto). +See the full schema in [Create crypto settlements](/payments/api-reference/latest/post-v1-merchants-merchantid-settlements-crypto). @@ -182,7 +182,7 @@ Use `isFinal` to decide when to stop polling. While the payment is still in flig In test mode the `txId` is synthetic (`test:{paymentId}`) — no transaction is executed on-chain. Live payments return a real transaction hash. -See the full response schema in [Get the payment status](/api-reference/latest/get-v1-payments-id-status). +See the full response schema in [Get the payment status](/payments/api-reference/latest/get-v1-payments-id-status). diff --git a/payments/psps/headless-sdk/implementation.mdx b/payments/psps/headless-sdk/implementation.mdx index d660784..979aeea 100644 --- a/payments/psps/headless-sdk/implementation.mdx +++ b/payments/psps/headless-sdk/implementation.mdx @@ -369,7 +369,7 @@ WCP_WALLET_API_KEY= The full public API of pay-core, pay-state, pay-react, and pay-appkit. - + The Gateway and Payments endpoints behind the SDK. diff --git a/payments/psps/headless-sdk/packages-reference.mdx b/payments/psps/headless-sdk/packages-reference.mdx index 43a4f98..2a99be2 100644 --- a/payments/psps/headless-sdk/packages-reference.mdx +++ b/payments/psps/headless-sdk/packages-reference.mdx @@ -280,7 +280,7 @@ function useAppKitWalletProvider(appKit: AppKit | undefined, options?: UseAppKit The step-by-step React / Next.js walkthrough. - + The Gateway and Payments endpoints behind the SDK. diff --git a/payments/psps/overview.mdx b/payments/psps/overview.mdx index 7a393eb..95a938e 100644 --- a/payments/psps/overview.mdx +++ b/payments/psps/overview.mdx @@ -41,7 +41,7 @@ Reach for the **Headless SDK** when you need to **own the experience** end to en Own the full checkout experience with the `@walletconnect/pay-*` packages. - + The Gateway and Payments endpoints behind WalletConnect Pay. diff --git a/payments/test-mode.mdx b/payments/test-mode.mdx index e7f5388..c8d0d5a 100644 --- a/payments/test-mode.mdx +++ b/payments/test-mode.mdx @@ -133,7 +133,7 @@ Switching from test to live is just a key swap: create a **live key** (prefix `w Create your first test payment in six steps. - + How API keys and the Api-Key header work. diff --git a/payments/token-and-chain-coverage.mdx b/payments/token-and-chain-coverage.mdx index 5f46b5a..bf65147 100644 --- a/payments/token-and-chain-coverage.mdx +++ b/payments/token-and-chain-coverage.mdx @@ -14,7 +14,7 @@ This list will be updated over time as assets move from beta into General Availa ## Supported tokens and chains -When creating crypto settlements, use the CAIP-19 token identifier below when specifying the settlement token contract. See the [Create crypto settlements](/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto) endpoint for details. +When creating crypto settlements, use the CAIP-19 token identifier below when specifying the settlement token contract. See the [Create crypto settlements](/payments/api-reference/2026-02-18/post-v1-merchants-merchantid-settlements-crypto) endpoint for details. | Token | Chain | CAIP-19 | Acceptance | Settlement | diff --git a/payments/wallets/api-first.mdx b/payments/wallets/api-first.mdx index 896895f..fdda511 100644 --- a/payments/wallets/api-first.mdx +++ b/payments/wallets/api-first.mdx @@ -225,4 +225,4 @@ If a payment or route expires mid-flow, the API returns a `410` (payment expired ## API Reference -For request/response schemas and examples for each Gateway endpoint, see the **[API Reference](/api-reference)**. +For request/response schemas and examples for each Gateway endpoint, see the **[API Reference](/payments/api-reference)**. diff --git a/payments/wallets/webview.mdx b/payments/wallets/webview.mdx index da42d04..e72c87d 100644 --- a/payments/wallets/webview.mdx +++ b/payments/wallets/webview.mdx @@ -553,7 +553,7 @@ const res = await fetch( const { status } = await res.json(); // "succeeded" | "processing" | "failed" | … ``` -See the [Payments Status API](/api-reference/2026-02-18/get-v1-payments-id-status) for the full response schema. +See the [Payments Status API](/payments/api-reference/2026-02-18/get-v1-payments-id-status) for the full response schema. ## Best Practices diff --git a/payments/webhooks.mdx b/payments/webhooks.mdx index 6355ca1..0c24db5 100644 --- a/payments/webhooks.mdx +++ b/payments/webhooks.mdx @@ -8,7 +8,7 @@ Webhooks push payment lifecycle events to an HTTPS endpoint you control, as they ## Webhooks vs. polling -Polling [`GET /v1/payments/{id}/status`](/api-reference/latest/get-v1-payments-id-status) is the primary way to validate payment status during the purchase cycle: create the payment, then poll until the status is final. Webhooks come on top as an enhancement. They usually tell you first, and with far fewer requests, so you can update the order status in your UI, notify a customer, or kick off downstream processing the moment something happens. +Polling [`GET /v1/payments/{id}/status`](/payments/api-reference/latest/get-v1-payments-id-status) is the primary way to validate payment status during the purchase cycle: create the payment, then poll until the status is final. Webhooks come on top as an enhancement. They usually tell you first, and with far fewer requests, so you can update the order status in your UI, notify a customer, or kick off downstream processing the moment something happens. When a webhook event arrives, its payload already contains everything you need. Every event is a full signed snapshot of the payment and carries a monotonic `payment_state_version`, so verifying the signature, deduplicating by `id`, and applying the version guard is enough; there is no need to call the API from inside your handler. @@ -173,7 +173,7 @@ That's roughly **28 hours** of automatic retries. After the final attempt the de Replay operations reach back 14 days at most. And if every delivery to an endpoint keeps failing for **5 days**, the endpoint is **disabled** and stops receiving events. -Because a misconfigured URL or a disabled endpoint drops deliveries silently, don't rely on noticing an outage. Run a **periodic reconciliation job**: poll [`GET /v1/payments/{id}/status`](/api-reference/latest/get-v1-payments-id-status) for any payment your records still show in a non-final state after its `expires_at` has passed, and [`GET /v1/payments`](/api-reference/latest/get-v1-payments), which returns `settled`, for succeeded payments still awaiting settlement. Use the endpoint's delivery history in the dashboard to debug what went wrong. +Because a misconfigured URL or a disabled endpoint drops deliveries silently, don't rely on noticing an outage. Run a **periodic reconciliation job**: poll [`GET /v1/payments/{id}/status`](/payments/api-reference/latest/get-v1-payments-id-status) for any payment your records still show in a non-final state after its `expires_at` has passed, and [`GET /v1/payments`](/payments/api-reference/latest/get-v1-payments), which returns `settled`, for succeeded payments still awaiting settlement. Use the endpoint's delivery history in the dashboard to debug what went wrong. To stop deliveries entirely (for example, when decommissioning an integration), delete the endpoint from the dashboard's **Webhooks** page. Deletion takes effect immediately and cannot be undone. @@ -549,7 +549,7 @@ Webhook configuration does **not** carry over from test to live; they are separa Simulate every payment status transition and watch the webhooks arrive. - + The polling endpoint to confirm state on the critical path. diff --git a/scripts/generate-specs.mjs b/scripts/generate-specs.mjs index c5a6481..9641007 100644 --- a/scripts/generate-specs.mjs +++ b/scripts/generate-specs.mjs @@ -86,7 +86,7 @@ function slugify(method, path) { } async function generatePages(version, spec) { - const dir = join(ROOT, "api-reference", version); + const dir = join(ROOT, "payments", "api-reference", version); await mkdir(dir, { recursive: true }); // Group by second path segment: /v1/{segment}/... @@ -112,7 +112,7 @@ async function generatePages(version, spec) { const title = (op.summary || `${method} ${path}`).replace(/["\\]/g, "\\$&"); const mdx = `---\ntitle: "${title}"\nopenapi: "api/${version}.json ${method} ${path}"\n---\n`; writes.push(writeFile(join(dir, filename), mdx)); - pages.push(`api-reference/${version}/${slug}`); + pages.push(`payments/api-reference/${version}/${slug}`); } groups.push({ group, pages }); } @@ -177,7 +177,7 @@ async function buildNavigation( tab: "API Reference", icon: "code", groups: [ - { group: "Overview", pages: ["api-reference/index", "api-reference/versioning"] }, + { group: "Overview", pages: ["payments/api-reference/index", "payments/api-reference/versioning"] }, ...groups, ], }, @@ -208,14 +208,14 @@ function buildManagedRedirects(latestStableVersion) { if (!latestStableVersion) return []; return [ { - source: "/api-reference/latest/:slug*", - destination: `/api-reference/${latestStableVersion}/:slug*`, + source: "/payments/api-reference/latest/:slug*", + destination: `/payments/api-reference/${latestStableVersion}/:slug*`, }, ]; } const MANAGED_REDIRECT_SOURCES = new Set([ - "/api-reference/latest/:slug*", + "/payments/api-reference/latest/:slug*", ]); function mergeRedirects(existing, latestStableVersion) { @@ -232,14 +232,14 @@ async function main() { const allVersions = [...stable, ...preview]; validateVersions(allVersions); - const apiRefDir = join(ROOT, "api-reference"); + const apiRefDir = join(ROOT, "payments", "api-reference"); const apiDir = join(ROOT, "api"); const versionSet = new Set(allVersions); const staleRefs = (await readdir(apiRefDir, { withFileTypes: true })) .filter((e) => e.isDirectory() && !versionSet.has(e.name)) .map((e) => { - console.log(`Removed stale directory api-reference/${e.name}`); + console.log(`Removed stale directory payments/api-reference/${e.name}`); return rm(join(apiRefDir, e.name), { recursive: true }); }); From 72e38ee4c284f84a08949aa9e24bd33030f5c46f Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:38:00 +0200 Subject: [PATCH 06/24] docs: remove /network overview page Content will be added elsewhere; homepage still links to /network, which will 404 until that's back. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- network/index.mdx | 64 ----------------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 network/index.mdx diff --git a/network/index.mdx b/network/index.mdx deleted file mode 100644 index 85ab4c3..0000000 --- a/network/index.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Network" -sidebarTitle: "Overview" -description: "An overview of the WalletConnect Network, its technology, participants, and permissioned architecture." ---- - -## Overview - -The WalletConnect Network is a network of apps, wallets and chains, facilitating end-users to connect to apps using any supported wallet on any supported chain. It is chain agnostic, working across ecosystems from EVM and its L2s, to Solana, Cosmos, Polkadot, Bitcoin and more. To date, it has facilitated more than 300+ million connections for 50+ million users between over 700+ different wallets and 80,000+ applications. - -Since its inception in 2018, the Network's design emphasizes interoperability and composability to efficiently enable interoperability between apps, wallets, fintechs, chains and TradFi. - -## Technology - -The WalletConnect Network's key components include: - -1. **Service Nodes**; database nodes that form the backbone of the network's storage layer. They operate on a consistent-hashing based distributed database. - -2. **Gateway Nodes**; responsible for facilitating encrypted communications and data routing between wallets and applications. - -3. **Relay Service**; connects users' wallets to dapps. - -## Permissioned Network - -The WalletConnect Network operates in a permissioned environment. This means: - -* Specific node operators manage the Service Nodes under service-level agreements. -* The Gateway Nodes are centralized and managed by WalletConnect. - -This allows WalletConnect to provide a secure and reliable service for enterprise-grade apps and wallets. - -## Network Participants - -WalletConnect Network Architecture - -The WalletConnect Network comprises various participants, each playing a crucial role in maintaining functionality and security: - -1. **Service Node Operators**: They run the service nodes (database nodes) that form the backbone of the network's storage layer. These nodes operate on a consistent-hashing based distributed database. - -2. **Gateway Node Operators**: They manage the gateway nodes, which are the entry points for apps and SDKs. Gateways facilitate encrypted communications and data routing between wallets and applications. - -3. **Wallets**: These allow end-users to manage their blockchain keys and interact with apps via the WalletConnect protocol. Most wallets integrate with the network using the WalletKit SDK. - -4. **Apps**: These are the products and services in the web3 space that drive traffic to the network. They can integrate directly or via available SDKs. - -5. **SDKs**: Software Development Kits that simplify the integration process for apps and wallets. - -6. **End Users**: The consumers of all services within the network, from wallets to apps, going through the relay and database nodes. - -Each of these participants contributes to the ecosystem in unique ways, ensuring the network's functionality, security, and continued growth. Their roles and interactions form the foundation of the WalletConnect Network's robust and interconnected infrastructure. - -## Learn more about the WalletConnect Network - - - - Learn about the WalletConnect network's governance model. - - - Learn how WCT powers the network's governance and incentivizes participants. - - - Read more about the network's design, architecture, and core principles. - - From ddf8e8a79e6e2d3d31134763f306eb2f3cc4acc8 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Sierra Date: Fri, 4 Sep 2026 11:55:23 +0200 Subject: [PATCH 07/24] docs: migrate Wallets/Apps/Network docs from docs.walletconnect.network under /network MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrates the full content of the docs.walletconnect.network Mintlify site (github.com/WalletConnect/... foundation docs repo) into this repo, nested under a /network prefix, combining the .network and .com domains into one site: - wallets/ -> network/wallets/ (Wallet SDK docs: Web, Android, iOS, Flutter, React Native, .NET, chains, custodians, walletguide, guides, features, more) — 116 files - apps/ -> network/apps/ (App SDK docs: React, Next, Vue, JavaScript) - WCT-token/ -> network/WCT-token/ (overview, rewards, service-node-rewards, staking, faq, governance, contracts — already consolidated in the source repo) - service-nodes.mdx -> network/service-nodes.mdx - network/wallets.mdx (network participant page, distinct from the Wallet SDK docs) carried over as-is - network/index.mdx: new /network landing page, using network.mdx's content (Technology/Permissioned Network/Participants) as the canonical version; overview.mdx's shorter intro was not merged in - Supporting assets: 5 missing /images/cloud/*.png and 9 /snippets/ files (cloud-banner, cloud/*, walletkit chain-abstraction/mobile linking snippets, chainlist, walletlist) the migrated content depends on All internal /wallets, /apps, /WCT-token links within the migrated content were rewritten to /network/wallets, /network/apps, /network/WCT-token. One dead nav reference inherited from the source repo (wallets/guides/app-extended-sessions, a file that doesn't exist there either) was dropped rather than carried over broken. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WzTGS8bJLU4QvnDsthWChe --- images/cloud/11.png | Bin 0 -> 252145 bytes images/cloud/6.png | Bin 0 -> 239686 bytes images/cloud/7.png | Bin 0 -> 257360 bytes images/cloud/8.png | Bin 0 -> 249230 bytes images/cloud/9.png | Bin 0 -> 194728 bytes network/WCT-token/contracts.mdx | 44 ++ network/WCT-token/faq.mdx | 121 +++ network/WCT-token/governance.mdx | 48 ++ network/WCT-token/overview.mdx | 64 ++ network/WCT-token/rewards.mdx | 48 ++ network/WCT-token/service-node-rewards.mdx | 39 + network/WCT-token/staking.mdx | 188 +++++ network/apps/javascript/installation.mdx | 472 +++++++++++ network/apps/next/installation.mdx | 469 +++++++++++ network/apps/overview.mdx | 130 +++ network/apps/react/installation.mdx | 483 +++++++++++ network/apps/vue/installation.mdx | 487 ++++++++++++ network/index.mdx | 62 ++ network/service-nodes.mdx | 82 ++ network/wallets.mdx | 15 + network/wallets/android/best-practices.mdx | 234 ++++++ network/wallets/android/chain-abstraction.mdx | 141 ++++ network/wallets/android/cloud/analytics.mdx | 7 + .../android/cloud/explorer-submission.mdx | 7 + network/wallets/android/cloud/relay.mdx | 7 + network/wallets/android/eip5792.mdx | 271 +++++++ network/wallets/android/installation.mdx | 50 ++ network/wallets/android/link-mode.mdx | 57 ++ network/wallets/android/mobile-linking.mdx | 190 +++++ .../notifications/notify/installation.mdx | 31 + .../android/notifications/notify/overview.mdx | 26 + .../notifications/notify/resources.mdx | 19 + .../notifications/notify/spam-protection.mdx | 27 + .../android/notifications/notify/usage.mdx | 339 ++++++++ .../wallets/android/notifications/push.mdx | 75 ++ network/wallets/android/one-click-auth.mdx | 114 +++ network/wallets/android/resources.mdx | 27 + network/wallets/android/usage.mdx | 429 ++++++++++ network/wallets/android/verify.mdx | 50 ++ network/wallets/best-practices.mdx | 748 ++++++++++++++++++ network/wallets/c-sharp/cloud/analytics.mdx | 7 + .../c-sharp/cloud/explorer-submission.mdx | 7 + network/wallets/c-sharp/cloud/relay.mdx | 7 + network/wallets/c-sharp/installation.mdx | 13 + network/wallets/c-sharp/usage.mdx | 378 +++++++++ network/wallets/c-sharp/verify.mdx | 99 +++ network/wallets/chains/adi.mdx | 31 + network/wallets/chains/bitcoin.mdx | 311 ++++++++ network/wallets/chains/canton.mdx | 581 ++++++++++++++ network/wallets/chains/evm.mdx | 338 ++++++++ network/wallets/chains/overview.mdx | 24 + network/wallets/chains/solana.mdx | 272 +++++++ network/wallets/chains/stacks.mdx | 263 ++++++ network/wallets/chains/stellar.mdx | 382 +++++++++ network/wallets/chains/sui.mdx | 173 ++++ network/wallets/chains/ton.mdx | 208 +++++ network/wallets/chains/tron.mdx | 263 ++++++ .../wallets/custodians/app-access-control.mdx | 46 ++ .../custodians/app-extended-sessions.mdx | 77 ++ .../custodians/contract-access-control.mdx | 130 +++ .../wallets/custodians/extended-sessions.mdx | 35 + network/wallets/custodians/overview.mdx | 33 + .../wallets/features/chain-abstraction.mdx | 87 ++ network/wallets/features/link-mode.mdx | 39 + network/wallets/features/notifications.mdx | 22 + network/wallets/features/one-click-auth.mdx | 31 + network/wallets/features/verify.mdx | 56 ++ network/wallets/flutter/chain-abstraction.mdx | 244 ++++++ network/wallets/flutter/cloud/analytics.mdx | 7 + .../flutter/cloud/explorer-submission.mdx | 7 + network/wallets/flutter/cloud/relay.mdx | 7 + network/wallets/flutter/eip5792.mdx | 284 +++++++ network/wallets/flutter/installation.mdx | 33 + network/wallets/flutter/link-mode.mdx | 106 +++ network/wallets/flutter/mobile-linking.mdx | 232 ++++++ network/wallets/flutter/one-click-auth.mdx | 146 ++++ network/wallets/flutter/usage.mdx | 448 +++++++++++ network/wallets/flutter/verify.mdx | 46 ++ .../guides/tonconnect-walletconnect.mdx | 179 +++++ network/wallets/ios/best-practices.mdx | 213 +++++ network/wallets/ios/chain-abstraction.mdx | 92 +++ network/wallets/ios/cloud/analytics.mdx | 7 + .../wallets/ios/cloud/explorer-submission.mdx | 7 + network/wallets/ios/cloud/relay.mdx | 7 + network/wallets/ios/eip5792.mdx | 284 +++++++ network/wallets/ios/installation.mdx | 47 ++ network/wallets/ios/link-mode.mdx | 43 + network/wallets/ios/mobile-linking.mdx | 244 ++++++ .../ios/notifications/notify/installation.mdx | 42 + .../ios/notifications/notify/overview.mdx | 26 + .../ios/notifications/notify/resources.mdx | 19 + .../notifications/notify/spam-protection.mdx | 27 + .../ios/notifications/notify/usage.mdx | 184 +++++ network/wallets/ios/notifications/push.mdx | 92 +++ network/wallets/ios/one-click-auth.mdx | 102 +++ network/wallets/ios/resources.mdx | 28 + network/wallets/ios/usage.mdx | 442 +++++++++++ network/wallets/ios/verify.mdx | 50 ++ .../wallets/more/from-web3wallet-android.mdx | 107 +++ .../wallets/more/from-web3wallet-flutter.mdx | 79 ++ network/wallets/more/from-web3wallet-ios.mdx | 114 +++ .../more/from-web3wallet-react-native.mdx | 66 ++ .../wallets/more/from-web3wallet-to-reown.mdx | 32 + .../wallets/more/from-web3wallet-unity.mdx | 98 +++ network/wallets/more/from-web3wallet-web.mdx | 65 ++ network/wallets/more/staying-up-to-date.mdx | 41 + network/wallets/overview.mdx | 63 ++ .../wallets/react-native/best-practices.mdx | 198 +++++ .../react-native/chain-abstraction.mdx | 96 +++ .../wallets/react-native/cloud/analytics.mdx | 7 + .../cloud/explorer-submission.mdx | 7 + network/wallets/react-native/cloud/relay.mdx | 7 + network/wallets/react-native/eip5792.mdx | 284 +++++++ network/wallets/react-native/installation.mdx | 31 + network/wallets/react-native/link-mode.mdx | 115 +++ .../wallets/react-native/mobile-linking.mdx | 115 +++ .../notifications/notify/installation.mdx | 114 +++ .../notifications/notify/overview.mdx | 26 + .../notifications/notify/spam-protection.mdx | 27 + .../notifications/notify/usage.mdx | 427 ++++++++++ .../react-native/notifications/push.mdx | 115 +++ .../wallets/react-native/one-click-auth.mdx | 137 ++++ network/wallets/react-native/resources.mdx | 31 + network/wallets/react-native/usage.mdx | 364 +++++++++ network/wallets/react-native/verify.mdx | 72 ++ network/wallets/walletguide/chain-list.mdx | 17 + .../walletguide/explorer-submission.mdx | 183 +++++ network/wallets/walletguide/explorer.mdx | 113 +++ network/wallets/walletguide/overview.mdx | 47 ++ network/wallets/walletguide/wallet-list.mdx | 16 + network/wallets/web/best-practices.mdx | 202 +++++ network/wallets/web/chain-abstraction.mdx | 92 +++ network/wallets/web/cloud/analytics.mdx | 7 + .../wallets/web/cloud/explorer-submission.mdx | 7 + network/wallets/web/cloud/relay.mdx | 7 + network/wallets/web/eip5792.mdx | 284 +++++++ network/wallets/web/installation.mdx | 23 + network/wallets/web/one-click-auth-siws.mdx | 132 ++++ network/wallets/web/one-click-auth.mdx | 135 ++++ network/wallets/web/resources.mdx | 31 + network/wallets/web/usage.mdx | 624 +++++++++++++++ network/wallets/web/verify.mdx | 71 ++ snippets/chainlist.mdx | 80 ++ snippets/cloud-banner.mdx | 12 + snippets/cloud/analytics.mdx | 300 +++++++ snippets/cloud/explorer-submission.mdx | 106 +++ snippets/cloud/relay.mdx | 69 ++ .../chain-abstraction/error-handling.mdx | 29 + .../shared/chain-abstraction/intro.mdx | 25 + snippets/walletkit/shared/mobile-linking.mdx | 12 + snippets/walletlist.mdx | 89 +++ 151 files changed, 18760 insertions(+) create mode 100644 images/cloud/11.png create mode 100644 images/cloud/6.png create mode 100644 images/cloud/7.png create mode 100644 images/cloud/8.png create mode 100644 images/cloud/9.png create mode 100644 network/WCT-token/contracts.mdx create mode 100644 network/WCT-token/faq.mdx create mode 100644 network/WCT-token/governance.mdx create mode 100644 network/WCT-token/overview.mdx create mode 100644 network/WCT-token/rewards.mdx create mode 100644 network/WCT-token/service-node-rewards.mdx create mode 100644 network/WCT-token/staking.mdx create mode 100644 network/apps/javascript/installation.mdx create mode 100644 network/apps/next/installation.mdx create mode 100644 network/apps/overview.mdx create mode 100644 network/apps/react/installation.mdx create mode 100644 network/apps/vue/installation.mdx create mode 100644 network/index.mdx create mode 100644 network/service-nodes.mdx create mode 100644 network/wallets.mdx create mode 100644 network/wallets/android/best-practices.mdx create mode 100644 network/wallets/android/chain-abstraction.mdx create mode 100644 network/wallets/android/cloud/analytics.mdx create mode 100644 network/wallets/android/cloud/explorer-submission.mdx create mode 100644 network/wallets/android/cloud/relay.mdx create mode 100644 network/wallets/android/eip5792.mdx create mode 100644 network/wallets/android/installation.mdx create mode 100644 network/wallets/android/link-mode.mdx create mode 100644 network/wallets/android/mobile-linking.mdx create mode 100644 network/wallets/android/notifications/notify/installation.mdx create mode 100644 network/wallets/android/notifications/notify/overview.mdx create mode 100644 network/wallets/android/notifications/notify/resources.mdx create mode 100644 network/wallets/android/notifications/notify/spam-protection.mdx create mode 100644 network/wallets/android/notifications/notify/usage.mdx create mode 100644 network/wallets/android/notifications/push.mdx create mode 100644 network/wallets/android/one-click-auth.mdx create mode 100644 network/wallets/android/resources.mdx create mode 100644 network/wallets/android/usage.mdx create mode 100644 network/wallets/android/verify.mdx create mode 100644 network/wallets/best-practices.mdx create mode 100644 network/wallets/c-sharp/cloud/analytics.mdx create mode 100644 network/wallets/c-sharp/cloud/explorer-submission.mdx create mode 100644 network/wallets/c-sharp/cloud/relay.mdx create mode 100644 network/wallets/c-sharp/installation.mdx create mode 100644 network/wallets/c-sharp/usage.mdx create mode 100644 network/wallets/c-sharp/verify.mdx create mode 100644 network/wallets/chains/adi.mdx create mode 100644 network/wallets/chains/bitcoin.mdx create mode 100644 network/wallets/chains/canton.mdx create mode 100644 network/wallets/chains/evm.mdx create mode 100644 network/wallets/chains/overview.mdx create mode 100644 network/wallets/chains/solana.mdx create mode 100644 network/wallets/chains/stacks.mdx create mode 100644 network/wallets/chains/stellar.mdx create mode 100644 network/wallets/chains/sui.mdx create mode 100644 network/wallets/chains/ton.mdx create mode 100644 network/wallets/chains/tron.mdx create mode 100644 network/wallets/custodians/app-access-control.mdx create mode 100644 network/wallets/custodians/app-extended-sessions.mdx create mode 100644 network/wallets/custodians/contract-access-control.mdx create mode 100644 network/wallets/custodians/extended-sessions.mdx create mode 100644 network/wallets/custodians/overview.mdx create mode 100644 network/wallets/features/chain-abstraction.mdx create mode 100644 network/wallets/features/link-mode.mdx create mode 100644 network/wallets/features/notifications.mdx create mode 100644 network/wallets/features/one-click-auth.mdx create mode 100644 network/wallets/features/verify.mdx create mode 100644 network/wallets/flutter/chain-abstraction.mdx create mode 100644 network/wallets/flutter/cloud/analytics.mdx create mode 100644 network/wallets/flutter/cloud/explorer-submission.mdx create mode 100644 network/wallets/flutter/cloud/relay.mdx create mode 100644 network/wallets/flutter/eip5792.mdx create mode 100644 network/wallets/flutter/installation.mdx create mode 100644 network/wallets/flutter/link-mode.mdx create mode 100644 network/wallets/flutter/mobile-linking.mdx create mode 100644 network/wallets/flutter/one-click-auth.mdx create mode 100644 network/wallets/flutter/usage.mdx create mode 100644 network/wallets/flutter/verify.mdx create mode 100644 network/wallets/guides/tonconnect-walletconnect.mdx create mode 100644 network/wallets/ios/best-practices.mdx create mode 100644 network/wallets/ios/chain-abstraction.mdx create mode 100644 network/wallets/ios/cloud/analytics.mdx create mode 100644 network/wallets/ios/cloud/explorer-submission.mdx create mode 100644 network/wallets/ios/cloud/relay.mdx create mode 100644 network/wallets/ios/eip5792.mdx create mode 100644 network/wallets/ios/installation.mdx create mode 100644 network/wallets/ios/link-mode.mdx create mode 100644 network/wallets/ios/mobile-linking.mdx create mode 100644 network/wallets/ios/notifications/notify/installation.mdx create mode 100644 network/wallets/ios/notifications/notify/overview.mdx create mode 100644 network/wallets/ios/notifications/notify/resources.mdx create mode 100644 network/wallets/ios/notifications/notify/spam-protection.mdx create mode 100644 network/wallets/ios/notifications/notify/usage.mdx create mode 100644 network/wallets/ios/notifications/push.mdx create mode 100644 network/wallets/ios/one-click-auth.mdx create mode 100644 network/wallets/ios/resources.mdx create mode 100644 network/wallets/ios/usage.mdx create mode 100644 network/wallets/ios/verify.mdx create mode 100644 network/wallets/more/from-web3wallet-android.mdx create mode 100644 network/wallets/more/from-web3wallet-flutter.mdx create mode 100644 network/wallets/more/from-web3wallet-ios.mdx create mode 100644 network/wallets/more/from-web3wallet-react-native.mdx create mode 100644 network/wallets/more/from-web3wallet-to-reown.mdx create mode 100644 network/wallets/more/from-web3wallet-unity.mdx create mode 100644 network/wallets/more/from-web3wallet-web.mdx create mode 100644 network/wallets/more/staying-up-to-date.mdx create mode 100644 network/wallets/overview.mdx create mode 100644 network/wallets/react-native/best-practices.mdx create mode 100644 network/wallets/react-native/chain-abstraction.mdx create mode 100644 network/wallets/react-native/cloud/analytics.mdx create mode 100644 network/wallets/react-native/cloud/explorer-submission.mdx create mode 100644 network/wallets/react-native/cloud/relay.mdx create mode 100644 network/wallets/react-native/eip5792.mdx create mode 100644 network/wallets/react-native/installation.mdx create mode 100644 network/wallets/react-native/link-mode.mdx create mode 100644 network/wallets/react-native/mobile-linking.mdx create mode 100644 network/wallets/react-native/notifications/notify/installation.mdx create mode 100644 network/wallets/react-native/notifications/notify/overview.mdx create mode 100644 network/wallets/react-native/notifications/notify/spam-protection.mdx create mode 100644 network/wallets/react-native/notifications/notify/usage.mdx create mode 100644 network/wallets/react-native/notifications/push.mdx create mode 100644 network/wallets/react-native/one-click-auth.mdx create mode 100644 network/wallets/react-native/resources.mdx create mode 100644 network/wallets/react-native/usage.mdx create mode 100644 network/wallets/react-native/verify.mdx create mode 100644 network/wallets/walletguide/chain-list.mdx create mode 100644 network/wallets/walletguide/explorer-submission.mdx create mode 100644 network/wallets/walletguide/explorer.mdx create mode 100644 network/wallets/walletguide/overview.mdx create mode 100644 network/wallets/walletguide/wallet-list.mdx create mode 100644 network/wallets/web/best-practices.mdx create mode 100644 network/wallets/web/chain-abstraction.mdx create mode 100644 network/wallets/web/cloud/analytics.mdx create mode 100644 network/wallets/web/cloud/explorer-submission.mdx create mode 100644 network/wallets/web/cloud/relay.mdx create mode 100644 network/wallets/web/eip5792.mdx create mode 100644 network/wallets/web/installation.mdx create mode 100644 network/wallets/web/one-click-auth-siws.mdx create mode 100644 network/wallets/web/one-click-auth.mdx create mode 100644 network/wallets/web/resources.mdx create mode 100644 network/wallets/web/usage.mdx create mode 100644 network/wallets/web/verify.mdx create mode 100644 snippets/chainlist.mdx create mode 100644 snippets/cloud-banner.mdx create mode 100644 snippets/cloud/analytics.mdx create mode 100644 snippets/cloud/explorer-submission.mdx create mode 100644 snippets/cloud/relay.mdx create mode 100644 snippets/walletkit/shared/chain-abstraction/error-handling.mdx create mode 100644 snippets/walletkit/shared/chain-abstraction/intro.mdx create mode 100644 snippets/walletkit/shared/mobile-linking.mdx create mode 100644 snippets/walletlist.mdx diff --git a/images/cloud/11.png b/images/cloud/11.png new file mode 100644 index 0000000000000000000000000000000000000000..98ba2866372899349940665e8ce54778b92ae431 GIT binary patch literal 252145 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%0A|49rXr0 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

Wf;@&Sitt0%K~EKT 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

EAvJQT4Ru?Zk^jX_9{O=_qG&>~~+xU3d>@=!OH> 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 literal 0 HcmV?d00001 diff --git a/images/cloud/7.png b/images/cloud/7.png new file mode 100644 index 0000000000000000000000000000000000000000..e5ce05e1fe12db9d81db29a9c20124cee1d9e2d5 GIT binary patch literal 257360 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�Zx0FBzE$ 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

V0Ym2Rz5aCdAHR^pkO#8D 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�ma3K@?CzZdD8~mrDWZq$i|9=^~*Wr(Iu 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 R{RsFuel+Yz&0k`E_@C!33b+6O literal 0 HcmV?d00001 diff --git a/images/cloud/8.png b/images/cloud/8.png new file mode 100644 index 0000000000000000000000000000000000000000..2f910f601cffe95a5f5fc8feb42d012561c3bc26 GIT binary patch literal 249230 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 a9{p!94RQIxe|!M^`}&mU$*QmXZ~tF)e|cX3 literal 0 HcmV?d00001 diff --git a/images/cloud/9.png b/images/cloud/9.png new file mode 100644 index 0000000000000000000000000000000000000000..04520153984259c9aaa312fa2291865dbb3b8fac GIT binary patch literal 194728 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 ZIc}&pSjk48*Cn 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 + This applies only to long-term allocation contracts. + + +--- + +### What happens after my unlock finishes? + +When the unlock period ends: + +- Your stakeweight and voting power drop to **0** +- You can **withdraw** your full amount +- To continue earning, simply **stake again** \ No newline at end of file diff --git a/network/WCT-token/governance.mdx b/network/WCT-token/governance.mdx new file mode 100644 index 0000000..ae7606c --- /dev/null +++ b/network/WCT-token/governance.mdx @@ -0,0 +1,48 @@ +--- +title: Governance +sidebarTitle: Overview +--- + +The governance of the WalletConnect Network is structured to facilitate decentralization, transparency, and community participation. This section outlines the roles and responsibilities of the WalletConnect Foundation and the community governance model that guides the Network. + +## Foundation + +The WalletConnect Foundation is tasked with stewarding the Network by promoting its adoption, use, and growth. The Foundation's responsibilities include overview of grants to stakeholders, supporting applications, sdk and wallet development teams, and managing partnerships. + +## Councils + +The Councils includes several curated groups of individuals who are responsible for the different functions that are either part of the foundation, core development teams, node operator teams or work independently. Envisioned Councils include: + +- **Technical Council** - responsible for the technology & infrastructure +- **Partnerships Council** - responsible for the partnerships & growth + +This structure is projected to be implemented during the constitution of the community governance. + +## Community Governance + +The WalletConnect Network is designed for a fully decentralized governance model managed by community governance. Further decentralization is expected to be facilitated by approved proposals of WCT tokenholders participating in the Network governance. + +Optimally this transition occurs through planned, multiple phases. An example of such planned multiple phases follows, though the actual transition will depend on input and approval from WCT tokenholders: + +1. **Phase 1 - TGE Preparation:** + - The WalletConnect Foundation was established and began operations. + - The Foundation and reown collaborate on the Network's technical, community, partnerships, and administrative governance. + +2. **Phase 2 - Foundation Transition:** + - The Foundation establishes different councils to eventually take over various governance functions. + - The Foundation expands its programs and responsibilities over community, partnerships, and administration considerations for the Network. + - The community governance arises from WCT token stakers who participate in the Network and its governance. + +3. **Phase 3 - Partnerships Transition:** + - The Partnerships Council, elected by the community governance, assumes a more prominent role in community initiatives, including marketing, business development, grants programs, education, developer relations, and events. + +4. **Phase 4 - Technology Transition:** + - The Technical Council, elected by the community governance, assumes responsibility for technical governance as the Network becomes permissionless. + - The Foundation coordinates this transition. + +5. **Phase 5 - Administration Transition:** + - The Foundation requires community governance approval to establish annual budgets, review and elect councils, and handle other administrative responsibilities through voting by community governance delegates. + + +Token holders can participate in governance starting in Phase 2 after TGE by staking their WCT tokens, proposing changes, and voting on key issues, thereby shaping the future of the WalletConnect Network. + \ No newline at end of file diff --git a/network/WCT-token/overview.mdx b/network/WCT-token/overview.mdx new file mode 100644 index 0000000..9b8fd99 --- /dev/null +++ b/network/WCT-token/overview.mdx @@ -0,0 +1,64 @@ +--- +title: WCT Token +sidebarTitle: "Intro" +--- + +The WCT token powers the WalletConnect ecosystem, acting as both a reward and governance mechanism. + +## Token Functions + +The WCT token has three primary functions within the WalletConnect Network: + +1. **Rewards**: WCT tokens are distributed as cashback, staking rewards, and node operator rewards. +2. **Staking**: Participants can stake WCT tokens to earn rewards and participate in governance. +3. **Governance**: WCT holders can vote on proposals and changes, giving the community control over the Network's development through decentralized governance. + +## WCT Allocation + + + +The initial supply of WCT tokens is capped at 1 billion, with the following allocations: + +- WalletConnect Foundation: 27% +- Airdrops: 18.5% +- Team: 18.5% +- Rewards: 17.5% +- Previous Backers: 11.5% +- Core Development: 7% + +Tokens allocated to core development, team and previous backers will be subject to a 4-year unlock including a 1 year cliff starting at the token generation event (TGE). + +## Fixed Supply + +The initial design of the WalletConnect Network's tokenomics does not include token inflation. The current model focuses on utilizing existing token allocations such that inflation is not envisioned within the first 3-4 years. + +Introduction of an inflationary design would follow only after the token holders' vote to approval following careful consideration of Network metrics, participant feedback, and overall ecosystem health, with specific parameters to be determined through Network governance processes. + +## Token Flow + +Payments represent one of the largest economic opportunities in crypto. Global card networks generate hundreds of billions in fee revenue annually — funding rewards programs, interchange, and network operations for every participant. WalletConnect Pay is designed to bring that same model onchain: generate real transaction revenue from real commerce, powered by the WalletConnect Network. + +The Network is the primary engine of WalletConnect Pay. The WCT token sits at the centre, connecting payment activity to staking rewards, governance weight, and long-term token value. + +### How the Network Powers Value Flows + +Every payment powered by WalletConnect Pay generates transaction fees. Those fees flow back into the Network through multiple mechanisms. Additional mechanisms are expected to be implemented. + +**Rewards Distribution** — Fee revenue funds rewards across all four stakeholder groups in the payment flow: + +| Stakeholder | How They Earn | +| --- | --- | +| Wallets | Earn interchange on every payment routed through WalletConnect Pay — modelled on card network interchange | +| End Users | Earn cashback-style rewards on every purchase | + +### Why This Model Works + +Most alternative payment methods have failed not for technical reasons, but because they gave users no reason to switch. UK Open Banking was technically superior to cards but offered consumers zero upside. CurrentC was backed by the largest US retailers but built solely to save merchants on fees — and died before launch because users had nothing to gain. + +WalletConnect Pay is designed around the opposite principle: lead with incentives on every side. The result is a self-reinforcing flywheel — more payments generate more fees, more fees fund better rewards, better rewards drive more payments. + +WCT is what holds this flywheel together. Stakers benefit as volume grows. Governance shapes how rewards and buybacks are calibrated over time. The token is not waiting for utility — it is the connective tissue between a payments network and its community of participants. + + +Merchants pay transaction fees — not users. The end-user experience remains frictionless by design. + diff --git a/network/WCT-token/rewards.mdx b/network/WCT-token/rewards.mdx new file mode 100644 index 0000000..ab38678 --- /dev/null +++ b/network/WCT-token/rewards.mdx @@ -0,0 +1,48 @@ +--- +title: Rewards +--- + +The WalletConnect Network implements a strategic reward system to incentivize network participants and ensure the network's growth and stability. + +## Reward Allocation + +17.5% of the initial token supply is allocated for rewards to incentivize Network participants over the first few years of operations. This allocation is strategically phased: + +- **First Year**: Only 5% will be distributed to test Network assumptions +- **Subsequent Years**: The remaining 12.5% is reserved + +## Phased Distribution + +The reward distribution is strategically phased to allow for testing and long-term sustainability: + +1. **First Year**: A conservative 5% distribution to test network assumptions and reward mechanisms. +2. **Subsequent Years**: A larger 12.5% allocation, designated as a "flexible incentive" for ongoing distribution. + +:::note +The larger portion (12.5%) is a "flexible incentive" and may be subject to change to maintain the reward mechanism's support of Network goals and benefits to all participants. This flexibility ensures that the reward system can adapt to the evolving needs of the Network and its participants. +::: + +## Purpose of Rewards + +The reward system is designed to: + +1. Incentivize active participation in the network +2. Encourage long-term commitment from participants +3. Ensure network security and efficiency +4. Support the overall growth and sustainability of the WalletConnect ecosystem + +## Types of Rewards + +The Network includes various types of rewards: + +1. **Staking Rewards**: Participants can earn rewards by staking WCT tokens. +2. **Node Rewards**: Service Node operators receive rewards based on their performance and activity. +3. **Wallet Performance Rewards**: Wallets can earn rewards based on their performance and certification status. +4. **End-user Cashback**: Cashback rewards for using WalletConnect Pay. + +## Related Topics + +To learn more about specific aspects of the reward system and participation in the WalletConnect Network, please refer to the following sections: + +- [Staking](../wct-staking) +- [Service Node Performance Rewards](./service-node-rewards) \ No newline at end of file diff --git a/network/WCT-token/service-node-rewards.mdx b/network/WCT-token/service-node-rewards.mdx new file mode 100644 index 0000000..3c80fe3 --- /dev/null +++ b/network/WCT-token/service-node-rewards.mdx @@ -0,0 +1,39 @@ +--- +title: Service Node Rewards +--- + +The WalletConnect Network implements a carefully structured reward system for node operators, designed to incentivize high performance and long-term commitment. The node rewards budget is split into two phases, with the first phase addressing the unique challenges of the WCT token non-transferability period. + +## Phase 1: Non-Transferability Period + +During this initial phase, a fixed-base reward structure is implemented, resulting in the following token-base revenues: + +1. **Initial Allocation**: 100,000 WCT are distributed as initial allocation and can be staked. These tokens are locked for the entire period of non-transferability. + +2. **Performance Boost (B_n)**: A boost given to nodes to reflect their performance and activity that is not based on WCT price. + +### Boost Calculation + +The performance boost (B_n) is calculated as follows: + +$$B_n = \alpha + (weight \cdot performance score)$$ + +A multiplicator (M_n) is also applied: + +$$M_n = \frac{100000}{T}$$ + +Where T is the period on which the initial allocation is locked. + +### Weight Distribution + +The boost is based on the weight of the node relative to other nodes. Initially, if there are 15 nodes, each getting 100,000 WCT, they would each get 6.67% weight. This stake weight evolves if some nodes do not restake their boost. + +## Performance-Based Rewards + +Individual node rewards are conditional on the performance factor $U(i,t) \in [0, 1]$. In line with the performance factors for other groups, there is a set of KPIs defining this. Initially, it will be based on uptime and latency. + +For a detailed explanation of how these factors are calculated and weighted, please refer to the [Performance Evaluation](../service-nodes/#performance-evaluation) section. + + +The reward structure is subject to adjustment through network governance to ensure it continues to align with the network's goals and economic sustainability. + \ No newline at end of file diff --git a/network/WCT-token/staking.mdx b/network/WCT-token/staking.mdx new file mode 100644 index 0000000..75bc23f --- /dev/null +++ b/network/WCT-token/staking.mdx @@ -0,0 +1,188 @@ +--- +title: "WCT Staking" +--- + +Staking WCT is the primary mechanism through which token holders engage with and support the network by locking their tokens in the protocol's smart contracts. This alignment of interests creates a more secure and participatory ecosystem. + +Staking WCT provides three key benefits: voting rights in protocol governance, eligibility for performance rewards programs, and weekly WCT token rewards distributions. These mechanisms allow token holders to participate actively in the protocol while earning additional rewards. + + +The staking model now uses perpetual positions with user-triggered unlocking. You select an unlock duration up front (from a discrete set of options), but your position stays fully locked and at full stakeweight until you decide to initiate unlock. When you initiate unlock, stakeweight decays linearly over the chosen duration. + + +## Stake Weight + +Stakeweight is the measure used to determine a staker's position within the network at any given time. It is derived from two factors: the amount of WCT staked and the remaining lock time of the position. Rewards are distributed proportionally to each staker's share of total network stakeweight, and governance voting power is directly proportional to stakeweight. + +### States + +- **Locked (Perpetual):** Your position is active and not unlocking. While locked, the remaining lock time is fixed at your selected unlock duration, so stakeweight does not decay. + +- **Unlocking:** You've initiated an unstake. Remaining lock time decreases linearly to zero over the selected unlock duration; stakeweight decays accordingly. When it reaches zero, the position becomes fully withdrawable. + +### Calculating Stake Weight + +The stakeweight calculation is: + + +$$ +\text{Stakeweight} = \frac{\text{Amount of WCT} \times \text{Remaining Lock Time}}{209} +$$ + +Where: + +- **Amount of WCT:** Number of WCT tokens staked. +- **Remaining Lock Time:** + - **Locked state:** fixed at the **selected unlock duration** (e.g., 52 weeks). + - **Unlocking state:** decays linearly from the selected duration down to 0. +- **209:** Normalization constant for maximum stakeweight. + +For example, if a user stakes **1,000 WCT** and has selected a **40-week** unlock duration: + +- **Locked:** +$$ +\text{Stakeweight} = \frac{1000 \times 40}{209} \approx 191.39 +$$ + +- **Unlocking (halfway through, 20 weeks remaining):** +$$ +\text{Stakeweight} = \frac{1000 \times 20}{209} \approx 95.69 +$$ + + +While the stakeweight formula uses 209 weeks as the denominator, the current maximum unlock duration you can select is 104 weeks (≈ 2 years). + + + +Due to timestamp rounding, 104 weeks is used to represent 2 years. + + +### Stakeweight Decay (only during Unlocking) + +In the **Locked** state, stakeweight remains constant (no decay). + +In the **Unstaking** state, **remaining lock time**—and thus stakeweight—decays linearly week by week until it reaches 0 at the end of the unlock duration. + +## How to Stake WCT + +To stake WCT, visit [**https://app.walletconnect.com/stake**](https://app.walletconnect.com/stake) + + + + + + +The staking flow involves: +- Connect your wallet. +- Select **Stake**. +- Enter the **amount** you want to stake. +- Set the **duration** (this sets the **unstaking period** used when you later exit. The longer the duration, the higher the APY). +- **Approve** the amount — sign the approval with your wallet. +- **Stake** — sign the staking transaction with your wallet. + + +Your position is perpetually locked until you initiate unstaking. Choosing the unlock duration does not exit you; it sets the duration for a future exit. + + +## Discrete Unlock Duration Options + +To simplify decisions, the unlock duration must be one of: + +- **4, 8, 12, 26, 52, 78, or 104 weeks** (≈ 1–24 months) + +You can change your preset **while Locked**. The preset determines the **remaining lock time** used for stakeweight in the Locked state and the **length of the decay** once you initiate unstaking. + +## Staking Rewards Eligibility + +Rewards are distributed **weekly**. Each reward period **starts and ends on Thursday (00:00 GMT)**. + +To be eligible for a given week: +- Your position must **exist before Thursday 00:00 GMT** of that week; and +- Your position must have **Remaining Lock Time > 0**: + - **Locked:** always eligible. + - **Unlocking:** eligible while **≥ 1 week** remains (once it hits 0, eligibility ends). + +### Examples + +#### Eligible (Locked) +Created on **Wednesday 23:00 GMT**, preset **4 weeks**, not unlocking yet → Eligible for the week starting Thursday 00:00 GMT (position existed before the cutoff and is Locked). + +#### Eligible (Unlocking with ≥ 1 week) +Initiate unlock on **Monday** with preset **12 weeks** → For subsequent Thursdays while ≥ 1 week remains, the position is eligible (with a decaying stakeweight). + +#### Ineligible (Too late) +Create a new position at **Thursday 01:00 GMT** → Not eligible for that week (created after the cutoff). + +## Position Lifecycle + +### Initiating Unstake (Exit) + +When you're ready to exit: + +1. Go to [**https://app.walletconnect.com/stake**](https://app.walletconnect.com/stake) +2. Connect your wallet +3. Click **Unstake** +4. After the unstaking duration ends, you will be able to withdraw your locked tokens. + +From that point: +- Remaining lock time **decays linearly** from the unstaking duration selected when the position was created to **0**. +- Stakeweight decays accordingly. +- When it reaches **0**, the position becomes **fully withdrawable**. + + + + + +### Re-Locking (Stop Decay) + +- While **Unstaking**, you can **Update** your position to return to the **Locked** state. +- When updating your position, you must select a preset that is **≥ the current remaining time** (you can make it **longer**, but not shorter). +- Decay stops immediately; stakeweight snaps back to the fixed value using the new preset. + +### Completed Unstake + +When remaining lock time reaches **0**: +- Stakeweight and voting power become **0**. +- The position becomes **withdrawable** (full amount; partial withdrawals are not supported). +- After withdrawing, you may create a **new** staking position at any time. + +## Updating Your Position + +Users can update **active staking** positions at any time: + +### Adding WCT + +Increase your position by depositing more WCT. The added tokens adopt your position's current preset. + + + +### Changing the Unlock Duration Preset + +While **Staked**, you can change your duration to any of the discrete options **greater than or equal to** your current remaining time. This **does not** initiate unlocking; it only changes the **fixed remaining lock time** used for stakeweight in the Locked state and sets the future unlock duration. + + + +## Claiming Rewards + +Every Thursday, WCT rewards are distributed to eligible positions based on their proportional share of total network stakeweight. If your position's stakeweight represents 5% of the total, you'll receive approximately 5% of that week's distribution. + +$$ +\text{Reward Share} = \frac{\text{Position Stakeweight}}{\text{Total Network Stakeweight}} +$$ + +You can claim rewards on your dashboard at any time. When claiming, you may **re-stake** rewards back into the position to grow stakeweight. + + +Checking in weekly lets you claim and optionally re-stake rewards and adjust your preset, helping you maintain optimal stakeweight. + + +## Migration Path (Existing Positions) + +To avoid disrupting existing positions at upgrade time: + +- Existing positions were treated as **already unlocking** under the new contracts, so they continue to decay and become withdrawable on their original timelines without action required. +- If you prefer the new **perpetual** behavior, select **Update**, choose a duration (you'll be able to select only durations **greater than or equal to** your current remaining lock), then remain **Locked** until you choose to initiate a new unlock. + +## Backwards Compatibility / Optionality + +Power users can still mimic the old behavior by **initiating unlock immediately after staking**, which starts decay from day one (as before). Otherwise, you enjoy constant stakeweight until you decide to exit. \ No newline at end of file diff --git a/network/apps/javascript/installation.mdx b/network/apps/javascript/installation.mdx new file mode 100644 index 0000000..a309bb3 --- /dev/null +++ b/network/apps/javascript/installation.mdx @@ -0,0 +1,472 @@ +--- +title: Installation +sidebarTitle: JavaScript +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +WalletConnect App SDK is chain agnostic and provides seamless integration with several blockchain ecosystems. WalletConnect App SDK when combined with Universal Provider library enables compatibility across any blockchain protocol. + +## Pre-requisites + +This section is to inform you about the pre-requisites for integrating WalletConnect as an App with JavaScript (vanilla JS). + +### Cloud Configuration + +Create a new project on WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. You will need this project ID to initialize WalletConnect in your project (app). + + + +### Allowlist + +To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings. + +The allowlist supports a list of origins in the format `[scheme://]`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply. + +Examples of possible origins in the allowlist: +- `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com` +- `https://example.com` - allows `https://example.com` but not `http://example.com` +- `https://*.example.com` - allows `https://www.example.com` but not `https://example.com` + + +Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed. + + +## Installation + + +```bash npm +npm install @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Yarn +yarn add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Bun +bun add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash pnpm +pnpm add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + + + +## Implementation + +Here is a sample implementation of WalletConnect App SDK with JavaScript. You can also check the example repository below. + + +Check the WalletConnect App SDK JavaScript example + + +For a quick integration of WalletConnect App SDK you can use the `UniversalConnector` class. Which simplifies the integration of WalletConnect App SDK by providing a single interface for all the blockchain protocols. + +You can configure the Universal Connector with the networks you want to support. +For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs. + +We recommend creating a config file to establish a singleton instance for the Universal Connector: + + + +```tsx Generic Example +import { UniversalConnector } from '@reown/appkit-universal-connector' + +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const suiMainnet = { + id: 784, + chainNamespace: 'sui', + caipNetworkId: 'sui:mainnet', + name: 'Sui', + nativeCurrency: { name: 'SUI', symbol: 'SUI', decimals: 9 }, + rpcUrls: { default: { http: ['https://fullnode.mainnet.sui.io:443'] } } +} + +export const networks = [suiMainnet] + +export let universalConnector + +export async function getUniversalConnector() { + if (!universalConnector) { + universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['sui_signPersonalMessage'], + chains: [suiMainnet], + events: [], + namespace: 'sui' + } + ] + }) + } + return universalConnector +} +``` + +```tsx Stacks Example +import { UniversalConnector } from '@reown/appkit-universal-connector' + +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const stacksMainnet = { + id: 'stacks-mainnet', + chainNamespace: 'stacks', + caipNetworkId: 'stacks:1', + name: 'Stacks Mainnet', + nativeCurrency: { name: 'STX', symbol: 'STX', decimals: 6 }, + rpcUrls: { default: { http: ['https://stacks-node-api.mainnet.stacks.co'] } } // Example Stacks Mainnet RPC URL +} + +export const networks = [stacksMainnet] + +export let universalConnector + +export async function getUniversalConnector() { + if (!universalConnector) { + universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['stx_signMessage', 'stx_signTransaction', 'stx_getAccounts', 'stx_getAddresses', 'stx_callContract', 'stx_deployContract', 'sendTransfer', 'getAddresses'], + chains: [stacksMainnet], + events: ['stx_chainChanged', 'stx_accountsChanged'], + namespace: 'stacks' + } + ] + }) + } + return universalConnector +} +``` + +```tsx TON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tonMainnet: CustomCaipNetwork<'ton'> = { + id: -239, + chainNamespace: 'ton' as const, + caipNetworkId: 'ton:-239', + name: 'TON', + nativeCurrency: { name: 'TON', symbol: 'TON', decimals: 9 }, + rpcUrls: { default: { http: ['https://toncenter.com/api/v2/jsonRPC'] } } +} + +export const networks = [tonMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['ton_signData'], + chains: [tonMainnet as CustomCaipNetwork], + events: [], + namespace: 'ton' + } + ] + }) + + return universalConnector +} +``` + +```tsx TRON Example +import { UniversalConnector } from '@reown/appkit-universal-connector' + +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tronMainnet = { + id: '0x2b6653dc', + chainNamespace: 'tron', + caipNetworkId: 'tron:0x2b6653dc', + name: 'Tron Mainnet', + nativeCurrency: { name: 'TRX', symbol: 'TRX', decimals: 6 }, + rpcUrls: { default: { http: ['https://api.trongrid.io'] } } +} + +export const networks = [tronMainnet] + +export let universalConnector + +export async function getUniversalConnector() { + if (!universalConnector) { + universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['tron_signTransaction', 'tron_signMessage'], + chains: [tronMainnet], + events: [], + namespace: 'tron' + } + ] + }) + } + return universalConnector +} +``` + + + +In the main.js file you can add: + +```tsx +import { getUniversalConnector } from './config/appKit.js' + +async function setup() { + const universalConnector = await getUniversalConnector() + + // check if session is already connected + if (universalConnector?.provider.session) { + session = universalConnector?.provider.session + } +} + +setup() +``` + + + +## Trigger the modal +To open the WalletConnect modal you need to call the `connect` function from the Universal Connector. +For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs. + +```tsx + +.... + +

+ +``` + +## Smart Contract Interaction + + + + +[Wagmi hooks](https://wagmi.sh/react/api/hooks/useReadContract) can help us interact with wallets and smart contracts: + +```tsx +import { useReadContract } from "wagmi"; +import { USDTAbi } from "../abi/USDTAbi"; + +const USDTAddress = "0x..."; + +function App() { + const result = useReadContract({ + abi: USDTAbi, + address: USDTAddress, + functionName: "totalSupply", + }); +} +``` + +Read more about Wagmi hooks for smart contract interaction [here](https://wagmi.sh/react/hooks/useReadContract). + + + + +[Ethers](https://docs.ethers.org/v6/) can help us interact with wallets and smart contracts: + +```tsx +import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/react"; +import { BrowserProvider, Contract, formatUnits } from "ethers"; + +const USDTAddress = "0x617f3112bf5397D0467D315cC709EF968D9ba546"; + +// The ERC-20 Contract ABI, which is a common contract interface +// for tokens (this is the Human-Readable ABI format) +const USDTAbi = [ + "function name() view returns (string)", + "function symbol() view returns (string)", + "function balanceOf(address) view returns (uint)", + "function transfer(address to, uint amount)", + "event Transfer(address indexed from, address indexed to, uint amount)", +]; + +function Components() { + const { address, isConnected } = useAppKitAccount(); + const { walletProvider } = useAppKitProvider("eip155"); + + async function getBalance() { + if (!isConnected) throw Error("User disconnected"); + + const ethersProvider = new BrowserProvider(walletProvider); + const signer = await ethersProvider.getSigner(); + // The Contract object + const USDTContract = new Contract(USDTAddress, USDTAbi, signer); + const USDTBalance = await USDTContract.balanceOf(address); + + console.log(formatUnits(USDTBalance, 18)); + } + + return ; +} +``` + + + + [@Solana/web3.js](https://solana.com/docs/clients/javascript) library allows for seamless interaction with wallets and smart contracts on the Solana blockchain. + +For a practical example of how it works, you can refer to our [lab dApp](https://lab.reown.com/appkit/?name=solana). + +```tsx +import { + SystemProgram, + PublicKey, + Keypair, + Transaction, + TransactionInstruction, + LAMPORTS_PER_SOL +} from '@solana/web3.js' +import { useAppKitAccount, useAppKitProvider } from '@reown/appkit/react' +import { useAppKitConnection, type Provider } from '@reown/appkit-adapter-solana/react' + +function deserializeCounterAccount(data?: Buffer): { count: number } { + if (data?.byteLength !== 8) { + throw Error('Need exactly 8 bytes to deserialize counter') + } + + return { + count: Number(data[0]) + } +} + +const { address } = useAppKitAccount() +const { connection } = useAppKitConnection() +const { walletProvider } = useAppKitProvider('solana') + +async function onIncrementCounter() { + const PROGRAM_ID = new PublicKey('Cb5aXEgXptKqHHWLifvXu5BeAuVLjojQ5ypq6CfQj1hy') + + const counterKeypair = Keypair.generate() + const counter = counterKeypair.publicKey + + const balance = await connection.getBalance(walletProvider.publicKey) + if (balance < LAMPORTS_PER_SOL / 100) { + throw Error('Not enough SOL in wallet') + } + + const COUNTER_ACCOUNT_SIZE = 8 + const allocIx: TransactionInstruction = SystemProgram.createAccount({ + fromPubkey: walletProvider.publicKey, + newAccountPubkey: counter, + lamports: await connection.getMinimumBalanceForRentExemption(COUNTER_ACCOUNT_SIZE), + space: COUNTER_ACCOUNT_SIZE, + programId: PROGRAM_ID + }) + + const incrementIx: TransactionInstruction = new TransactionInstruction({ + programId: PROGRAM_ID, + keys: [ + { + pubkey: counter, + isSigner: false, + isWritable: true + } + ], + data: Buffer.from([0x0]) + }) + + const tx = new Transaction().add(allocIx).add(incrementIx) + + tx.feePayer = walletProvider.publicKey + tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash + + await walletProvider.signAndSendTransaction(tx, [counterKeypair]) + + const counterAccountInfo = await connection.getAccountInfo(counter, { + commitment: 'confirmed' + }) + + if (!counterAccountInfo) { + throw new Error('Expected counter account to have been created') + } + + const counterAccount = deserializeCounterAccount(counterAccountInfo?.data) + + if (counterAccount.count !== 1) { + throw new Error('Expected count to have been 1') + } + + console.log(`[alloc+increment] count is: ${counterAccount.count}`); +} +``` + + + diff --git a/network/apps/next/installation.mdx b/network/apps/next/installation.mdx new file mode 100644 index 0000000..1fb2638 --- /dev/null +++ b/network/apps/next/installation.mdx @@ -0,0 +1,469 @@ +--- +title: Installation +sidebarTitle: Next.js +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +WalletConnect App SDK is chain agnostic and provides seamless integration with several blockchain ecosystems. WalletConnect App SDK when combined with Universal Provider library enables compatibility across any blockchain protocol. + +## Pre-requisites + +This section is to inform you about the pre-requisites for integrating WalletConnect as an App with Next.js. + +### Cloud Configuration + +Create a new project on WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. You will need this project ID to initialize WalletConnect in your project (app). + + + +### Allowlist + +To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings. + +The allowlist supports a list of origins in the format `[scheme://]`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply. + +Examples of possible origins in the allowlist: +- `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com` +- `https://example.com` - allows `https://example.com` but not `http://example.com` +- `https://*.example.com` - allows `https://www.example.com` but not `https://example.com` + + +Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed. + + +## Installation + + +```bash npm +npm install @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Yarn +yarn add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Bun +bun add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash pnpm +pnpm add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + + + +## Implementation + +For a quick integration of WalletConnect App SDK you can use the `UniversalConnector` class. Which simplifies the integration of WalletConnect App SDK by providing a single interface for all the blockchain protocols. + +You can configure the Universal Connector with the networks you want to support. +For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs. + +We recommend creating a config file to establish a singleton instance for the Universal Connector: + + + +```tsx Generic Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const suiMainnet: CustomCaipNetwork<'sui'> = { + id: 784, + chainNamespace: 'sui' as const, + caipNetworkId: 'sui:mainnet', + name: 'Sui', + nativeCurrency: { name: 'SUI', symbol: 'SUI', decimals: 9 }, + rpcUrls: { default: { http: ['https://fullnode.mainnet.sui.io:443'] } } +} + +export const networks = [suiMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['sui_signPersonalMessage'], + chains: [suiMainnet as CustomCaipNetwork], + events: [], + namespace: 'sui' + } + ] + }) + + return universalConnector +} +``` + +```tsx Stacks Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { InferredCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const stacksMainnet: InferredCaipNetwork = { + id: 'stacks-mainnet', + chainNamespace: 'stacks' as const, + caipNetworkId: 'stacks:1', + name: 'Stacks Mainnet', + nativeCurrency: { name: 'STX', symbol: 'STX', decimals: 6 }, + rpcUrls: { default: { http: ['https://stacks-node-api.mainnet.stacks.co'] } } // Example Stacks Mainnet RPC URL +} + +export const networks = [stacksMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['stx_signMessage', 'stx_signTransaction', 'stx_getAccounts', 'stx_getAddresses', 'stx_callContract', 'stx_deployContract', 'sendTransfer', 'getAddresses'], + chains: [stacksMainnet as InferredCaipNetwork], + events: ['stx_chainChanged', 'stx_accountsChanged'], + namespace: 'stacks' + } + ] + }) + + return universalConnector +} +``` + +```tsx TON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tonMainnet: CustomCaipNetwork<'ton'> = { + id: -239, + chainNamespace: 'ton' as const, + caipNetworkId: 'ton:-239', + name: 'TON', + nativeCurrency: { name: 'TON', symbol: 'TON', decimals: 9 }, + rpcUrls: { default: { http: ['https://toncenter.com/api/v2/jsonRPC'] } } +} + +export const networks = [tonMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['ton_signData'], + chains: [tonMainnet as CustomCaipNetwork], + events: [], + namespace: 'ton' + } + ] + }) + + return universalConnector +} +``` + +```tsx TRON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tronMainnet: CustomCaipNetwork<'tron'> = { + id: '0x2b6653dc', + chainNamespace: 'tron' as const, + caipNetworkId: 'tron:0x2b6653dc', + name: 'Tron Mainnet', + nativeCurrency: { name: 'TRX', symbol: 'TRX', decimals: 6 }, + rpcUrls: { default: { http: ['https://api.trongrid.io'] } } +} + +export const networks = [tronMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['tron_signTransaction', 'tron_signMessage'], + chains: [tronMainnet as CustomCaipNetwork], + events: [], + namespace: 'tron' + } + ] + }) + + return universalConnector +} +``` + + + +In the App.tsx file you can add : + +```tsx +import { useState, useEffect } from 'react' +import { getUniversalConnector } from './config' // previous config file +import { UniversalConnector } from '@reown/appkit-universal-connector' + +export function App() { + const [universalConnector, setUniversalConnector] = useState() + const [session, setSession] = useState() + + + // Initialize the Universal Connector on component mount + useEffect(() => { + getUniversalConnector().then(setUniversalConnector) + }, []) + + // Set the session state in case it changes + useEffect(() => { + setSession(universalConnector?.provider.session) + }, [universalConnector?.provider.session]) +``` + + +## Trigger the modal + +To open the WalletConnect modal you need to call the `connect` function from the Universal Connector. + +```tsx + // get the session from the universal connector + const handleConnect = async () => { + if (!universalConnector) { + return + } + + const { session: providerSession } = await universalConnector.connect() + setSession(providerSession) + }; + + // disconnect the universal connector + const handleDisconnect = async () => { + if (!universalConnector) { + return + } + await universalConnector.disconnect() + setSession(null) + }; + + ... + + return ( + ( +
+ + +
+ ) +``` + +## Smart Contract Interaction + + + + +[Wagmi hooks](https://wagmi.sh/react/api/hooks/useReadContract) can help us interact with wallets and smart contracts: + +```tsx +import { useReadContract } from "wagmi"; +import { USDTAbi } from "../abi/USDTAbi"; + +const USDTAddress = "0x..."; + +function App() { + const result = useReadContract({ + abi: USDTAbi, + address: USDTAddress, + functionName: "totalSupply", + }); +} +``` + +Read more about Wagmi hooks for smart contract interaction [here](https://wagmi.sh/react/hooks/useReadContract). + + + + +[Ethers](https://docs.ethers.org/v6/) can help us interact with wallets and smart contracts: + +```tsx +import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/react"; +import { BrowserProvider, Contract, formatUnits } from "ethers"; + +const USDTAddress = "0x617f3112bf5397D0467D315cC709EF968D9ba546"; + +// The ERC-20 Contract ABI, which is a common contract interface +// for tokens (this is the Human-Readable ABI format) +const USDTAbi = [ + "function name() view returns (string)", + "function symbol() view returns (string)", + "function balanceOf(address) view returns (uint)", + "function transfer(address to, uint amount)", + "event Transfer(address indexed from, address indexed to, uint amount)", +]; + +function Components() { + const { address, isConnected } = useAppKitAccount(); + const { walletProvider } = useAppKitProvider("eip155"); + + async function getBalance() { + if (!isConnected) throw Error("User disconnected"); + + const ethersProvider = new BrowserProvider(walletProvider); + const signer = await ethersProvider.getSigner(); + // The Contract object + const USDTContract = new Contract(USDTAddress, USDTAbi, signer); + const USDTBalance = await USDTContract.balanceOf(address); + + console.log(formatUnits(USDTBalance, 18)); + } + + return ; +} +``` + + + + [@Solana/web3.js](https://solana.com/docs/clients/javascript) library allows for seamless interaction with wallets and smart contracts on the Solana blockchain. + +For a practical example of how it works, you can refer to our [lab dApp](https://lab.reown.com/appkit/?name=solana). + +```tsx +import { + SystemProgram, + PublicKey, + Keypair, + Transaction, + TransactionInstruction, + LAMPORTS_PER_SOL +} from '@solana/web3.js' +import { useAppKitAccount, useAppKitProvider } from '@reown/appkit/react' +import { useAppKitConnection, type Provider } from '@reown/appkit-adapter-solana/react' + +function deserializeCounterAccount(data?: Buffer): { count: number } { + if (data?.byteLength !== 8) { + throw Error('Need exactly 8 bytes to deserialize counter') + } + + return { + count: Number(data[0]) + } +} + +const { address } = useAppKitAccount() +const { connection } = useAppKitConnection() +const { walletProvider } = useAppKitProvider('solana') + +async function onIncrementCounter() { + const PROGRAM_ID = new PublicKey('Cb5aXEgXptKqHHWLifvXu5BeAuVLjojQ5ypq6CfQj1hy') + + const counterKeypair = Keypair.generate() + const counter = counterKeypair.publicKey + + const balance = await connection.getBalance(walletProvider.publicKey) + if (balance < LAMPORTS_PER_SOL / 100) { + throw Error('Not enough SOL in wallet') + } + + const COUNTER_ACCOUNT_SIZE = 8 + const allocIx: TransactionInstruction = SystemProgram.createAccount({ + fromPubkey: walletProvider.publicKey, + newAccountPubkey: counter, + lamports: await connection.getMinimumBalanceForRentExemption(COUNTER_ACCOUNT_SIZE), + space: COUNTER_ACCOUNT_SIZE, + programId: PROGRAM_ID + }) + + const incrementIx: TransactionInstruction = new TransactionInstruction({ + programId: PROGRAM_ID, + keys: [ + { + pubkey: counter, + isSigner: false, + isWritable: true + } + ], + data: Buffer.from([0x0]) + }) + + const tx = new Transaction().add(allocIx).add(incrementIx) + + tx.feePayer = walletProvider.publicKey + tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash + + await walletProvider.signAndSendTransaction(tx, [counterKeypair]) + + const counterAccountInfo = await connection.getAccountInfo(counter, { + commitment: 'confirmed' + }) + + if (!counterAccountInfo) { + throw new Error('Expected counter account to have been created') + } + + const counterAccount = deserializeCounterAccount(counterAccountInfo?.data) + + if (counterAccount.count !== 1) { + throw new Error('Expected count to have been 1') + } + + console.log(`[alloc+increment] count is: ${counterAccount.count}`); +} +``` + + + diff --git a/network/apps/overview.mdx b/network/apps/overview.mdx new file mode 100644 index 0000000..f34e127 --- /dev/null +++ b/network/apps/overview.mdx @@ -0,0 +1,130 @@ +--- +title: "WalletConnect for Apps" +sidebarTitle: Overview +--- + +## **Your Gateway to the WalletConnect Network** + + +**We highly recommend using one of our SDK partners to integrate WalletConnect into your app.** + + +The **WalletConnect App SDK** is the foundational gateway for apps to access the **WalletConnect Network,** the decentralized connectivity layer for the financial internet. + +With a single integration, developers can connect to **700+ wallets** and **65,000+ apps** across **EVM, Solana, Bitcoin**, and **any network with a CAIP-25 namespace**, while preserving privacy, composability, and user choice. + +**Built on open standards** and powered by a decentralized relay network, WalletConnect unlocks secure and cross-chain wallet connections for apps across devices and platforms. + +Whether you’re building for DeFi, gaming, payments, or identity, WalletConnect provides the essential building block for **trusted wallet-to-app experiences**, all backed by the **infrastructure that powers the financial internet**. + +## **Powering leading SDKs across Web3** + +The WalletConnect App SDK is already embedded in some of the most widely-used SDKs in the ecosystem - powering everything from onboarding to payments. + +## **Who is it for?** + +- **App developers** who want to connect wallets quickly and securely +- **SDK builders** who want a powerful foundation for wallet connectivity +- **Web3 platforms** scaling across chains and wallets + +If your product needs to talk to wallets, the App SDK is your starting point. + +## What does WalletConnect have to offer for Apps? + +At its core, the WalletConnect handles the most critical UX layer of any onchain app: **wallet connection**. + +✅ **Prebuilt modal UX** for connecting wallets + +✅ **Chain-agnostic support** across EVM, Solana, Bitcoin, and more + +✅ **Built-in compatibility** with 500+ wallets + +✅ **Native, embedded UI** - no iframes, no redirects + +✅ **Customizable and composable** - use standalone or extend with your own flows + +It’s the fastest way to build reliable wallet connectivity, with none of the versioning, RPC mismatches, or fragmented logic that plague homegrown solutions. + +## Demo + + + +--- + +## How to Integrate WalletConnect into your App + +There are **two core pathways to integrate WalletConnect** into your app: + +1. Via an SDK partner that has already integrated WalletConnect into their SDK. +2. Standalone integration of WalletConnect. + +Below, you can find instructions and information for both pathways. + +## Integrate WalletConnect via an SDK Partner + +First, we need to cover what exactly is an SDK and how projects can use them to integrate WalletConnect into their app. + +### What is an SDK? + +An SDK is a software development kit that provides a set of tools, libraries, and documentation for developers to build applications. It is a collection of code, tools, and resources that help developers build applications faster and easier. + +In this context, SDKs are pre-packaged developer tools that abstract away the underlying protocol, i.e. WalletConnect, and provide a simplified integration path for apps and wallets, making wallet connectivity fast, reliable, and developer-friendly. + +### 🛠 Most Popular SDKs built on top of WalletConnect + +- [**Reown AppKit**](https://reown.com/appkit) - A modular UX engine for onboarding, payments, and wallet interaction. Used in 286M+ sessions and 10B+ RPC calls . +- [**Privy**](https://www.privy.io/) - Secure wallet infrastructure that simplifies identity, session handling, and embedded wallets. +- [**Dynamic**](https://www.dynamic.xyz/) - All-in-one authentication and wallet SDK for web3 apps across mobile and web. +- [**ConnectKit**](https://family.co/connectkit) - Beautiful React components built for WalletConnect connections. +- [**RainbowKit**](https://www.rainbowkit.com/) - Customizable wallet connection UI optimized for Ethereum and WalletConnect. +- [**Canton dApp SDK**](https://github.com/hyperledger-labs/splice-wallet-kernel/tree/main/sdk/dapp-sdk) - Browser SDK from the [Splice Wallet Kernel](https://github.com/hyperledger-labs/splice-wallet-kernel) for building dApps on the [Canton Network](https://www.canton.network/). Implements the [CIP-103](https://github.com/canton-foundation/cips/blob/main/cip-0103/cip-0103.md) dApp API with multi-transport support (HTTP, `postMessage`) and an EIP-1193-style `window.canton` provider. + +These SDKs demonstrate what’s possible with the App SDK as a base layer and how it can be extended to suit your product, stack, and user flow. + +### SDK Chain Compatibility + +Below you can find the chain compatibility for the most popular SDKs built on top of WalletConnect. + +| SDK | Networks / Chains Supported | +|------------------|----------------------------------------------------| +| **Reown AppKit** | EVM, Solana, Bitcoin, Polkadot, Cosmos and all other networks with a CAIP-25 namespace | +| **Privy** | EVM, Solana, Bitcoin | +| **Dynamic** | EVM, Solana, Bitcoin, Flow, StarkNet, Sui, Cosmos, Algorand, Spark | +| **ConnectKit** | EVM | +| **RainbowKit** | EVM | +| **Canton dApp SDK** | Canton Network | + +## Standalone Integration of WalletConnect as an App + +If you do not wish to use an SDK partner, you can integrate WalletConnect directly into your app. Please refer to the corresponding installation guide for each framework given below. + + + + Get started with WalletConnect as an App in React. + + + + Get started with WalletConnect as an App in Next.js. + + + + Get started with WalletConnect as an App in Vue. + + + + Get started with WalletConnect as an App in JavaScript. + + + +### Chains Supported by WalletConnect + +Please refer to the [Chains Supported](https://docs.reown.com/cloud/chains/chain-list) page for the list of chains supported by WalletConnect. + +### RPCs and Chain Specific Methods + +Please refer to the **RPC Reference** dropdown under the [Multi-Chain](https://docs.reown.com/advanced/multichain/rpc-reference/) section for the list of RPCs and chain specific methods supported by WalletConnect. \ No newline at end of file diff --git a/network/apps/react/installation.mdx b/network/apps/react/installation.mdx new file mode 100644 index 0000000..035da2b --- /dev/null +++ b/network/apps/react/installation.mdx @@ -0,0 +1,483 @@ +--- +title: Installation +sidebarTitle: React +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +WalletConnect App SDK is chain agnostic and provides seamless integration with several blockchain ecosystems. WalletConnect App SDK when combined with Universal Provider library enables compatibility across any blockchain protocol. + +## Pre-requisites + +This section is to inform you about the pre-requisites for integrating WalletConnect as an App with React. + +### Cloud Configuration + +Create a new project on WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. You will need this project ID to initialize WalletConnect in your project (app). + + + +### Allowlist + +To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings. + +The allowlist supports a list of origins in the format `[scheme://]`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply. + +Examples of possible origins in the allowlist: +- `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com` +- `https://example.com` - allows `https://example.com` but not `http://example.com` +- `https://*.example.com` - allows `https://www.example.com` but not `https://example.com` + + +Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed. + + +## Installation + + + If you are setting up your React app, please **do not use** `npx create-react-app`, as it has been deprecated. Using it may cause dependency + issues. Instead, please use [Vite](https://vitejs.dev/guide/#scaffolding-your-first-vite-project) to + create your React app. You can set it up by running `npm create vite@latest`. + + + + + +```bash npm +npm install @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Yarn +yarn add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Bun +bun add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash pnpm +pnpm add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + + + +## Implementation + +Here is a sample implementation of WalletConnect App SDK with React. You can also check the example repository below. + + +Check the WalletConnect App SDK React example + + +For a quick integration of WalletConnect App SDK you can use the `UniversalConnector` class. Which simplifies the integration of WalletConnect App SDK by providing a single interface for all the blockchain protocols. + +You can configure the Universal Connector with the networks you want to support. +For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs. + +We recommend creating a config file to establish a singleton instance for the Universal Connector: + + + +```tsx Generic Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "b56e18d47c72ab683b10814fe9495694" // this is a public projectId only to use on localhost + +if (!projectId) { + throw new Error('Project ID is not defined') +} + +// you can configure your own network +const suiMainnet: CustomCaipNetwork<'sui'> = { + id: 784, + chainNamespace: 'sui' as const, + caipNetworkId: 'sui:mainnet', + name: 'Sui', + nativeCurrency: { name: 'SUI', symbol: 'SUI', decimals: 9 }, + rpcUrls: { default: { http: ['https://fullnode.mainnet.sui.io:443'] } } +} + +export const networks = [suiMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['sui_signPersonalMessage'], + chains: [suiMainnet as CustomCaipNetwork], + events: [], + namespace: 'sui' + } + ] + }) + + return universalConnector +} +``` + +```tsx Stacks Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { InferredCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const stacksMainnet: InferredCaipNetwork = { + id: 'stacks-mainnet', + chainNamespace: 'stacks' as const, + caipNetworkId: 'stacks:1', + name: 'Stacks Mainnet', + nativeCurrency: { name: 'STX', symbol: 'STX', decimals: 6 }, + rpcUrls: { default: { http: ['https://stacks-node-api.mainnet.stacks.co'] } } // Example Stacks Mainnet RPC URL +} + +export const networks = [stacksMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['stx_signMessage', 'stx_signTransaction', 'stx_getAccounts', 'stx_getAddresses', 'stx_callContract', 'stx_deployContract', 'sendTransfer', 'getAddresses'], + chains: [stacksMainnet as InferredCaipNetwork], + events: ['stx_chainChanged', 'stx_accountsChanged'], + namespace: 'stacks' + } + ] + }) + + return universalConnector +} +``` + +```tsx TON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tonMainnet: CustomCaipNetwork<'ton'> = { + id: -239, + chainNamespace: 'ton' as const, + caipNetworkId: 'ton:-239', + name: 'TON', + nativeCurrency: { name: 'TON', symbol: 'TON', decimals: 9 }, + rpcUrls: { default: { http: ['https://toncenter.com/api/v2/jsonRPC'] } } +} + +export const networks = [tonMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['ton_signData'], + chains: [tonMainnet as CustomCaipNetwork], + events: [], + namespace: 'ton' + } + ] + }) + + return universalConnector +} +``` + +```tsx TRON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tronMainnet: CustomCaipNetwork<'tron'> = { + id: '0x2b6653dc', + chainNamespace: 'tron' as const, + caipNetworkId: 'tron:0x2b6653dc', + name: 'Tron Mainnet', + nativeCurrency: { name: 'TRX', symbol: 'TRX', decimals: 6 }, + rpcUrls: { default: { http: ['https://api.trongrid.io'] } } +} + +export const networks = [tronMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['tron_signTransaction', 'tron_signMessage'], + chains: [tronMainnet as CustomCaipNetwork], + events: [], + namespace: 'tron' + } + ] + }) + + return universalConnector +} +``` + + + +In the App.tsx file you can add : + +```tsx +import { useState, useEffect } from 'react' +import { getUniversalConnector } from './config' // previous config file +import { UniversalConnector } from '@reown/appkit-universal-connector' + +export function App() { + const [universalConnector, setUniversalConnector] = useState() + const [session, setSession] = useState() + + + // Initialize the Universal Connector on component mount + useEffect(() => { + getUniversalConnector().then(setUniversalConnector) + }, []) + + // Set the session state in case it changes + useEffect(() => { + setSession(universalConnector?.provider.session) + }, [universalConnector?.provider.session]) +``` + + +## Trigger the modal + +To open the WalletConnect modal you need to call the `connect` function from the Universal Connector. + +```tsx + // get the session from the universal connector + const handleConnect = async () => { + if (!universalConnector) { + return + } + + const { session: providerSession } = await universalConnector.connect() + setSession(providerSession) + }; + + // disconnect the universal connector + const handleDisconnect = async () => { + if (!universalConnector) { + return + } + await universalConnector.disconnect() + setSession(null) + }; + + ... + + return ( + ( +
+ + +
+ ) +``` + +## Smart Contract Interaction + + + + +[Wagmi hooks](https://wagmi.sh/react/api/hooks/useReadContract) can help us interact with wallets and smart contracts: + +```tsx +import { useReadContract } from "wagmi"; +import { USDTAbi } from "../abi/USDTAbi"; + +const USDTAddress = "0x..."; + +function App() { + const result = useReadContract({ + abi: USDTAbi, + address: USDTAddress, + functionName: "totalSupply", + }); +} +``` + +Read more about Wagmi hooks for smart contract interaction [here](https://wagmi.sh/react/hooks/useReadContract). + + + + +[Ethers](https://docs.ethers.org/v6/) can help us interact with wallets and smart contracts: + +```tsx +import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/react"; +import { BrowserProvider, Contract, formatUnits } from "ethers"; + +const USDTAddress = "0x617f3112bf5397D0467D315cC709EF968D9ba546"; + +// The ERC-20 Contract ABI, which is a common contract interface +// for tokens (this is the Human-Readable ABI format) +const USDTAbi = [ + "function name() view returns (string)", + "function symbol() view returns (string)", + "function balanceOf(address) view returns (uint)", + "function transfer(address to, uint amount)", + "event Transfer(address indexed from, address indexed to, uint amount)", +]; + +function Components() { + const { address, isConnected } = useAppKitAccount(); + const { walletProvider } = useAppKitProvider("eip155"); + + async function getBalance() { + if (!isConnected) throw Error("User disconnected"); + + const ethersProvider = new BrowserProvider(walletProvider); + const signer = await ethersProvider.getSigner(); + // The Contract object + const USDTContract = new Contract(USDTAddress, USDTAbi, signer); + const USDTBalance = await USDTContract.balanceOf(address); + + console.log(formatUnits(USDTBalance, 18)); + } + + return ; +} +``` + + + + [@Solana/web3.js](https://solana.com/docs/clients/javascript) library allows for seamless interaction with wallets and smart contracts on the Solana blockchain. + +For a practical example of how it works, you can refer to our [lab dApp](https://lab.reown.com/appkit/?name=solana). + +```tsx +import { + SystemProgram, + PublicKey, + Keypair, + Transaction, + TransactionInstruction, + LAMPORTS_PER_SOL +} from '@solana/web3.js' +import { useAppKitAccount, useAppKitProvider } from '@reown/appkit/react' +import { useAppKitConnection, type Provider } from '@reown/appkit-adapter-solana/react' + +function deserializeCounterAccount(data?: Buffer): { count: number } { + if (data?.byteLength !== 8) { + throw Error('Need exactly 8 bytes to deserialize counter') + } + + return { + count: Number(data[0]) + } +} + +const { address } = useAppKitAccount() +const { connection } = useAppKitConnection() +const { walletProvider } = useAppKitProvider('solana') + +async function onIncrementCounter() { + const PROGRAM_ID = new PublicKey('Cb5aXEgXptKqHHWLifvXu5BeAuVLjojQ5ypq6CfQj1hy') + + const counterKeypair = Keypair.generate() + const counter = counterKeypair.publicKey + + const balance = await connection.getBalance(walletProvider.publicKey) + if (balance < LAMPORTS_PER_SOL / 100) { + throw Error('Not enough SOL in wallet') + } + + const COUNTER_ACCOUNT_SIZE = 8 + const allocIx: TransactionInstruction = SystemProgram.createAccount({ + fromPubkey: walletProvider.publicKey, + newAccountPubkey: counter, + lamports: await connection.getMinimumBalanceForRentExemption(COUNTER_ACCOUNT_SIZE), + space: COUNTER_ACCOUNT_SIZE, + programId: PROGRAM_ID + }) + + const incrementIx: TransactionInstruction = new TransactionInstruction({ + programId: PROGRAM_ID, + keys: [ + { + pubkey: counter, + isSigner: false, + isWritable: true + } + ], + data: Buffer.from([0x0]) + }) + + const tx = new Transaction().add(allocIx).add(incrementIx) + + tx.feePayer = walletProvider.publicKey + tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash + + await walletProvider.signAndSendTransaction(tx, [counterKeypair]) + + const counterAccountInfo = await connection.getAccountInfo(counter, { + commitment: 'confirmed' + }) + + if (!counterAccountInfo) { + throw new Error('Expected counter account to have been created') + } + + const counterAccount = deserializeCounterAccount(counterAccountInfo?.data) + + if (counterAccount.count !== 1) { + throw new Error('Expected count to have been 1') + } + + console.log(`[alloc+increment] count is: ${counterAccount.count}`); +} +``` + + + diff --git a/network/apps/vue/installation.mdx b/network/apps/vue/installation.mdx new file mode 100644 index 0000000..7a2cd38 --- /dev/null +++ b/network/apps/vue/installation.mdx @@ -0,0 +1,487 @@ +--- +title: Installation +sidebarTitle: Vue +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +WalletConnect App SDK is chain agnostic and provides seamless integration with several blockchain ecosystems. WalletConnect App SDK when combined with Universal Provider library enables compatibility across any blockchain protocol. + +## Pre-requisites + +This section is to inform you about the pre-requisites for integrating WalletConnect as an App with Vue + +### Cloud Configuration + +Create a new project on WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. You will need this project ID to initialize WalletConnect in your project (app). + + + +### Allowlist + +To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings. + +The allowlist supports a list of origins in the format `[scheme://]`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply. + +Examples of possible origins in the allowlist: +- `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com` +- `https://example.com` - allows `https://example.com` but not `http://example.com` +- `https://*.example.com` - allows `https://www.example.com` but not `https://example.com` + + +Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed. + + +## Installation + + + +```bash npm +npm install @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Yarn +yarn add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash Bun +bun add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + +```bash pnpm +pnpm add @reown/appkit @reown/appkit-universal-connector @reown/appkit-common ethers +``` + + + +## Implementation + +Here is a sample implementation of WalletConnect App SDK with Vue. You can also check the example repository below. + + +Check the WalletConnect App SDK Vue example + + +For a quick integration of WalletConnect App SDK you can use the `UniversalConnector` class. Which simplifies the integration of WalletConnect App SDK by providing a single interface for all the blockchain protocols. + +You can configure the Universal Connector with the networks you want to support. +For more information, please visit [RPC Reference](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc) section from our docs. + +We recommend creating a config file to establish a singleton instance for the Universal Connector: + + + +```tsx Generic Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const suiMainnet: CustomCaipNetwork<'sui'> = { + id: 784, + chainNamespace: 'sui' as const, + caipNetworkId: 'sui:mainnet', + name: 'Sui', + nativeCurrency: { name: 'SUI', symbol: 'SUI', decimals: 9 }, + rpcUrls: { default: { http: ['https://fullnode.mainnet.sui.io:443'] } } +} + +export const networks = [suiMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['sui_signPersonalMessage'], + chains: [suiMainnet as CustomCaipNetwork], + events: [], + namespace: 'sui' + } + ] + }) + + return universalConnector +} +``` + +```tsx Stacks Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { InferredCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +// you can configure your own network +const stacksMainnet: InferredCaipNetwork = { + id: 'stacks-mainnet', + chainNamespace: 'stacks' as const, + caipNetworkId: 'stacks:1', + name: 'Stacks Mainnet', + nativeCurrency: { name: 'STX', symbol: 'STX', decimals: 6 }, + rpcUrls: { default: { http: ['https://stacks-node-api.mainnet.stacks.co'] } } // Example Stacks Mainnet RPC URL +} + +export const networks = [stacksMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['stx_signMessage', 'stx_signTransaction', 'stx_getAccounts', 'stx_getAddresses', 'stx_callContract', 'stx_deployContract', 'sendTransfer', 'getAddresses'], + chains: [stacksMainnet as InferredCaipNetwork], + events: ['stx_chainChanged', 'stx_accountsChanged'], + namespace: 'stacks' + } + ] + }) + + return universalConnector +} +``` + +```tsx TON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tonMainnet: CustomCaipNetwork<'ton'> = { + id: -239, + chainNamespace: 'ton' as const, + caipNetworkId: 'ton:-239', + name: 'TON', + nativeCurrency: { name: 'TON', symbol: 'TON', decimals: 9 }, + rpcUrls: { default: { http: ['https://toncenter.com/api/v2/jsonRPC'] } } +} + +export const networks = [tonMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['ton_signData'], + chains: [tonMainnet as CustomCaipNetwork], + events: [], + namespace: 'ton' + } + ] + }) + + return universalConnector +} +``` + +```tsx TRON Example +import type { AppKitNetwork } from '@reown/appkit/networks' +import type { CustomCaipNetwork } from '@reown/appkit-common' +import { UniversalConnector } from '@reown/appkit-universal-connector' + +// Get projectId from https://dashboard.walletconnect.com +export const projectId = import.meta.env.VITE_PROJECT_ID || "YOUR_PROJECT_ID_HERE" // Replace with your actual project ID + +if (!projectId || projectId === "YOUR_PROJECT_ID_HERE") { + throw new Error('Project ID is not defined. Please set your project ID from the WalletConnect Dashboard.') +} + +const tronMainnet: CustomCaipNetwork<'tron'> = { + id: '0x2b6653dc', + chainNamespace: 'tron' as const, + caipNetworkId: 'tron:0x2b6653dc', + name: 'Tron Mainnet', + nativeCurrency: { name: 'TRX', symbol: 'TRX', decimals: 6 }, + rpcUrls: { default: { http: ['https://api.trongrid.io'] } } +} + +export const networks = [tronMainnet] as [AppKitNetwork, ...AppKitNetwork[]] + +export async function getUniversalConnector() { + const universalConnector = await UniversalConnector.init({ + projectId, + metadata: { + name: 'Universal Connector', + description: 'Universal Connector', + url: 'https://www.walletconnect.com', + icons: ['https://www.walletconnect.com/icon.png'] + }, + networks: [ + { + methods: ['tron_signTransaction', 'tron_signMessage'], + chains: [tronMainnet as CustomCaipNetwork], + events: [], + namespace: 'tron' + } + ] + }) + + return universalConnector +} +``` + + + +In de App.vue file you can add : + +```tsx + +``` + + +## Trigger the modal + +To open the WalletConnect modal you need to call the `connect` function from the Universal Connector. + +```tsx + + +... + +async handleConnect() { + if (!universalConnector) { + return + } + + const { session: providerSession } = await universalConnector.connect() + } +``` + +## Smart Contract Interaction + + + +[Wagmi actions](https://wagmi.sh/core/api/actions/readContract) can help us interact with wallets and smart contracts: + +```html + +``` + +Read more about Wagmi actions for smart contract interaction [here](https://wagmi.sh/core/actions/readContract). + + + + +[Ethers](https://docs.ethers.org/v6/) can help us interact with wallets and smart contracts: + +```html + +``` + + + + + [@Solana/web3.js](https://solana.com/docs/clients/javascript) library allows for seamless interaction with wallets and smart contracts on the Solana blockchain. + +For a practical example of how it works, you can refer to our [lab dApp](https://lab.reown.com/appkit/?name=solana). + +```tsx +import { ref } from 'vue'; +import { + SystemProgram, + PublicKey, + Keypair, + Transaction, + TransactionInstruction, + LAMPORTS_PER_SOL +} from '@solana/web3.js'; +import { useAppKitAccount, useAppKitProvider } from '@reown/appkit/vue' +import { useAppKitConnection, type Provider } from '@reown/appkit-adapter-solana/vue' + +export default { + setup() { + const counterMessage = ref(''); + const { address } = useAppKitAccount(); + const { connection } = useAppKitConnection() + const { walletProvider } = useAppKitProvider('solana') + + function deserializeCounterAccount(data) { + if (data?.byteLength !== 8) { + throw Error('Need exactly 8 bytes to deserialize counter'); + } + + return { + count: Number(data[0]) + }; + } + + async function onIncrementCounter() { + try { + const PROGRAM_ID = new PublicKey('Cb5aXEgXptKqHHWLifvXu5BeAuVLjojQ5ypq6CfQj1hy'); + + const counterKeypair = Keypair.generate(); + const counter = counterKeypair.publicKey; + + const balance = await connection.getBalance(walletProvider.publicKey); + if (balance < LAMPORTS_PER_SOL / 100) { + throw Error('Not enough SOL in wallet'); + } + + const COUNTER_ACCOUNT_SIZE = 8; + const allocIx = SystemProgram.createAccount({ + fromPubkey: walletProvider.publicKey, + newAccountPubkey: counter, + lamports: await connection.getMinimumBalanceForRentExemption(COUNTER_ACCOUNT_SIZE), + space: COUNTER_ACCOUNT_SIZE, + programId: PROGRAM_ID + }); + + const incrementIx = new TransactionInstruction({ + programId: PROGRAM_ID, + keys: [ + { + pubkey: counter, + isSigner: false, + isWritable: true + } + ], + data: Buffer.from([0x0]) + }); + + const tx = new Transaction().add(allocIx).add(incrementIx); + + tx.feePayer = walletProvider.publicKey; + tx.recentBlockhash = (await connection.getLatestBlockhash('confirmed')).blockhash; + + await walletProvider.signAndSendTransaction(tx, [counterKeypair]); + + const counterAccountInfo = await connection.getAccountInfo(counter, { + commitment: 'confirmed' + }); + + if (!counterAccountInfo) { + throw new Error('Expected counter account to have been created'); + } + + const counterAccount = deserializeCounterAccount(counterAccountInfo?.data); + + if (counterAccount.count !== 1) { + throw new Error('Expected count to have been 1'); + } + + counterMessage.value = `[alloc+increment] count is: ${counterAccount.count}`; + } catch (error) { + console.error(error); + counterMessage.value = `Error: ${error.message}`; + } + } + + return { + onIncrementCounter, + counterMessage + }; + } +}; +``` + + + diff --git a/network/index.mdx b/network/index.mdx new file mode 100644 index 0000000..a9241ff --- /dev/null +++ b/network/index.mdx @@ -0,0 +1,62 @@ +--- +title: "Network" +--- + +## Overview + +The WalletConnect Network is a network of apps, wallets and chains, facilitating end-users to connect to apps using any supported wallet on any supported chain. It is chain agnostic, working across ecosystems from EVM and its L2s, to Solana, Cosmos, Polkadot, Bitcoin and more. To date, it has facilitated more than 300+ million connections for 50+ million users between over 700+ different wallets and 80,000+ applications. + +Since its inception in 2018, the Network's design emphasizes interoperability and composability to efficiently enable interoperability between apps, wallets, fintechs, chains and TradFi. + +## Technology + +The WalletConnect Network's key components include: + +1. **Service Nodes**; database nodes that form the backbone of the network's storage layer. They operate on a consistent-hashing based distributed database. + +2. **Gateway Nodes**; responsible for facilitating encrypted communications and data routing between wallets and applications. + +3. **Relay Service**; connects users' wallets to dapps. + +## Permissioned Network + +The WalletConnect Network operates in a permissioned environment. This means: + +* Specific node operators manage the Service Nodes under service-level agreements. +* The Gateway Nodes are centralized and managed by WalletConnect. + +This allows WalletConnect to provide a secure and reliable service for enterprise-grade apps and wallets. + +## Network Participants + +WalletConnect Network Architecture + +The WalletConnect Network comprises various participants, each playing a crucial role in maintaining functionality and security: + +1. **Service Node Operators**: They run the service nodes (database nodes) that form the backbone of the network's storage layer. These nodes operate on a consistent-hashing based distributed database. + +2. **Gateway Node Operators**: They manage the gateway nodes, which are the entry points for apps and SDKs. Gateways facilitate encrypted communications and data routing between wallets and applications. + +3. **Wallets**: These allow end-users to manage their blockchain keys and interact with apps via the WalletConnect protocol. Most wallets integrate with the network using the WalletKit SDK. + +4. **Apps**: These are the products and services in the web3 space that drive traffic to the network. They can integrate directly or via available SDKs. + +5. **SDKs**: Software Development Kits that simplify the integration process for apps and wallets. + +6. **End Users**: The consumers of all services within the network, from wallets to apps, going through the relay and database nodes. + +Each of these participants contributes to the ecosystem in unique ways, ensuring the network's functionality, security, and continued growth. Their roles and interactions form the foundation of the WalletConnect Network's robust and interconnected infrastructure. + +## Learn more about the WalletConnect Network + + + + Learn about the WalletConnect network's governance model. + + + Learn how WCT powers the network's governance and incentivizes participants. + + + Read more about the network's design, architecture, and core principles. + + diff --git a/network/service-nodes.mdx b/network/service-nodes.mdx new file mode 100644 index 0000000..76fbc7b --- /dev/null +++ b/network/service-nodes.mdx @@ -0,0 +1,82 @@ +--- +title: Service Nodes +--- + +Service nodes form the backbone of the WalletConnect Network, serving as crucial infrastructure for persisting and managing end-to-end encrypted network messages. These nodes employ rendezvous hashing, a sophisticated method that ensures even distribution of data across the network. This approach not only enhances reliability and fault tolerance but also maintains user privacy by design - service nodes cannot decrypt or read the content of the messages they handle. + +## Technical Architecture + +The network's architecture is built on the premise that clients may be offline for extended periods. To address this, a "mailbox" system persists messages, allowing clients to retrieve data upon reconnection. This system is underpinned by a database utilizing rendezvous hashing, a concept that has proven its scalability in modern databases including Cassandra, DynamoDB, MongoDB, and others. + +The nodes are primarily constructed in Rust, chosen for its performance and safety features. For critical lower-level operations such as bloom-filters and I/O, the nodes integrate RocksDB, an industry-standard implementation maintained by Facebook/Meta. This hybrid approach leverages the strengths of custom-built solutions and battle-tested components. + +Current research focuses on evolving the rendezvous hashing-based database into a fully permissionless system. The next milestone is to publish a comprehensive technical design for community review, a crucial step before implementation. In the interim, node access to the network remains permissioned to ensure stability and security. + +## Service Node Operators + +Service Node Operators play a vital role in the WalletConnect ecosystem. Their responsibilities extend beyond mere node management to include proactive maintenance of high uptime and consistent performance optimization. The barrier to entry - staking WCT tokens - serves a dual purpose: it demonstrates the operator's commitment and aligns their interests with the network's success. + +The reward structure for operators is carefully designed to promote both long-term commitment and high-quality service. Staking rewards incentivize sustained participation, while performance-based incentives, calculated using key metrics like uptime and latency, encourage continuous improvement and innovation in node operation. + +## Node Statuses + +The WalletConnect Network implements a dynamic node status system, allowing for flexible and responsive network management: + +- **Active**: These nodes are the workhorses of the network, directly processing user requests within their assigned region. The initial target of 15 active nodes balances network robustness with economic efficiency. + +- **Reserve**: Operating similarly to active nodes, reserve nodes ensure network resilience. They participate in the replication process and stand ready to step into an active role when needed, maintaining a pool of qualified nodes. + +- **Jailed**: This status serves as a temporary penalty for nodes that fail to meet performance standards. The 24-hour exclusion period provides operators time to address issues while protecting the network from underperforming nodes. + +- **Standby**: Representing potential capacity, standby nodes have staked tokens but are not actively running. This status allows the network to scale rapidly when demand increases. + +- **Deactivated**: This status accommodates operators who choose to cease support, ensuring an orderly exit process that protects both the operator's interests and the network's stability. + +| Status | Target Number | +|-------------|----------------| +| Active | 15 | +| Reserve | 6 | +| Jailed | No target | +| Standby | No target | +| Deactivated | No target | + + +Target numbers are initial values and may be adjusted through governance decisions to optimize network performance and economic sustainability. + + +## Performance Evaluation + +The sophisticated performance evaluation system is a cornerstone of maintaining the WalletConnect Network's high standards. The performance coefficient $U(i,t) \in [0, 1]$ provides a nuanced measure of each node's contribution: + +$$\text{Performance} = (W_u \cdot U_i) \cdot (W_l \cdot L_i)$$ + +Where $U_i$ represents uptime, $L_i$ denotes latency, and $W_u$ and $W_l$ are adjustable weights. This formula allows for fine-tuning of performance priorities as the network evolves. + +## Performance Verification + +The transition from a permissioned to a permissionless verification system represents a key evolution in the network's maturity: + +1. Permissioned Network (Phase 1): + * Trusted oracle nodes conduct performance verification, ensuring a controlled and stable initial environment. + * The oracle node plays a crucial role within the Network. It functions as both a data collector and a regular service operator. + +2. Permissionless Network (Phase 2): + * All nodes engage in mutual performance measurement, creating a more decentralized and robust verification system. + * Every node pings and reports on every other node operator, replacing the need for a central oracle. + * This distributed approach enhances the network's resilience and reduces single points of failure. + +Key Transition: +* Phase 1: Trusted nodes (oracles) verify performance +* Phase 2: Every node participates in performance measurement + +This phased approach allows for gradual decentralization while maintaining network integrity throughout the transition. It enables the network to start with a controlled, easily manageable system and evolve into a more decentralized, robust structure as it matures. + +## Slashing Mechanism + +The slashing mechanism is a critical component in maintaining high network standards: + +1. Performance threshold $\tau$ (where $0 < \tau < 1$) is set through governance. +2. Nodes with $U(i,t) < \tau$ trigger a slashing event. +3. The underperforming node is moved to "jailed" status and replaced by a reserve node. +4. Jailed nodes may face a reduction in staked tokens, with the percentage determined by governance. +5. After the jailing period, nodes return to standby status, with the opportunity to re-enter active service. \ No newline at end of file diff --git a/network/wallets.mdx b/network/wallets.mdx new file mode 100644 index 0000000..ee22f18 --- /dev/null +++ b/network/wallets.mdx @@ -0,0 +1,15 @@ +--- +title: "Wallets" +sidebarTitle: "Wallets" +--- + +Wallets enable users to manage their blockchain keys and interact with applications via the WalletConnect protocol. They play a vital role in the Network by enabling end-users to securely access and utilize blockchain services on any network. Wallets are responsible for integrating with the WalletConnect Network and providing a seamless user experience for managing digital assets and performing blockchain transactions. Today, reown provides the WalletKit SDK to enable simple integrations for wallets to the Network. +## Certified Wallets + +The [WalletConnect Certified](https://walletconnect.com/blog/walletguide-and-walletconnect-certified-the-future-of-digital-wallets) program offers additional incentives for wallets that meet high standards of UX and integration, further encouraging wallets to stay up-to-date with the latest network features and best practices​. + +## Wallet Rewards + +Wallets participating in the WalletConnect network can earn rewards through staking and performance incentives. To qualify, wallets must stake WCT tokens, which enables them to participate in the Network's governance and earn staking rewards. + +For a closer look at the WalletConnect network's wallet rewards system, refer to the [Wallet Rewards](/network/WCT-token/rewards) documentation.​ diff --git a/network/wallets/android/best-practices.mdx b/network/wallets/android/best-practices.mdx new file mode 100644 index 0000000..ce0ccb2 --- /dev/null +++ b/network/wallets/android/best-practices.mdx @@ -0,0 +1,234 @@ +--- +title: Best Practices +--- + +The purpose of this guide is to show the best practices in regards of the WalletKit client usage. The goal is to provide the best user experience that just works in every circumstances. + + +In order to ensure the best user experience and flawless connection flow, please make sure that WalletKit is initialized immediately after your app launch, especially if launched via a WalletConnect Deep Link. It guarantees that websocket connection is opened immediately and all requests are received by your wallet + + +## Pairing + +A pairing is a connection between a wallet and a dapp that has fixed permissions to only allow a dapp to propose a session through it. Dapp can propose infinite number of sessions on one pairing. Wallet must use a pair method from WalletKit client to pair with dapp. + +```kotlin +val pairingParams = Wallet.Params.Pair(pairingUri) +WalletKit.pair(pairingParams, + onSuccess = { + //Subscribed on the pairing topic successfully. Wallet should await for a session proposal + }, + onError = { error -> + //Some error happens while pairing - check Expected errors section + } +} +``` + +### Pairing State + +A pairing state is a primitive exposed by the WalletKit client for a wallet to indicate whether it should await a session proposal. The pairing state is `true` when a wallet scans a QR and awaits a session proposal. Once the session proposal is received by the wallet, the pairing state is changed to `false`. +When `true` wallet should show a loading indicator awaiting a session proposal, when changed to `false` a proposal dialog should be displayed. + +```kotlin +val coreDelegate = object : CoreClient.CoreDelegate { + override fun onPairingState(pairingState: Core.Model.PairingState) { + //Here a pairing state is triggered + } + ...other callbacks +} + +CoreClient.setDelegate(coreDelegate) +``` + +### Pairing Expiry + +A pairing expiry event is triggered whenever a pairing is expired. The expiry for inactive pairing is 5 mins, whereas for active pairing is 30 days. A pairing becomes active when a session proposal is received and user successfully approves it. This event helps to know when given pairing expires and update UI accordingly. + +```kotlin +val coreDelegate = object : CoreClient.CoreDelegate { + override fun onPairingExpired(expiredPairing: Core.Model.ExpiredPairing) { + //Here a pairing expiry is triggered + } + ...other callbacks +} + +CoreClient.setDelegate(coreDelegate) + +``` + +### Expected User flow + +### Pairing Flow + + + + + +### Pairing Error + + + + + +### Expected Errors + +While pairing the following errors might occur: + +- No Internet connection error or pairing timeout when scanning QR with no Internet connection + - User should pair again with Internet connection +- Pairing expired error when scanning a QR code with expired pairing + - User should refresh a QR code and scan again +- Pairing with existing pairing is not allowed + - User should refresh a QR code and scan again. I usually happens when user scans an already paired QR code. + +## Session Proposal + +A session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Whenever a user wants to establish a connection between a wallet and a dapp, one should approve a session proposal. + +### User Action Feedback + +Whenever user approves or rejects a session proposal, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +Session approve + +```kotlin + WalletKit.approveSession(approveProposal, + onSuccess = { + //Session approval response was sent successfully - update your UI + } + onError = { error -> + //Error while sending session approval - update your UI + }) +``` + +Session reject + +```kotlin + WalletKit.rejectSession(reject, + onSuccess = { + //Session rejection response was sent successfully - update your UI + }, + onError = { error -> + //Error while sending session rejection - update your UI + }) +``` + +### Session Proposal Expiry + +A session proposal expiry is 5 mins. It means a given proposal is stored for 5 mins in the SDK storage and user has 5 mins for approval or rejection decision. After that time the below event is emitted and proposal modal should be removed from the app's UI. + +```kotlin +val walletDelegate = object : WalletKit.WalletDelegate { + override fun onProposalExpired(proposal: Wallet.Model.ExpiredProposal) { + //Here this event is triggered when a proposal expires - update your UI + } + ...other callbacks +} +WalletKit.setWalletDelegate(walletDelegate) +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session proposal the following errors might occurs: + +- No Internet connection + - It happens when a user tries to approve or reject session proposal with no Internet connection +- Session proposal expired + - It happens when users tries to approve or reject expired session proposal +- Invalid namespaces + - It happens when a validation of session namespaces fails +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Session Request + +A session request represents the request sent by a dapp to a wallet. + +### User Action Feedback + +Whenever user approves or rejects a session request, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +```kotlin +WalletKit.respondSessionRequest(Wallet.Params.SessionRequestResponse, + onSuccess = { + //Session request response was sent successfully - update your UI + }, + onError = { error -> + //Error while sending session response - update your UI + }) +``` + +### Session Request Expiry + +A session request expiry is defined by a dapp. It's value must be between now() + 5mins and now() + 7 days. After the session request expires the below event is emitted and session request modal should be removed from the app's UI. + +```kotlin +val walletDelegate = object : WalletKit.WalletDelegate { + override fun onRequestExpired(request: Wallet.Model.ExpiredRequest) { + //Here this event is triggered when a session request expires - update your UI + } + ...other callbacks +} +WalletKit.setWalletDelegate(walletDelegate) +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session request the following error might occur: + +- Invalid session + - This error might happen when user approves or rejects a session request on expired session +- Session request expired + - This error might happen when user approves or rejects a session request that already expires +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Web Socket Connection State + +The Web Socket connection state tracks the connection with the relay server, event is emitted whenever a connection state changes. + +```kotlin +val walletDelegate = object : WalletKit.WalletDelegate { + override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) { + //Here this event is triggered when a connection state has changed + } + ...other callbacks +} +WalletKit.setWalletDelegate(walletDelegate) +``` + +### Expected User flow + +### Connection State + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/connection_state.gif) + diff --git a/network/wallets/android/chain-abstraction.mdx b/network/wallets/android/chain-abstraction.mdx new file mode 100644 index 0000000..3e23cd4 --- /dev/null +++ b/network/wallets/android/chain-abstraction.mdx @@ -0,0 +1,141 @@ +--- +title: Chain Abstraction +--- + +import HowItWorks from "/snippets/walletkit/shared/chain-abstraction/intro.mdx"; +import ErrorHandling from "/snippets/walletkit/shared/chain-abstraction/error-handling.mdx"; + + + +## Methods + +The following methods from Wallet SDK are used in implementing chain abstraction. + + +💡 Chain abstraction is currently in the early access phase and requires the `@ChainAbstractionExperimentalApi` annotation. + + +### Prepare + +This method is used to check if chain abstraction is needed. If it is, it will return a `PrepareSuccess.Available` object with the necessary transactions and funding information. +If it is not, it will return a `PrepareSuccess.NotRequired` object with the original transaction. + + +Accounts field is a list of CAIP-20 accounts you are sourcing from e.g. Solana account + + +```kotlin +@ChainAbstractionExperimentalApi +fun prepare( + initialTransaction: Wallet.Model.InitialTransaction, + accounts: List, + onSuccess: (Wallet.Model.PrepareSuccess) -> Unit, + onError: (Wallet.Model.PrepareError) -> Unit +) +``` + +### Execute + +This method is used to execute the chain abstraction operation. It broadcasts the bridging and initial transactions and waits for them to be completed. +The method returns a `ExecuteSuccess` object with the transaction hash and receipt. + +```kotlin +@ChainAbstractionExperimentalApi +fun execute( + prepareAvailable: Wallet.Model.PrepareSuccess.Available, + prepareSignedTxs: List, + initSignedTx: String, + onSuccess: (Wallet.Model.ExecuteSuccess) -> Unit, + onError: (Wallet.Model.Error) -> Unit +) +``` + +## Usage + +When sending a transaction, first check if chain abstraction is needed using the `prepare` method. If it is needed, you must sign all the fulfillment transactions and use the `execute` method. + +If the operation is successful, use `execute` method and await the transaction hash and receipt. +If the operation is unsuccessful, send the JsonRpcError to the dapp and display the error to the user. + +```kotlin + val initialTransaction = Wallet.Model.Transaction(...) + WalletKit.ChainAbstraction.prepare( + initialTransaction, + caip10Accounts, + onSuccess = { prepareSuccess -> + when (prepareSuccess) { + is Wallet.Model.PrepareSuccess.Available -> { + // If the route is available, present a CA transaction flow + + //sign route transactions + transactionsDetails?.route?.forEach { route -> + route.transactionDetails.forEach { transactionDetails -> + val signedTransaction = Signer.signHash(transactionDetails.transactionHashToSign, EthAccountDelegate.privateKey) + eip155Signatures.add(signedTransaction) + } + } + } + + //sign initial transaction + val signedInitialTx = Signer.signHash(transactionsDetails?.initialDetails.transactionHashToSign, EthAccountDelegate.privateKey) + + //Call the execute + WalletKit.ChainAbstraction.execute(prepareSuccess, eip155Signatures, signedInitialTx + onSuccess = { + //The execution of the Chain Abstraction is successfull + //Send the response to the Dapp or show to the user + }, + onError = { + //Execute error - wallet should send the JsonRpcError to a dapp for given request and display error to the user + } + ) + } + + is Wallet.Model.PrepareSuccess.NotRequired -> { + // user does not need to move funds from other chains, sign and broadcast original transaction + } + } + }, + onError = { prepareError -> + // One of the possible errors: NoRoutesAvailable, InsufficientFunds, InsufficientGasFunds - wallet should send the JsonRpcError to a dapp for given request and display error to the user + } + ) +``` + +For example, check out implementation of chain abstraction in [sample wallet](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/master/sample/wallet) with Kotlin. + + + +## Testing + +To test Chain Abstraction, you can use the [AppKit laboratory](https://appkit-lab.reown.com/library/wagmi/) and try sending any supported [tokens](/network/wallets/features/chain-abstraction#what-are-the-supported-tokens-and-networks%3F) with any chain abstraction supported wallet. +You can also use this [sample wallet](https://appdistribution.firebase.dev/i/076a3bc9669d3bee) for testing. + + + +## ProGuard rules + +If you encounter issues with minification, add the below rules to your application: + +``` +-keepattributes *Annotation* + +-keep class com.sun.jna.** { *; } +-keepclassmembers class com.sun.jna.** { + native ; + *; +} + +-keep class uniffi.** { *; } + +# Preserve all public and protected fields and methods +-keepclassmembers class ** { + public *; + protected *; +} + +-dontwarn uniffi.** +-dontwarn com.sun.jna.** +``` \ No newline at end of file diff --git a/network/wallets/android/cloud/analytics.mdx b/network/wallets/android/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/android/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/android/cloud/explorer-submission.mdx b/network/wallets/android/cloud/explorer-submission.mdx new file mode 100644 index 0000000..cd1e47b --- /dev/null +++ b/network/wallets/android/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + \ No newline at end of file diff --git a/network/wallets/android/cloud/relay.mdx b/network/wallets/android/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/android/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/android/eip5792.mdx b/network/wallets/android/eip5792.mdx new file mode 100644 index 0000000..6818c5c --- /dev/null +++ b/network/wallets/android/eip5792.mdx @@ -0,0 +1,271 @@ +--- +title: Wallet Call API +--- + +WalletConnect supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. +Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities. + +- `wallet_sendCalls`: Requests that a wallet submits a batch of calls. +- `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet_sendCalls. +- `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet_sendCalls. +- `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication). + +## Usage + + + + ## Capabilities in CAIP-25 Connection Requests + + CAIP-25 defines how capabilities can be expressed in wallet-to-dapp connections. These capabilities control how methods like `wallet_sendCalls` behave. + + ### Session Properties + +In a connection request, dApps can request capabilities through `sessionProperties`. These capabilities can be universal (applying to all chains) or chain-specific: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": [], + "strict": [], + "exoticThirdThing": [] + }, + "atomic": { + "status": "supported" + } +} +``` + +### Scoped Properties + +For chain-specific capabilities, dapps use `scopedProperties`: + +```json +"scopedProperties": { + "eip155:8453": { + "paymasterService": { + "supported": true + }, + "sessionKeys": { + "supported": true + } + }, + "eip155:84532": { + "auxiliaryFunds": { + "supported": true + } + } +} +``` + +### Wallet Response + +The wallet's response should specify the capabilities it supports, in accordance with EIP-5792 and CAIP-25: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": ["halt", "continue"], + "strict": ["continue"] + }, + "atomic": { + "status": "ready" + } +}, +"scopedProperties": { + "eip155:1": { + "atomic": { + "status": "supported" + } + }, + "eip155:137": { + "atomic": { + "status": "unsupported" + } + }, + "eip155:84532": { + "eip155:83532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": { + "auxiliaryFunds": { + "supported": false + }, + "atomic": { + "status": "supported" + } + } + } +} +``` +- Capabilities shared across all address in a namespace can be expressed at top-level +- Address-specific capabilities can include exceptions to scope-wide capabilities + +### Atomic Capability + +According to [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792), the `atomic` capability specifies how the wallet handles batches of transactions. It has three possible values: + +- `supported` — The wallet executes calls atomically and contiguously. +- `ready` — The wallet can upgrade to support atomic execution, pending user approval. +- `unsupported` — The wallet provides no atomicity guarantees. + +This capability is expressed per chain and is crucial for determining how `wallet_sendCalls` with `atomicRequired: true` will be handled. + + ### Example + The `wallet_getCapabilities` method is used to request information about what capabilities a wallet supports. Following EIP-5792, here's how it should be implemented: + + #### Request + ```json + { + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_getCapabilities", + "params": ["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]] + } + ``` + + #### Response + The wallet should return a response following EIP-5792, where capabilities are organized by chain ID: + + ```json + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "0x2105": { + "atomic": { + "status": "supported" + } + }, + "0x14A34": { + "atomic": { + "status": "unsupported" + } + } + } + } + ``` + + + + ### Implementation + When implementing `wallet_sendCalls`, wallets must follow these requirements: + + #### Connection Approval + - Only approve this method during the connection approval flow if your wallet can implement it correctly + - Define the `atomic` capability per chain/account in the CAIP-25 response + + #### Request Format + ```json + { + "id": 12345, + "version": "2.0", + "method": "wc_sessionRequest", + "params": { + "chainId": "caip-2-chain-id", + "request": { + "method": "wallet_sendCalls", + "params": { + "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "chainId": "0x01", + "atomicRequired": true, + "calls": [ + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x182183", + "data": "0xfbadbaf01" + } + ] + } + } + } + } + ``` + + #### Core Implementation Requirements + - Execute calls in the exact order specified in the request + - Do not wait for any calls to be finalized before completing the batch + - If the user rejects the request, do not send any calls + + #### Atomic Execution Behavior + When `atomicRequired` is `true`: + - Execute all calls atomically (either all succeed or none have any effect) + - Execute all calls contiguously (no other transactions between batch calls) + - If your wallet can upgrade from `ready` to `supported` atomicity, do so before executing + + When `atomicRequired` is `false`: + - You may execute calls sequentially without atomicity guarantees + - You may execute atomically if your wallet supports it + - You may upgrade to `supported` atomicity and execute atomically + + #### Response Enrichment + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + + + ### Example + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + To implement this functionality, the response for wallet_sendCalls should be enriched with capabilities: + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + ### Response Format + The response format for `wallet_getCallsStatus` varies based on the execution method: + + + For non-atomic execution, include all transactions in the receipts array, even those that were included on-chain but eventually reverted. + + + #### For Atomic Execution + ```json + { + "receipts": [/* single receipt or array of receipts */], + "atomic": true + } + ``` + + #### For Non-Atomic Execution + ```json + { + "receipts": [/* array of receipts for all transactions */], + "atomic": false + } + ``` + + + +## References +- EIP-5792: https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability +- CAIP-25 namespaces: https://github.com/ChainAgnostic/namespaces/blob/main/eip155/caip25.md diff --git a/network/wallets/android/installation.mdx b/network/wallets/android/installation.mdx new file mode 100644 index 0000000..5ff30f5 --- /dev/null +++ b/network/wallets/android/installation.mdx @@ -0,0 +1,50 @@ +--- +title: Installation +--- + +Add the `jitpack.io` Maven repository to your `root/build.gradle.kts` file. For example: + +```gradle +allprojects { + repositories { + mavenCentral() + maven { url "https://jitpack.io" } + } +} +``` + +In `app/build.gradle.kts` add the WalletKit package and its dependencies: + +```gradle +implementation("com.reown:android-core:release_version") +implementation("com.reown:walletkit:release_version") +``` + +## ProGuard rules + +If you encounter issues with minification, add the below rules to your application: + +``` +-keepattributes *Annotation* + +-keep class com.sun.jna.** { *; } +-keepclassmembers class com.sun.jna.** { + native ; + *; +} + +-keep class uniffi.** { *; } + +# Preserve all public and protected fields and methods +-keepclassmembers class ** { + public *; + protected *; +} + +-dontwarn uniffi.** +-dontwarn com.sun.jna.** +``` + +## Next Steps + +Now that you've installed Wallet SDK, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/android/link-mode.mdx b/network/wallets/android/link-mode.mdx new file mode 100644 index 0000000..26fc62e --- /dev/null +++ b/network/wallets/android/link-mode.mdx @@ -0,0 +1,57 @@ +--- +title: Link Mode +--- + +The Wallet SDK Link Mode is a low latency mechanism for transporting [One-Click Auth](/network/wallets/android/one-click-auth) requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection. + +To support Link Mode add a universal link for your wallet in Cloud project configuration dashboard, configure your AppMetaData `appLink` with a valid universal link and set the `linkMode` property to `true`: + + +Make sure that [1-Click Auth](/network/wallets/android/one-click-auth) is implemented before enabling Link Mode. + + +```kotlin {3-4} + val appMetaData = Core.Model.AppMetaData( + ... + appLink = "https://example.com/example_wallet", + linkMode = true +) + +CoreClient.initialize( + metaData: appMetaData, + ... +) + +WalletKit.initialize(Wallet.Params.Init(core = CoreClient)) +``` + +Once link mode and app link are properly configured and the user interacts with a link mode supporting dApp, your wallet will receive requests over app links. You must pass these requests to WalletKit so it can process them: + +```kotlin +val url = intent.dataString +WalletKit.dispatchEnvelope(url) { error -> + //handle error +} +``` + +Ensure to handle incoming app links in your Activity onCreate method and in onNewIntent callback. + +Ensure that your App Link is properly configured in your app's Manifest file with the `autoVerify` set to `true`: + +``` + + + + + + + +``` + +For more information on how to configure app links for your app, refer to the [Android Documentation](https://developer.android.com/training/app-links/verify-android-applinks). + +For enabling links to app content check [this](https://developer.android.com/training/app-links/deep-linking) documentation page. + +For more information on how to interact with other apps using intents, see [Android Intent Documentation](https://developer.android.com/training/basics/intents). diff --git a/network/wallets/android/mobile-linking.mdx b/network/wallets/android/mobile-linking.mdx new file mode 100644 index 0000000..5a8f99a --- /dev/null +++ b/network/wallets/android/mobile-linking.mdx @@ -0,0 +1,190 @@ +--- +title: Mobile Linking +--- + +import HowToTest from "/snippets/walletkit/shared/mobile-linking.mdx"; + + + +This feature is only relevant to native platforms. + + + +## Usage + +Mobile Linking allows your wallet to automatically redirect back to the Dapp allowing for less user interactions and hence a better UX for your users. + +### Establishing Communication Between Mobile Wallets and Apps + +When integrating a wallet with a mobile application, it's essential to understand how they communicate. The process involves two main steps: + +1. **QR Code Handshake:** The mobile app (Dapp) generates a unique URI (Uniform Resource Identifier) and displays it as a QR code. This URI acts like a secret handshake. When the user scans the QR code using their wallet app, they establish a connection. It's like saying, "Hey, let's chat!" +2. **Deep Links and Universal Links:** The URI from the QR code allows the wallet app to create a [deep link](https://support.google.com/google-ads/answer/10023042?hl=en#:~:text=Deep%20links%20send%20mobile%20device,%2C%20Shopping%2C%20and%20Display%20campaigns.) or [universal link](https://developer.apple.com/ios/universal-links/). These links work on both Android and iOS. They enable seamless communication between the wallet and the app. + + + +**Developers should prefer Deep Linking over Universal Linking.** + +Universal Linking may redirect the user to a browser, which might not provide the intended user experience. Deep Linking ensures the user is taken directly to the app. + + + +### Key Behavior to Address + +In some scenarios, wallets use redirect metadata provided in session proposals to open applications. This can cause unintended behavior, such as: + +Redirecting to the wrong app when multiple apps share the same redirect metadata (e.g., a desktop and mobile version of the same Dapp). +Opening an unrelated application if a QR code is scanned on a different device than where the wallet is installed. + +#### Recommended Approach + +To avoid this behavior, wallets should: + +- **Restrict Redirect Metadata to Deep Link Use Cases**: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. + +The connection and sign request flows are similar across platforms. + +### Connection Flow + +- **Dapp Prompts User:** The Dapp asks the user to connect. +- **User Chooses Wallet:** The user selects a wallet from a list of compatible wallets. +- **Redirect to Wallet:** The user is redirected to their chosen wallet. +- **Wallet Approval:** The wallet prompts the user to approve or reject the session (similar to granting permission). +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reunites with Dapp:** After all the interactions, the user ends up back in the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking-light.png) + + +### Sign Request Flow + +When the Dapp needs the user to sign something (like a transaction), a similar pattern occurs: + +- **Automatic Redirect:** The Dapp automatically sends the user to their previously chosen wallet. +- **Approval Prompt:** The wallet asks the user to approve or reject the request. +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reconnects:** Eventually, the user returns to the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking_sign-light.png) + + +## Platform preparations + +In order for Dapps to be able to trigger your wallet for a connection or sign request using deep links you first need to add your own wallet to the Explorer by login to your [WalletConnect Dashboard](https://dashboard.walletconnect.com/sign-in) account, declare a deep link and define an [``](https://developer.android.com/training/app-links/deep-linking#adding-filters) in your wallet's Manifest.xml with the same deep link added in Explorer: + +```xml + + + + + + +``` + + + +Dapps developers must do the same for their own custom schemes if they want the wallet to be able to navigate back after a session approval or a sign request response + + + + + +## Integration + +#### Wallet Support + +**Disclaimer:** The below solution is designed for the communication between native Android Dapps and native Android wallets. In the case of mobile browser Dapps and native Android wallets communication, we recommend moving wallets into the background after both approving and rejecting sessions or approving and rejecting requests to persist smooth deep-link UX. + +In order to add support for mobile linking within your wallet and receive session proposals, register following deep link in your mobile wallet using intent filters in your Activity/Fragment or deepLink tag in your navigation graph. + +To support universal native modal and WalletConnectModal register: `wc://` + +Deep link example: `examplewallet://wc?uri={pairingUri}` + +To receive signing request in your Wallet, you'll need to initialize Kotlin SDK with the `Redirect` object where you pass a deep link that redirects to your wallet when it comes to receiving signing request from Dapp. + +```kotlin +val redirect = "examplewallet://request" //should be unique for your wallet + +val appMetaData = Core.Model.AppMetaData( + name = "Wallet Name", + description = "Wallet Description", + url = "Wallet Url", + icons = listOfIconUrlStrings, + redirect = redirect +) + +CoreClient.initialize(projectId = projectId, connectionType = connectionType, application = application, metaData = appMetaData) + +val init = Wallet.Params.Init(coreClient = CoreClient) +WalletKit.initialize(init) +``` + +Redirect when responding to a session proposal: + +```kotlin + WalletKit.approveSession(approveProposal, + onSuccess = { + // trigger deeplink: proposal.redirect + } +) +``` + +Redirect when responding to a request: + +```kotlin +val redirect = WalletKit.getActiveSessionByTopic(sessionRequest.topic)?.redirect?.toUri() +WalletKit.respondSessionRequest(response, + onSuccess = { + // trigger deeplink: redirect + } +) +``` + +**Heads-up:** To make this flow working well, Wallet must register one of its Android components with the same deep link that it initialized with. + +To check the flow implementation described above have a look on our sample wallet: +https://github.com/WalletConnect/WalletConnectKotlinV2/tree/master/sample/wallet + +#### Dapp Support + +To send session proposals to mobile wallet user the pairing URI as deep link that triggers a wallet to open and consume pairing URI + +```kotlin +requireActivity().startActivity(Intent(Intent.ACTION_VIEW, deeplinkPairingUri.toUri())) +``` + +In order to add support for mobile linking within your Dapp and receive signing request responses from wallet, you'll need to initialize Kotlin SDK with the `Redirect` object where you pass a deep link that redirects to your Dapp when it comes to receiving signing request responses from wallet. + +```kotlin +val redirect = "kotlin-dapp-wc://request" //should be unique for your Dapp + +val appMetaData = Core.Model.AppMetaData( + name = "Dapp Name", + description = "Dapp Description", + url = "Dapp URL", + icons = listOfIconUrlStrings, + redirect = redirect +) + +CoreClient.initialize(projectId = projectId, connectionType = connectionType, application = application, metaData = appMetaData) + +val init = Sign.Params.Init(core = CoreClient) +SignClient.initialize(init) +``` + +**Heads-up:** To make this flow working well, Dapp must register one of its Android components with the same deep link that it initialized with. + +To check the flow implementation described above have a look on our Sample Dapp: +https://github.com/WalletConnect/WalletConnectKotlinV2/tree/master/sample/dapp + +#### References + +- https://developer.android.com/guide/navigation/navigation-deep-link#implicit +- https://developer.android.com/training/app-links#deep-links diff --git a/network/wallets/android/notifications/notify/installation.mdx b/network/wallets/android/notifications/notify/installation.mdx new file mode 100644 index 0000000..98bd58b --- /dev/null +++ b/network/wallets/android/notifications/notify/installation.mdx @@ -0,0 +1,31 @@ +--- +title: Installation +--- + +Add the `jitpack.io` Maven repository to your `root/build.gradle.kts` file. For example: + +```gradle +allprojects { + repositories { + mavenCentral() + maven { url "https://jitpack.io" } + } +} +``` + +In `app/build.gradle.kts` add the notify package and its dependencies: + +```gradle +implementation(platform("com.reown:android-bom:release_version")) +implementation("com.reown:android-core") +implementation("com.reown:notify") +``` + +#### Requirements + +- Android API level minimum 23 +- Java minimum version 11 + +## Next Steps + +Now that you've installed WalletConnect Notify, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the Notify API. diff --git a/network/wallets/android/notifications/notify/overview.mdx b/network/wallets/android/notifications/notify/overview.mdx new file mode 100644 index 0000000..6879154 --- /dev/null +++ b/network/wallets/android/notifications/notify/overview.mdx @@ -0,0 +1,26 @@ +--- +title: Overview +--- + + +For those integrating notifications related to wallet pairing and sign requests, please check [here](../push). + + +The WalletConnect Notify API is designed to enhance the interaction between wallet users and dapps by offering a robust notification system. This API empowers wallet developers to implement a dynamic notification experience directly within their wallets. It provides the functionality for users to opt-in to notifications, ensuring they stay informed about critical events and interactions. + +The Notify API is versatile, with support for both iOS and Android platforms, making it an ideal choice for cross-platform wallet applications. + +Coupled with the AppKit Notifications, the Notify API forms part of a comprehensive toolkit that enables seamless integration of web3 communication and messaging features into dapps. This ensures a more connected and interactive experience for users in the decentralized ecosystem. + +## Features + +Some of the key features of the Notify API include: + +- **Push Notifications for Desktop and Native Platforms**: This feature enables dapps to directly send vital notifications to user wallets, ensuring timely and relevant communication. +- **Robust Spam Protection**: Users have complete authority over which dapps can send them notifications, effectively eliminating any unsolicited messages from unknown sources. Furthermore, users can fine-tune their preferences to only receive notifications types they are interested in, like new features or some important events occurrence. +- **Chain Agnostic Architecture**: The Notify API is built to be compatible with any blockchain, allowing seamless multi-chain support without the need for writing additional integration code. **As of November 2023, the Notify Server and Clients are equipped to support EVM chains. Plans to extend support to non-EVM chains are in progress and are a significant part of our upcoming development roadmap.** + +_Example integration_ + + + diff --git a/network/wallets/android/notifications/notify/resources.mdx b/network/wallets/android/notifications/notify/resources.mdx new file mode 100644 index 0000000..58b79f4 --- /dev/null +++ b/network/wallets/android/notifications/notify/resources.mdx @@ -0,0 +1,19 @@ +--- +title: Resources +--- + +Valuable assets for developers interested in integrating Notify API into their wallet. + +- [Web3Inbox.com app](https://app.web3inbox.com) - Inbox web app that simulates wallet experience. +- [GM dapp](https://gm.walletconnect.com/) - Example dapp that sends notification every hour. +- [GM hackers](https://github.com/WalletConnect/gm-hackers) - Template used in hackathons sponsored by WalletConnect. + +## Wallet Resources + +To check more in details go and visit our [WalletKit Kotlin implementation app](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/sample/wallet). Sample Wallet .apk files can be found under the latest release tag in [Kotlin's V2 repository](https://github.com/WalletConnect/WalletConnectKotlinV2/tags) + +If you need to test your app's integration, you can use one [our GM dapp.](https://gm.walletconnect.com/) + +## Need Technical Support? + +If you require technical support along the way, please drop a message on the [WalletConnect GitHub](https://github.com/orgs/WalletConnect/discussions/) and our team will get back to you as soon as possible. diff --git a/network/wallets/android/notifications/notify/spam-protection.mdx b/network/wallets/android/notifications/notify/spam-protection.mdx new file mode 100644 index 0000000..d56bbfa --- /dev/null +++ b/network/wallets/android/notifications/notify/spam-protection.mdx @@ -0,0 +1,27 @@ +--- +title: Spam Protection +--- + +Users play a critical role in web3. That’s why, with WalletKit Notifications, we’re committed to ensuring users can enjoy a safe, seamless, and reliable experience that puts them in the driver’s seat. As part of that pledge, Web3Inbox provides a number of user-first, anti-spam features and elements that ensure users are always in control of their web3 communications. + +## How are users protected from spam with WalletKit Notifications? + +### Becoming a WalletKitNotifications customer + +When a wallet offers app notifications to their users via WalletKit Notifications, the feature will always be optional. If users decide they want to receive notifications from selected apps via their wallet, they’ll be able to ‘opt-in’ and subscribe to an app’s notifications by signing a message request. Similarly, when accessing notifications through the [Web3Inbox.com app](https://app.web3inbox.com), users will be met with the same request for each application they choose to subscribe to. This feature not only enables users to experience a customized, ‘app-by-app’ approach to staying connected in web3, but also ensures they only ever hear from the apps they choose to — no unsolicited notifications or spam from unknown senders. Its their curated inbox, connected with only those they choose. + +### Setting customized notification preferences + +Once users have subscribed to their chosen apps, they have the option to define and set which types of notifications they receive from those apps. For example, a user may wish to receive only information regarding changes to their portfolio from a DEX, or, they might want to receive notifications from an NFT marketplace — but only notifications regarding their own NFT collections. In these scenarios, they’ll have the ability to disable other notification types, like marketing updates, and ensure their feed is curated to show only information that’s meaningful to them. As apps set their own notification types, they have unlimited optionality to really build out a notification structure they know can support their users’ needs — no ‘one size fits all’ approach, but a personable, community-oriented structure that puts both app and user needs’ at the forefront of communication. + +### Rate limiting + +Apps are limited to a maximum number of notifications they’re able to send to their community. Specifically, apps may send accounts notifications twice an hour on average, but may exceed that average in bursts of up to 50 at a time. + +## Our continued pledge on spam protection + +We’re constantly working on improving and growing our products, and we have a number of impactful anti-spam features and functions in the works set to increase the overall protection and user experience of Web3Inbox users: + +### User reporting + +Users will have the ability to report applications that appear to be acting or engaging with their community in a malicious or suspicious manner. Projects that are flagged as malicious may be removed from the Web3Inbox discover page and have notification functionality disabled. diff --git a/network/wallets/android/notifications/notify/usage.mdx b/network/wallets/android/notifications/notify/usage.mdx new file mode 100644 index 0000000..be778aa --- /dev/null +++ b/network/wallets/android/notifications/notify/usage.mdx @@ -0,0 +1,339 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + + +In this section, we showcase the aspects of using the Notify API. We'll guide you through the initial steps of initializing the Notify client and logging in a blockchain account. You'll also learn how to manage your subscriptions and messages. Additionally, we cover the process of setting up and displaying push notifications on your preferred platform. To ensure a good user experience, we include best practices for spam protection, helping you to enable the users to maintain control over the notifications wallet receives. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out Extra (Platform Specific) under this section. + +- [Initialization](#initialization): + Creating a new Notify Client instance and initializing it with a projectId from [[WalletConnect Dashboard](https://dashboard.walletconnect.com/). +- [Account login](#account-login): + A SIWE message must be signed by the user in order to authorize the client to use Notify API +- [Subscribing to a new dapp](#subscribing-to-a-new-dapp): + Opt-in to receive notifications from dapp +- [Fetching active subscriptions](#fetching-active-subscriptions): + Get active subscriptions +- [Fetching subscription’s notification](#fetching-subscriptions-notifications): + Get notifications of a subscription +- [Fetching available notification types](#fetching-available-notification-types): + Get latest notification types +- [Updating subscriptions notification settings](#updating-subscriptions-notification-settings): + Change allowed notification types sent by dapp +- [Unsubscribe from a dapp](#unsubscribe-from-a-dapp): + Opt-out from receiving notifications from a dapp +- [Account logout](#account-logout): + To stop receiving notifications to this client, accounts can logout of using Notify API +- [Push Notification best practices](#push-notification-best-practices): + Guidelines on how to implement Push Notifications across different platforms +- [Firebase Cloud Messaging setup **(Android)**](#firebase-cloud-messaging-setup): + Configuring Android app in order to decrypt notifications +- [NotifyClient.Delegate **(Android)**](#notifyclientdelegate): + Setting and overriding functions through NotifyDelegate. + +## Initialization + + + +To initialize the Notify client, create a `Notify.Params.Init` object in the Android Application class with the Core Client passed as a parameter. The `Notify.Params.Init` object will then be passed to the `Notify.initialize` function. There is also an `onError` callback that will need to be provided which will return an instance of `Notify.Model.Error` if there's an issue initializing the client. + +**Note:** The CoreClient used here will be the same instance of the CoreClient used in other WalletConnect Kotlin SDKs + +```kotlin +val projectId = PROJECT_ID +val appMetaData = Core.Model.AppMetaData( + name = /* The name of your project as a String */, + description = /* A description of your project as a String */, + url = /* A url for your project as a String */, + icons = /* A list of URLs to icons related to your project as Strings */, + redirect = /* A redirect URI used by Dapps to deeplink back to your wallet. This is a String value */ +) + +CoreClient.initialize(projectId = projectId, connectionType = ConnectionType.AUTOMATIC, application = this, metaData = appMetaData) + +Notify.initialize(init = Notify.Params.Init(core = CoreClient) { error: Notify.Model.Error -> + // Error will be thrown if there's an issue during initialization +} +``` + +## Account login + +In order to register account in Notify API to be able to subscribe to any dapp to start receiving notifications, account needs to sign SIWE message to prove ownership. Developers can check if an account is registered by calling **`isRegistered()`** function. If the account is not registered, developers should call **`prepareRegistration()`** and then **`register()`** function to register the account. + +Snippet below shows how to check if an account is registered and how to register an account if it's not registered yet. Developers could use `CacaoSigner` to sign the message or use their own signing method. + +```kotlin +val account: String = ""// The CAIP-10 account i.e. "eip155:1:0xAbC1234567890DefABC1234567890dEFABC12345" +val domain = BuildConfig.APPLICATION_ID + +// Caution: This function is blocking and runs on the current thread. It is advised that this function be called from background operation +val isRegistered = NotifyClient.isRegistered(params = Notify.Params.IsRegistered(account = account, domain = domain)) + +if (!isRegistered) { + NotifyClient.prepareRegistration( + params = Notify.Params.PrepareRegistration(account = account, domain = domain), + onSuccess = { cacaoPayloadWithIdentityPrivateKey, message -> + + // Pick one of the following methods to sign the message: + + // 1. Using CacaoSigner to sign the message + val signature = CacaoSigner.sign( + message, + PRIVATE_KEY, // Private key used to signing a message, + SignatureType.EIP191 + ) + + // 2. Alternatively, you can use your own signing method + /** Add imports: + import com.reown.android.cacao.signature.SignatureType + import com.reown.android.internal.common.signing.signature.Signature + import com.reown.android.internal.common.signing.signature.toCacaoSignature + */ + + val signature: String = // Here developers provide signed message using their own signing method + val cacaoSignature = Notify.Model.Cacao.Signature(SignatureType.EIP191.header, Signature.fromString(signature).toCacaoSignature()) + + // Once the message has been signed, call the register function + + NotifyClient.register( + params = Notify.Params.Register(cacaoPayloadWithIdentityPrivateKey = cacaoPayloadWithIdentityPrivateKey, signature = signature), + onSuccess = { + // Registration was successful + }, + onError = { + // There was an error while trying to register the account + } + ) + + }, + onError = { + // There was an error while trying to prepare the registration + } + ) +} else { + // Great! Account is already registered +} +``` + +## Subscribing to a new dapp + +To begin receiving notifications from a dapp, users must opt-in by subscribing. This subscription process grants permission for the dapp to send notifications to the user. These notifications can serve a variety of purposes, such as providing updates on the user's blockchain account activities or informing them about ongoing campaigns within the dapp. Upon initial subscription, clients will be automatically enrolled to receive all types of notifications as defined by the dapp at that moment. Users have the flexibility to modify their notification settings later, allowing them to tailor the types of alerts they receive according to their preferences. + +```kotlin +val appDomain: Uri = // Dapp uri. e.g. gm.walletconnect.com +val account: String = // CAIP-10 account +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec +val params = Notify.Params.Subscribe(appDomain, account, timeout) + +NotifyClient.subscribe(params = params).let { result -> + when (result) { + is Notify.Result.Subscribe.Success -> { + // callback for when the subscription request was successful + } + + is Notify.Result.Subscribe.Error -> { + // callback for when the subscription request has failed + } + + } +} +``` + +## Fetching active subscriptions + +To fetch the current list of subscriptions an account has, call **`getActiveSubscriptions()`**. + +Method will return a map with the topic as the key and `Notify.Model.Subscription` as the value. + +```kotlin +val account: String = // CAIP-10 account +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec +val params = Notify.Params.GetActiveSubscriptions(account, timeout) + +try { + val result: Map = NotifyClient.getActiveSubscriptions(params) +} catch (e: Exception) { + // callback for when the get active subscriptions request has failed +} +``` + +## Fetching subscription’s notifications + +To fetch subscription’s notifications by calling **`getNotificationHistory()`**. + +```kotlin +val topic: String = // active subscription topic +val limit: Int? = // Optional. Limit - min 1, max 50, default 10 +val startingAfter: String? = // Optional. Id of the notification to start after +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec + +val params = Notify.Params.GetNotificationHistory(topic, limit, startingAfter, timeout) + +NotifyClient.getNotificationHistory(params).let { result -> + when (result) { + is Notify.Result.GetNotificationHistory.Success -> { + // callback for when the get notification history request was successful + } + + is Notify.Result.GetNotificationHistory.Error -> { + // callback for when the get notification history request has failed + } + } +} +``` + +## Fetching available notification types + +Developers can fetch latest notification types specified by dapp by calling **`getNotificationTypes()`** function. + +Method will return a map with the notification type id as the key and `Notify.Model.NotificationType` as the value. + +```kotlin +val appMetadata: Core.Model.AppMetaData = // App Metadata could be fetched from NotifyClient.getActiveSubscriptions() +val appDomain: String = URI(appMetadata.url).host +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec + +val params = Notify.Params.NotificationTypes(appDomain, timeout) +try { + val result: Map = NotifyClient.getNotificationTypes(params) +} catch (e: Exception) { + // callback for when the get notification types request has failed +} +``` + +## Updating subscriptions notification settings + +Users can alter their notification settings to filter out unwanted alerts from a dapp. During this process, they review and select the types of notifications they wish to receive, based on the latest options provided by the dapp. Available notification types fetching is shown in the [next section](#fetching-available-notification-types). + +```kotlin +val topic: String = // active subscription topic +val scope: List = // list of notification types +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec +val params = Notify.Params.UpdateSubscription(topic, scope, timeout) + +NotifyClient.update(params).let { result -> + when (result) { + is Notify.Result.UpdateSubscription.Success -> { + // callback for when the update request was successful + } + is Notify.Result.UpdateSubscription.Error -> { + // callback for when the update request has failed + } + } +} +``` + +## Unsubscribe from a dapp + +To opt-out of receiving notifications from a dap, a user can decide to unsubscribe from dapp. + +```kotlin +val topic: String = // active subscription topic +val timeout: Duration? = // Optional. Timeout - min 5 sec, max 60 sec, default 60 sec +val params = Notify.Params.DeleteSubscription(topic) + +NotifyClient.deleteSubscription(params).let { result -> + when (result) { + is Notify.Result.DeleteSubscription.Success -> { + // callback for when the delete request was successful + } + + is Notify.Result.DeleteSubscription.Error -> { + // callback for when the delete request has failed + } + } +} +``` + +## Account logout + +If an account is removed from the client or a user no longer wants to receive notifications for this account, you can logout the account from Notify API by calling **`unregister()`**. This will remove all subscriptions and messages for this account from the client’s storage. + +```kotlin +val params = Notify.Params.Unregistration(/*CAIP-10 account*/) +NotifyClient.unregister( + params, + onSuccess = { + // callback for when the unregistration was successful + }, + onError = { error -> + // callback for when the unregistration has failed + } +) +``` + +## Push Notification best practices + +To create a good user experience and to guide users into unsubscribing from the correct dapp, there are certain best practices when displaying push notifications. + +`Core.Model.Message` contains a `type` field, which is a unique id of the notification type. It is recommended to use this field as a notification channel id. By doing so it will create a channel for each notification type. To allow users to granularly control which notifications they want to receive within system settings, it is recommended to create a separate channel for every dapp and every notification type they might have. By doing so user would be able to turn off notifications for specific notification type per every subscribed dapp. + +```kotlin +class SampleFirebaseService: PushMessagingService() { + //... + override fun onMessage(message: Core.Model.Message, originalMessage: RemoteMessage) { + if (message is Core.Model.Message.Notify) { + val account: String = // CAIP-10 account + val appMetadata = NotifyClient.getActiveSubscriptions(Notify.Params.GetActiveSubscriptions(account))[topic]?.metadata + ?: throw IllegalStateException("No active subscription for topic: $topic") + + val appDomain = URI(appMetadata.url).host + ?: throw IllegalStateException("Unable to parse domain from $appMetadata.url") + + val notificationType = NotifyClient.getNotificationTypes(Notify.Params.GetNotificationTypes(appDomain))[channelId] + ?: throw IllegalStateException("No notification type for topic:${topic} and type: $channelId") + + val channelName = appMetadata.name + ": " + notificationType.name + val channelId = message.type + + val notificationBuilder = NotificationCompat.Builder(this, channelId) + .setContentTitle(message.title) + .setSmallIcon(android.R.drawable.ic_popup_reminder) // specify icon for notification + .setContentText(message.body) + .setAutoCancel(true) // clear notification after click + .setSound(defaultSoundUri) // specify sound for notification + .setContentIntent(pendingIntent) // specify pendingIntent + + // Since android Oreo notification channel is needed. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH) + notificationManager.createNotificationChannel(channel) + } + + notificationManager.notify(message.hashCode(), notificationBuilder.build()) // specify id of notification + } + } +//... +``` + +### Firebase Cloud Messaging setup + +To setup Firebase Cloud Messaging please follow our [Push Notifications docs](../push). + +### NotifyClient.Delegate + +`NotifyClient` needs a `NotifyClient.Delegate` passed to it for it to be able to expose asynchronous updates sent from the dapp. It's recommended to set the delegate in the `onCreate` function of the `Application` class. + +```kotlin +val walletDelegate = object : NotifyClient.Delegate { + + override fun onNotifySubscription(notifySubscribe: Notify.Event.Subscription) { + // Triggered when a wallet initiated subscription has been created + } + + override fun onNotifyNotification(notifyNotification: Notify.Event.Notification) { + // Triggered when a message has been sent by the Dapp. The message contains the title, body, icon, and url + } + + override fun onError(error: Notify.Model.Error) { + // Triggered when there's an error inside the SDK + } +} + +NotifyClient.setDelegate(walletDelegate) +``` diff --git a/network/wallets/android/notifications/push.mdx b/network/wallets/android/notifications/push.mdx new file mode 100644 index 0000000..ca597ce --- /dev/null +++ b/network/wallets/android/notifications/push.mdx @@ -0,0 +1,75 @@ +--- +title: Push Notifications +--- + +WalletKit provides the functionality for wallets to receive push notifications through Firebase Cloud Messaging (FCM) and Apple Push Notification Service (APNs) via the Push Server. This feature ensures that wallets are promptly notified of incoming signature requests. Each push notification contains the encrypted details of the signature request. Upon receiving the notification, it can be decrypted and presented to the developer, allowing for customization of the message according to their requirements. + +## Server setup + +For the push notifications to be forwarded to FCM or APNs, the [Push Server](https://docs.reown.com/advanced/push-server) will need to be configured with your FCM or APNs server API credentials. + +## App setup + +### Register the device token + +To enable a device for push notifications, it's essential to register the device token using `WalletKit.registerDeviceToken`. This token can be obtained from either FCM or APNS, depending on the platform used. + +This method enables wallets to receive push notifications from WalletConnect's Push Server via Firebase Cloud Messaging. This means you will have to setup your project with Firebase before being able to call `registerDeviceToken()` method. + +To register a wallet to receive WalletConnect push notifications, call `WalletKit.registerDeviceToken` and pass the Firebase Access Token. + +```kotlin +val firebaseAccessToken: String = //FCM access token received through the Firebase Messaging SDK +val enableEncrypted: Boolean = true //Flag that enables receiveing the detailed notifications + +WalletKit.registerDeviceToken( + firebaseAccessToken = firebaseAccessToken, + enableEncrypted = enableEncrypted, + onSuccess = { + // callback triggered once registered successfully with the Push Server + }, + onError = { error: Wallet.Model.Error -> + // callback triggered if there's an exception thrown during the registration process + }) +``` + +### Receiving push notifications + +After the device token is registered, the next step involves setting up the notification service specific to the platform being used. This service will decrypt the incoming requests and forward them to the developer for further processing and integration. + +The `PushMessagingService` is a wrapper around the `FirebaseMessagingService`. The `PushMessagingService` class needs to be implemented for WalletKit to be able to decrypt and notify wallets of a push notification sent from the Dapp in the background. This service also needs to be registered in the `AndroidManifest.xml` file similar to the example in the FCM documentation. + +```kotlin +class SampleFirebaseService: PushMessagingService() { + + override fun newToken(token: String) { + // Triggered when Firebase Cloud Messaging creates a new token + } + + override fun registeringFailed(token: String, throwable: Throwable) { + // Triggered when Firebase Cloud Messaging if there is an error with registering with the Push Server with a new token + } + + override fun onMessage(message: Core.Model.Message, originalMessage: RemoteMessage) { + // Triggered when a message is sent from the Push Server through Firebase Cloud Messaging and the message contains `Core.Model.Message`. The original FCM RemoteMessage is also returned + } + + override fun onDefaultBehavior(message: RemoteMessage) { + // Triggered when a message is sent from the Push Server through Firebase Cloud Messaging and the message does not contain `Core.Model.Message` in the payload. The original FCM RemoteMessage returned instead + } + + override fun onError(throwable: Throwable, defaultMessage: RemoteMessage) { + // Triggered when there is an error that occurs when a message is received from the Push Server + } +} +``` + +```xml + + + + + + + +``` diff --git a/network/wallets/android/one-click-auth.mdx b/network/wallets/android/one-click-auth.mdx new file mode 100644 index 0000000..10b527e --- /dev/null +++ b/network/wallets/android/one-click-auth.mdx @@ -0,0 +1,114 @@ +--- +title: One-click Auth +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem. + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/authenticatedSessions-light.png) + + +## Handling Authentication Requests + +To handle incoming authentication requests, set up WalletKit.WalletDelegate. The onSessionAuthenticate callback will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```kotlin +override val onSessionAuthenticate: ((Wallet.Model.SessionAuthenticate, Wallet.Model.VerifyContext) -> Unit) + get() = { sessionAuthenticate, verifyContext -> + // Triggered when wallet receives the session authenticate sent by a Dapp + // Process the authentication request here + // This involves displaying UI to the user +} +``` + +## Authentication Objects/Payloads + +#### Responding to Authentication Requests + +To interact with authentication requests, build authentication objects (Wallet.Model.Cacao). It involves the following steps: + +- **Creating an Authentication Payload Params** - Generate an authentication payload params that matches your application's supported chains and methods. +- **Formatting Authentication Messages** - Format the authentication message using the payload and the user's account. +- **Signing the Authentication Message** - Sign the formatted message to create a verifiable authentication object. + +Example: + +```kotlin +override val onSessionAuthenticate: ((Wallet.Model.SessionAuthenticate, Wallet.Model.VerifyContext) -> Unit) + get() = { sessionAuthenticate, verifyContext -> + val auths = mutableListOf() + + val authPayloadParams = + WalletKit.generateAuthPayloadParams( + sessionAuthenticate.payloadParams, + supportedChains = listOf("eip155:1", "eip155:137", "eip155:56"), // Note: Only EVM chains are supported + supportedMethods = listOf("personal_sign", "eth_signTypedData", "eth_sign") + ) + + authPayloadParams.chains.forEach { chain -> + val issuer = "did:pkh:$chain:$address" + val formattedMessage = WalletKit.formatAuthMessage(Wallet.Params.FormatAuthMessage(authPayloadParams, issuer)) + + val signature = signMessage(message: formattedMessage, privateKey: privateKey) //Note: Assume `signMessage` is a function you've implemented to sign messages. + val auth = WalletKit.generateAuthObject(authPayloadParams, issuer, signature) + auths.add(auth) + } +} +``` + +## Approving Authentication Requests + + + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + + +To approve an authentication request, construct Wallet.Model.Cacao instances for each supported chain, sign the authentication messages, generate AuthObjects and call approveSessionAuthenticate with the request ID and the authentication objects. + +```kotlin + val approveAuthenticate = Wallet.Params.ApproveSessionAuthenticate(id = sessionAuthenticate.id, auths = auths) +WalletKit.approveSessionAuthenticate(approveProposal, + onSuccess = { + //Redirect back to the dapp if redirect is set: sessionAuthenticate.participant.metadata?.redirect + }, + onError = { error -> + //Handle error + } +) +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSessionAuthenticate method. + +```kotlin +val rejectParams = Wallet.Params.RejectSessionAuthenticate( + id = sessionAuthenticate.id, + reason = "Reason" +) + +WalletKit.rejectSessionAuthenticate(rejectParams, + onSuccess = { + //Success + }, + onError = { error -> + //Handle error + } +) +``` + +## Testing One-click Auth + +You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/android/resources.mdx b/network/wallets/android/resources.mdx new file mode 100644 index 0000000..3b1ad7a --- /dev/null +++ b/network/wallets/android/resources.mdx @@ -0,0 +1,27 @@ +--- +title: Resources +--- + +Valuable assets for developers and users interested in integrating Wallet SDK into their applications. + +- [Awesome WalletConnect](https://github.com/WalletConnect/awesome-walletconnect) - Community-curated collection of WalletConnect-enabled wallets, libraries, and tools. +- [AppKit Laboratory](https://appkit-lab.reown.com/) - A place to test your wallet integrations against various setups of AppKit. +- [Wallet SDK GitHub](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/web3wallet) - Wallet SDK GitHub repository. + +### Wallet Resources + +To check more in details go and visit our [Wallet SDK Kotlin implementation app](https://github.com/reown-com/reown-kotlin/tree/develop/sample/wallet). Sample Wallet and Dapp .apk files can be found under the latest release tag in [Kotlin's V2 repository](https://github.com/reown-com/reown-kotlin/tags) + +If you need to test your app's integration, you can use one of our following demo dapps. + +**Sign** + +- [React dApp (with standalone client) - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) ([Demo](https://react-app.reown.com/)) + +### Dapp Resources + +Sample Wallet and Dapp .apk files can be found under the latest release tag in [Kotlin's V2 repository](https://github.com/reown-com/reown-kotlin/tags) + +**Sign** + +- [React dApp (with standalone client) - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) ([Demo](https://react-app.reown.com/)) diff --git a/network/wallets/android/usage.mdx b/network/wallets/android/usage.mdx new file mode 100644 index 0000000..a37f38a --- /dev/null +++ b/network/wallets/android/usage.mdx @@ -0,0 +1,429 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section. + +**[Initialization](#initialization)**: Creating a new WalletKit instance and initializing it with a projectId from [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +**Session**: Connection between a dapp and a wallet. + +- [Namespace Builder](#namespace-builder): + Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object +- [Session Approval](#session-approval): + Approving a session sent from a dapp +- [Session Rejection](#session-rejection): + Rejecting a session sent from a dapp +- [Responding to Session Requests](#responding-to-session-requests): + Responding to session requests sent from a dapp +- [Updating a Session](#updating-a-session): + Updating a session sent between a dapp and wallet +- [Extending a Session](#extending-a-session): + Extending a session between a dapp and wallet +- [Session Disconnect](#session-disconnect): + Disconnecting a session between a dapp and wallet +- [Register Device Token](#register-device-token) + Enabling Wallet Push Notifications by registering a device token. +- [WalletKit.WalletDelegate](#walletkitwalletdelegate) + Setting and overriding functions through WalletKit delegate. Also includes instructions about VerifyContext. +- [Format Message](#format-message) + Receiving formatted SIWE message + +To check the full list of platform specific instructions for your preferred platform, go to [Extra (Platform Specific)](#extra-platform-specific) and select your platform. + + + +## Initialization + +```kotlin +val projectId = "" // Get Project ID at https://dashboard.walletconnect.com/ +val connectionType = ConnectionType.AUTOMATIC or ConnectionType.MANUAL +val telemetryEnabled: Boolean = true +val appMetaData = Core.Model.AppMetaData( + name = "Wallet Name", + description = "Wallet Description", + url = "Wallet URL", + icons = /*list of icon url strings*/, + redirect = "kotlin-wallet-wc:/request" // Custom Redirect URI +) + +CoreClient.initialize(projectId = projectId, connectionType = connectionType, application = this, metaData = appMetaData, telemetryEnabled = telemetryEnabled) + +val initParams = Wallet.Params.Init(core = CoreClient) + +WalletKit.initialize(initParams) { error -> + // Error will be thrown if there's an issue during initialization +} +``` + +The WalletKit client will always be responsible for exposing accounts (CAIP10 compatible) to a Dapp and therefore is also in charge of signing. +To initialize the WalletKit client, create a `Wallet.Params.Init` object in the Android Application class with the Core Client. The `Wallet.Params.Init` object will then be passed to the `WalletKit`initialize function. + +The telemetry feature aims to improve the reliability and observability of connection flows between decentralized applications (dapps) and wallets. +It focuses solely on collecting data about code execution and error codes, without tracking any sensitive user information like amounts, accounts etc. + +It provides a comprehensive tracing system for three key use cases: + +- Subscribing to a Pairing Topic +- Approving a Session +- Approving an Authenticated Session + +Each execution trace consists of: + +- Trace Events: Collected to verify the proper execution of code. +- Error Events: Captured when errors occur during the trace, halting the execution trace. + +When an error event is encountered, it is stored locally within the SDK along with all preceding trace events. +These stored events are then transmitted to the server whenever the SDK is initialized. + +Error event tracing is enabled by default. + +Telemetry Enabled (telemetryEnabled = true): + +- The SDK stores events and sends them to the server. + +Telemetry Disabled (telemetryEnabled = false): + +- The SDK stops storing new events and deletes all unsent events from local storage upon the next initialization. + +Important Note: Since the SDK only stores abstract trace and error data, user identification is not possible. + +Example of the error events: + +```json +[ + { + "eventId": "69e53f11-fd4b-4efc-8d36-1f60a9ac8207", + "bundleId": "com.wallet.example", + "timestamp": 1689611327943, + "props": { + "event": "ERROR", + "type": "pairing_already_exists", + "properties": { + "topic": "topic1", + "trace": [ + "pairing_started", + "pairing_uri_validation_success", + "pairing_uri_not_expired", + "existing_pairing", + "pairing_not_expired", + "pairing_not_expired" + ] + } + } + }, + { + "eventId": "69e53f11-fd4b-4efc-8d36-2321312fds", + "bundleId": "com.wallet.example", + "timestamp": 16896113234323, + "props": { + "event": "ERROR", + "type": "session_approve_namespace_validation_failure", + "properties": { + "topic": "topic2", + "trace": ["session_approve_started", "proposal_not_expired"] + } + } + } +] +``` + +## Session + +A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires. + +### Namespace Builder + +With WalletKit 1.7.0 we've published a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your wallet's chains, methods, events, and accounts (supported namespaces) and returns ready-to-use namespaces object that has to be passed into `Wallet.Params.SessionApprove` when approving a session. + +```kotlin +val supportedNamespaces: Wallet.Model.Namespaces.Session = /* a map of all supported namespaces created by a wallet */ +val sessionProposal: Wallet.Model.SessionProposal = /* an object received by `fun onSessionProposal(sessionProposal: Wallet.Model.SessionProposal)` in `WalletKit.WalletDelegate` */ +val sessionNamespaces = WalletKit.generateApprovedNamespaces(sessionProposal, supportedNamespaces) + +val approveParams: Wallet.Params.SessionApprove = Wallet.Params.SessionApprove(proposerPublicKey, sessionNamespaces) +WalletKit.approveSession(approveParams) { error -> /*callback for error while approving a session*/ } +``` + +Examples of supported namespaces: + +```kotlin + val supportedNamespaces = mapOf( + "eip155" to Wallet.Model.Namespace.Session( + chains = listOf("eip155:1", "eip155:137", "eip155:3"), + methods = listOf("personal_sign", "eth_sendTransaction", "eth_signTransaction"), + events = listOf("chainChanged"), + accounts = listOf("eip155:1:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:137:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:3:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092") + ) +) + + val anotherSupportedNamespaces = mapOf( + "eip155" to Wallet.Model.Namespace.Session( + chains = listOf("eip155:1", "eip155:2", "eip155:4"), + methods = listOf("personal_sign", "eth_sendTransaction", "eth_signTransaction"), + events = listOf("chainChanged", "accountsChanged"), + accounts = listOf("eip155:1:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:2:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:4:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092") + ), + "cosmos" to Wallet.Model.Namespace.Session( + chains = listOf("cosmos:cosmoshub-4"), + methods = listOf("cosmos_method"), + events = listOf("cosmos_event"), + accounts = listOf("cosmos:cosmoshub-4:cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02") + ) +) + +``` + +### EVM methods & events + +In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events: + +```ts +{ + //... + methods: [ + "eth_accounts", + "eth_requestAccounts", + "eth_sendRawTransaction", + "eth_sign", + "eth_signTransaction", + "eth_signTypedData", + "eth_signTypedData_v3", + "eth_signTypedData_v4", + "eth_sendTransaction", + "personal_sign", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + "wallet_getPermissions", + "wallet_requestPermissions", + "wallet_registerOnboarding", + "wallet_watchAsset", + "wallet_scanQRCode", + "wallet_sendCalls", + "wallet_getCallsStatus", + "wallet_showCallsStatus", + "wallet_getCapabilities", + ], + events: [ + "chainChanged", + "accountsChanged", + "message", + "disconnect", + "connect", + ] +} +``` + +### Session Approval + + + +Addresses provided in `accounts` array should follow [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) +semantics. + + + +```kotlin +val proposerPublicKey: String = /*Proposer publicKey from SessionProposal object*/ +val namespace: String = /*Namespace identifier, see for reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md#syntax*/ +val accounts: List = /*List of accounts on chains*/ +val methods: List = /*List of methods that wallet approves*/ +val events: List = /*List of events that wallet approves*/ +val namespaces: Map = mapOf(namespace, Wallet.Model.Namespaces.Session(accounts, methods, events)) + +val approveParams: Wallet.Params.SessionApprove = Wallet.Params.SessionApprove(proposerPublicKey, namespaces) +WalletKit.approveSession(approveParams) { error -> /*callback for error while approving a session*/ } +``` + +To send an approval, pass a Proposer's Public Key along with the map of namespaces to the `WalletKit.approveSession` function. + +### Session Rejection + +```kotlin +val proposerPublicKey: String = /*Proposer publicKey from SessionProposal object*/ +val rejectionReason: String = /*The reason for rejecting the Session Proposal*/ +val rejectionCode: String = /*The code for rejecting the Session Proposal*/ +For reference use CAIP-25: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md + +val rejectParams: Wallet.Params.SessionReject = SessionReject(proposerPublicKey, rejectionReason, rejectionCode) +WalletKit.rejectSession(rejectParams) { error -> /*callback for error while rejecting a session*/ } +``` + +To send a rejection for the Session Proposal, pass a proposerPublicKey, rejection reason and rejection code to +the `WalletKit.rejectSession` function. + +### Responding to Session requests + +```kotlin +val sessionTopic: String = /*Topic of Session*/ +val jsonRpcResponse: Wallet.Model.JsonRpcResponse.JsonRpcResult = /*Active Session Request ID along with request data*/ +val result = Wallet.Params.SessionRequestResponse(sessionTopic = sessionTopic, jsonRpcResponse = jsonRpcResponse) + +WalletKit.respondSessionRequest(result) { error -> /*callback for error while responding session request*/ } +``` + +To respond to JSON-RPC method that were sent from Dapps for a session, submit a `Wallet.Params.SessionRequestResponse` with the session's topic and request +ID along with the respond data to the `WalletKit.respondSessionRequest` function. + +### Updating a Session + +NOTE: addresses provided in `accounts` array should follow [CAIP10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) +semantics. + +```kotlin +val sessionTopic: String = /*Topic of Session*/ +val namespace: String = /*Namespace identifier, see for reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md#syntax*/ +val accounts: List = /*List of accounts on chains*/ +val methods: List = /*List of methods that wallet approves*/ +val events: List = /*List of events that wallet approves*/ +val namespaces: Map = mapOf(namespace, Wallet.Model.Namespaces.Session(accounts, methods, events)) +val updateParams = Wallet.Params.SessionUpdate(sessionTopic, namespaces) + +WalletKit.updateSession(updateParams) { error -> /*callback for error while sending session update*/ } +``` + +To update a session with namespaces, submit a `Wallet.Params.SessionUpdate` object with the session's topic and namespaces to update session with +to `WalletKit.updateSession`. + +### Extending a Session + +```kotlin +val sessionTopic: String = /*Topic of Session*/ +val extendParams = Wallet.Params.SessionExtend(sessionTopic = sessionTopic) + +WalletKit.extendSession(extendParams) { error -> /*callback for error while extending a session*/ } +``` + +To extend a session, create a `Wallet.Params.SessionExtend` object with the session's topic to update the session with to `WalletKit.extendSession`. Session is +extended by 7 days. + +### Emitting a Session + +To emit an event, call emitSessionEvent() as follows: + +```kotlin +val sessionTopic: String = /*Topic of Session*/ +val event: Wallet.Model.SessiomEvent = SessionEvent(name = "accountsChanged", data = "0x000000000") + +val sessionEmit = Wallet.Params.SessionEmit(topic = sessionTopic, chainId = "eip155:1", event = event) + +WalletKit.emitSessionEvent(sessionEmit) { error -> /*callback for error while emiting an event*/ } +``` + +### Session Disconnect + +```kotlin +val disconnectionReason: String = /*The reason for disconnecting the Session*/ +val disconnectionCode: String = /*The code for disconnecting the Session*/ +val sessionTopic: String = /*Topic from the Session*/ +For reference use CAIP-25: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md +val disconnectParams = Wallet.Params.SessionDisconnect(sessionTopic, disconnectionReason, disconnectionCode) + +WalletKit.disconnectSession(disconnectParams) { error -> /*callback for error while disconnecting a session*/ } +``` + +To disconnect from un active session, pass a disconnection reason with code and the Session topic to the `WalletKit.disconnectSession` +function. + +## Extra (Platform Specific) + +#### WalletKit.WalletDelegate + +```kotlin +val walletDelegate = object : WalletKit.WalletDelegate { + override fun onSessionProposal(sessionProposal: Wallet.Model.SessionProposal, verifyContext: Wallet.Model.VerifyContext) { + // Triggered when wallet receives the session proposal sent by a Dapp + } + + fun onSessionAuthenticate(sessionAuthenticate: Wallet.Model.SessionAuthenticate, verifyContext: Wallet.Model.VerifyContext) { + // Triggered when wallet receives the session authenticate sent by a Dapp + } + + override fun onSessionRequest(sessionRequest: Wallet.Model.SessionRequest, verifyContext: Wallet.Model.VerifyContext) { + // Triggered when a Dapp sends SessionRequest to sign a transaction or a message + } + + override fun onAuthRequest(authRequest: Wallet.Model.AuthRequest, verifyContext: Wallet.Model.VerifyContext) { + // Triggered when Dapp / Requester makes an authorization request + } + + override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) { + // Triggered when the session is deleted by the peer + } + + override fun onSessionSettleResponse(settleSessionResponse: Wallet.Model.SettledSessionResponse) { + // Triggered when wallet receives the session settlement response from Dapp + } + + override fun onSessionUpdateResponse(sessionUpdateResponse: Wallet.Model.SessionUpdateResponse) { + // Triggered when wallet receives the session update response from Dapp + } + + override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) { + //Triggered whenever the connection state is changed + } + + override fun onError(error: Wallet.Model.Error) { + // Triggered whenever there is an issue inside the SDK + } +} +WalletKit.setWalletDelegate(walletDelegate) +``` + +`Wallet.Event.VerifyContext` provides a domain verification information about SessionProposal, SessionRequest and AuthRequest. It consists of origin of a Dapp from where the request has been sent, validation Enum that says whether origin is VALID, INVALID or UNKNOWN and verify url server. + +```kotlin +data class VerifyContext( + val id: Long, + val origin: String, + val validation: Model.Validation, + val verifyUrl: String +) + +enum class Validation { + VALID, INVALID, UNKNOWN +} +``` + +The WalletKit needs a `WalletKit.WalletDelegate` passed to it for it to be able to expose asynchronous updates sent from the Dapp. + +# + +#### Format message + +To receive formatted SIWE message, call formatMessage method with following parameters: + +```kotlin +val payloadParams: Wallet.Params.PayloadParams = //PayloadParams received in the onAuthRequest callback +val issuer = //MUST be the same as send with the respond methods and follows: https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md +val formatMessage = Wallet.Params.FormatMessage(event.payloadParams, issuer) + +WalletKit.formatMessage(formatMessage) +``` + +#### Register Device Token + +This method enables wallets to receive push notifications from WalletConnect's Push Server via [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging). This means you will have to setup your project with Firebase before being able to call registerDeviceToken method. + +Make sure that a service extending the FirebaseMessagingService is added to your manifest as per the [Firebase FCM documentation](https://firebase.google.com/docs/cloud-messaging/android/client#manifest) as well as any other setup Firebase requires [Firebase setup documentation](https://firebase.google.com/docs/android/setup). + +To register a wallet to receive WalletConnect push notifications, call `WalletKit.registerDeviceToken` and pass the Firebase Access Token. + +```kotlin +val firebaseAccessToken: String = //FCM access token received through the Firebase Messaging SDK + +WalletKit.registerDeviceToken( + firebaseAccessToken, + onSuccess = { + // callback triggered once registered successfully with the Push Server + }, + onError = { error: Wallet.Model.Error -> + // callback triggered if there's an exception thrown during the registration process + }) +``` diff --git a/network/wallets/android/verify.mdx b/network/wallets/android/verify.mdx new file mode 100644 index 0000000..882a04e --- /dev/null +++ b/network/wallets/android/verify.mdx @@ -0,0 +1,50 @@ +--- +title: Verify API +--- + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. +Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +These are: + + + + + +## Disclaimer + +Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + +## Domain risk detection + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +- Domain match: The domain linked to this request has been verified as this application's domain. + - This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +- Unverified: The domain sending the request cannot be verified. + - This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +- Mismatch: The application's domain doesn't match the sender of this request. + - This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +- Threat: This domain is flagged as malicious and potentially harmful. + - This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Implementation + +Wallet.Event.VerifyContext provides a domain verification information about SessionProposal, SessionRequest and AuthRequest. + +It consists of origin of an app from where the request has been sent, validation Enum that says whether origin is `VALID`, `INVALID` or `UNKNOWN` and verify url server. + +```kotlin +data class VerifyContext( + val id: Long, + val origin: String, + val validation: Model.Validation, + val verifyUrl: String +) + +enum class Validation { + VALID, INVALID, UNKNOWN +} +``` diff --git a/network/wallets/best-practices.mdx b/network/wallets/best-practices.mdx new file mode 100644 index 0000000..4cca006 --- /dev/null +++ b/network/wallets/best-practices.mdx @@ -0,0 +1,748 @@ +--- +sidebarTitle: Best Practices +title: Best Practices for Wallets +--- + +To ensure the smoothest and most seamless experience for our users, WalletConnect is committed to working closely with wallet providers to encourage the adoption of our recommended best practices. + +By implementing these guidelines, we aim to optimize performance and minimize potential challenges, even in suboptimal network conditions. + +We are actively partnering with wallet developers to optimize performance in scenarios such as: + +1. **Success and Error Messages** - Users need to know what’s going on, at all times. Too much communication is better than too little. The less users need to figure out themselves or assume what’s going on, the better. +2. **(Perceived) Latency** - A lot of factors can influence latency (or perceived latency), e.g. network conditions, position in the boot chain, waiting on the wallet to connect or complete a transaction and not knowing if or when it has done it. +3. **Old SDK Versions** - Older versions can have known and already fixed bugs, leading to unnecessary issues to users, which can be simply and quickly solved by updating to the latest SDK. + +To take all of the above into account and to make experience better for users, we've put together some key guidelines for wallet providers. These best practices focus on the most important areas for improving user experience. + +Please follow these best practices and make the experience for your users and yourself a delightful and quick one. + +## Checklist Before Going Live + +To make sure your wallet adheres to the best practices, we recommend implementing the following checklist before going live. You can find more detailed information on each point below. + +1. **Success and Error Messages** + * ✅ Display clear and concise messages for all user interactions + * ✅ Provide feedback for all user actions + * ✅ Connection success + * ✅ Connection error + * ✅ Loading indicators for waiting on connection, transaction, etc. + * ✅ Ensure that users are informed of the status of their connection and transactions + * ✅ Implement status indicators internet availability + * ✅ Make sure to provide feedback not only to users but also back to the dapp (e.g., if there's an error or a user has not enough funds to pay for gas, don't just display the info message to the user, but also send the error back to the dapp so that it can change the state accordingly) +2. **Mobile Linking** + * ✅ Implement mobile linking to allow for automatic redirection between the wallet and the dapp + * ✅ Use deep linking over universal linking for a better user experience + * ✅ Ensure that the user is redirected back to the dapp after completing a transaction +3. **Latency** + * ✅ Optimize performance to minimize latency + * ✅ Latency for connection in normal conditions: under 5 seconds + * ✅ Latency for connection in poor network (3G) conditions: under 15 seconds + * ✅ Latency for signing in normal conditions: under 5 seconds + * ✅ Latency for signing in poor network (3G) conditions: under 10 seconds +4. **Verify API** + * ✅ Present users with four key states that can help them determine whether the domain they’re about to connect to might be malicious (Domain match, Unverified, Mismatch, Threat) +5. **Latest SDK Version** + * ✅ Ensure that you are using the latest SDK version + * ✅ Update your SDK regularly to benefit from the latest features and bug fixes + * ✅ Subscribe to SDK updates to stay informed about new releases + +## 1. Success and Error Messages + +Users often face ambiguity in determining whether their connection or transactions were successful. They are also not guided to switching back into the dapp or automatically switched back when possible, causing unnecessary user anxiety. Additionally, wallets typically lack status indicators for connection and internet availability, leaving users in the dark. + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/connection-successful.png) + + +### Pairing + +A pairing is a connection between a wallet and a dapp that has fixed permissions to only allow a dapp to propose a session through it. Dapp can propose infinite number of sessions on one pairing. Wallet must use a pair method from WalletKit client to pair with dapp. + + + + ```jsx + const uri = 'xxx'; // pairing uri + try { + await walletKit.pair({ uri }); + } catch (error) { + // some error happens while pairing - check Expected errors section + } + ``` + + + + ```jsx + const uri = 'xxx'; // pairing uri + try { + await walletKit.pair({ uri }); + } catch (error) { + // some error happens while pairing - check Expected errors section + } + ``` + + + + ```swift + let uri = WalletConnectURI(string: urlString) + + if let uri { + Task { + try await WalletKit.instance.pair(uri: uri) + } + } + + ``` + + + + ```kotlin + val pairingParams = Wallet.Params.Pair(pairingUri) + WalletKit.pair(pairingParams, + onSuccess = { + //Subscribed on the pairing topic successfully. Wallet should await for a session proposal + }, + onError = { error -> + //Some error happens while pairing - check Expected errors section + } + } + ``` + + + +#### Pairing Expiry + +A pairing expiry event is triggered whenever a pairing is expired. The expiry for inactive pairing is 5 mins, whereas for active pairing is 30 days. A pairing becomes active when a session proposal is received and user successfully approves it. This event helps to know when given pairing expires and update UI accordingly. + + + + ```typescript + core.pairing.events.on("pairing_expire", (event) => { + // pairing expired before user approved/rejected a session proposal + const { topic } = topic; + }); + ``` + + + + ```typescript + core.pairing.events.on("pairing_expire", (event) => { + // pairing expired before user approved/rejected a session proposal + const { topic } = topic; + }); + ``` + + + + ```Swift + WalletKit.instance.pairingExpirationPublisher + .receive(on: DispatchQueue.main) + .sink { pairing in + guard !pairing.active else { return } + // let user know that pairing has expired + }.store(in: &publishers) + ``` + + + + ```kotlin + val coreDelegate = object : CoreClient.CoreDelegate { + override fun onPairingExpired(expiredPairing: Core.Model.ExpiredPairing) { + // Here a pairing expiry is triggered + } + // ...other callbacks + } + + CoreClient.setDelegate(coreDelegate) + + ``` + + + +#### Pairing messages + +1. Consider displaying a successful pairing message when pairing is successful. Before that happens, wallet should show a loading indicator. +2. Display an error message when a pairing fails. + +#### Expected Errors + +While pairing, the following errors might occur: + +* **No Internet connection error or pairing timeout when scanning QR with no Internet connection** + * User should pair again with Internet connection +* **Pairing expired error when scanning a QR code with expired pairing** + * User should refresh a QR code and scan again +* **Pairing with existing pairing is not allowed** + * User should refresh a QR code and scan again. It usually happens when user scans an already paired QR code. + +### Session Proposal + +A session proposal is a handshake sent by a dapp and its purpose is to define session rules. Whenever a user wants to establish a connection between a wallet and a dapp, one should approve a session proposal. + +Whenever user approves or rejects a session proposal, a wallet should show a loading indicator the moment the button is pressed, until Relay acknowledgement is received for any of these actions. + +#### Approving session + + + + ```typescript + try { + await walletKit.approveSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```typescript + try { + await walletKit.approveSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```swift + do { + try await WalletKit.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties) + // Update UI, remove loader + } catch { + // present error + } + ``` + + + + ```kotlin + WalletKit.approveSession(approveProposal, + onSuccess = { + //Session approval response was sent successfully - update your UI + } + onError = { error -> + //Error while sending session approval - update your UI + }) + ``` + + + +#### Rejecting session + + + + ```typescript + try { + await walletKit.rejectSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```typescript + try { + await walletKit.rejectSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```swift + do { + try await WalletKit.instance.reject(proposalId: proposal.id, reason: .userRejected) + // Update UI, remove loader + } catch { + // present error + } + ``` + + + + ```kotlin + WalletKit.rejectSession(reject, + onSuccess = { + //Session rejection response was sent successfully - update your UI + }, + onError = { error -> + //Error while sending session rejection - update your UI + }) + ``` + + + +#### Session proposal expiry + +A session proposal expiry is 5 minutes. It means a given proposal is stored for 5 minutes in the SDK storage and user has 5 minutes for the approval or rejection decision. After that time, the below event is emitted and proposal modal should be removed from the app's UI. + + + + ```typescript + walletKit.on("proposal_expire", (event) => { + // proposal expired and any modal displaying it should be removed + const { id } = event; + }); + ``` + + + + ```typescript + walletKit.on("proposal_expire", (event) => { + // proposal expired and any modal displaying it should be removed + const { id } = event; + }); + ``` + + + + ```swift + WalletKit.instance.sessionProposalExpirationPublisher.sink { _ in + // let user know that session proposal has expired, update UI + }.store(in: &publishers) + ``` + + + + ```kotlin + val walletDelegate = object : WalletKit.WalletDelegate { + override fun onProposalExpired(proposal: Wallet.Model.ExpiredProposal) { + // Here this event is triggered when a proposal expires - update your UI + } + // ...other callbacks + } + WalletKit.setWalletDelegate(walletDelegate) + ``` + + + +#### Session Proposal messages + +1. Consider displaying a successful session proposal message before redirecting back to the dapp. Before the success message is displayed, wallet should show a loading indicator. +2. Display an error message when session proposal fails. + +#### Expected errors + +While approving or rejecting a session proposal, the following errors might occur: + +* **No Internet connection** + * It happens when a user tries to approve or reject a session proposal with no Internet connection +* **Session proposal expired** + * It happens when a user tries to approve or reject an expired session proposal +* **Invalid [namespaces](https://docs.reown.com/advanced/glossary#namespaces)** + * It happens when a validation of session namespaces fails +* **Timeout** + * It happens when Relay doesn't acknowledge session settle publish within 10s + +### Session Request + +A session request represents the request sent by a dapp to a wallet. + +Whenever user approves or rejects a session request, a wallet should show a loading indicator the moment the button is pressed, until Relay acknowledgement is received for any of these actions. + + + + ```typescript + try { + await walletKit.respondSessionRequest(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```typescript + try { + await walletKit.respondSessionRequest(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } + ``` + + + + ```swift + do { + try await WalletKit.instance.respond(requestId: request.id, signature: signature, from: account) + // update UI -> remove the loader + } catch { + // present error to the user + } + ``` + + + + ```kotlin + WalletKit.respondSessionRequest(Wallet.Params.SessionRequestResponse, + onSuccess = { + //Session request response was sent successfully - update your UI + }, + onError = { error -> + //Error while sending session response - update your UI + }) + ``` + + + +#### Session request expiry + +A session request expiry is defined by a dapp. Its value must be between `now() + 5mins` and `now() + 7 days`. After the session request expires, the below event is emitted and session request modal should be removed from the app's UI. + + + + ```typescript + walletKit.on("session_request_expire", (event) => { + // request expired and any modal displaying it should be removed + const { id } = event; + }); + ``` + + + + ```typescript + walletKit.on("session_request_expire", (event) => { + // request expired and any modal displaying it should be removed + const { id } = event; + }); + ``` + + + + ```swift + WalletKit.instance.requestExpirationPublisher.sink { _ in + // let user know that request has expired + }.store(in: &publishers) + ``` + + + + ```kotlin + val walletDelegate = object : WalletKit.WalletDelegate { + override fun onRequestExpired(request: Wallet.Model.ExpiredRequest) { + // Here this event is triggered when a session request expires - update your UI + } + // ...other callbacks + } + WalletKit.setWalletDelegate(walletDelegate) + ``` + + + +#### Expected errors + +While approving or rejecting a session request, the following errors might occur: + +* **Invalid session** + * This error might happen when a user approves or rejects a session request on an expired session +* **Session request expired** + * This error might happen when a user approves or rejects a session request that already expired +* **Timeout** + * It happens when Relay doesn't acknowledge session settle publish within 10 seconds + +### Connection state + +The Web Socket connection state tracks the connection with the Relay server. An event is emitted whenever a connection state changes. + + + + ```typescript + core.relayer.on("relayer_connect", () => { + // connection to the relay server is established + }) + + core.relayer.on("relayer_disconnect", () => { + // connection to the relay server is lost + }) + + ``` + + + + ```typescript + core.relayer.on("relayer_connect", () => { + // connection to the relay server is established + }) + + core.relayer.on("relayer_disconnect", () => { + // connection to the relay server is lost + }) + ``` + + + + ```swift + WalletKit.instance.socketConnectionStatusPublisher + .receive(on: DispatchQueue.main) + .sink { status in + switch status { + case .connected: + // ... + case .disconnected: + // ... + } + }.store(in: &publishers) + ``` + + + + ```kotlin + val walletDelegate = object : WalletKit.WalletDelegate { + override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) { + // Here this event is triggered when a connection state has changed + } + // ...other callbacks + } + WalletKit.setWalletDelegate(walletDelegate) + ``` + + + +#### Connection state messages + +When the connection state changes, show a message in the UI. For example, display a message when the connection is lost or re-established. + +## 2. Mobile Linking + +### Why use Mobile Linking? + +Mobile Linking uses the mobile device’s native OS to automatically redirect between the native wallet app and a native app. This results in few user actions a better UX. + +#### Establishing Communication Between Mobile Wallets and Apps + +When integrating a wallet with a mobile application, it's essential to understand how they communicate. The process involves two main steps: + +1. **QR Code Handshake:** The mobile app (Dapp) generates a unique URI (Uniform Resource Identifier) and displays it as a QR code. This URI acts like a secret handshake. When the user scans the QR code or copy/pastes the URI using their wallet app, they establish a connection. It's like saying, "Hey, let's chat!" +2. **Deep Links and Universal Links:** The URI from the QR code allows the wallet app to create a [deep link](https://support.google.com/google-ads/answer/10023042) or [universal link](https://developer.apple.com/ios/universal-links/). These links work on both Android and iOS. They enable seamless communication between the wallet and the app. + + + **Developers should prefer Deep Linking over Universal Linking.** + + Universal Linking may redirect the user to a browser, which might not provide the intended user experience. Deep Linking ensures the user is taken directly to the app. + + +### Key Behavior to Address + +In some scenarios, wallets use redirect metadata provided in session proposals to open applications. This can cause unintended behavior, such as: + +Redirecting to the wrong app when multiple apps share the same redirect metadata (e.g., a desktop and mobile version of the same Dapp). +Opening an unrelated application if a QR code is scanned on a different device than where the wallet is installed. + +#### Recommended Approach + +To avoid this behavior, wallets should: + +* **Restrict Redirect Metadata to Deep Link Use Cases**: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. + +### Connection Flow + +1. **Dapp prompts user:** The Dapp asks the user to connect. +2. **User chooses wallet:** The user selects a wallet from a list of compatible wallets. +3. **Redirect to wallet:** The user is redirected to their chosen wallet. +4. **Wallet approval:** The wallet prompts the user to approve or reject the session (similar to granting permission). +5. **Return to dapp:** + * **Manual return:** The wallet asks the user to manually return to the Dapp. + * **Automatic return:** Alternatively, the wallet automatically takes the user back to the Dapp. +6. **User reunites with dapp:** After all the interactions, the user ends up back in the Dapp. + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking-light.png) + + +### Sign Request Flow + +When the Dapp needs the user to sign something (like a transaction), a similar pattern occurs: + +1. **Automatic redirect:** The Dapp automatically sends the user to their previously chosen wallet. +2. **Approval prompt:** The wallet asks the user to approve or reject the request. +3. **Return to dapp:** + * **Manual return:** The wallet asks the user to manually return to the Dapp. + * **Automatic return:** Alternatively, the wallet automatically takes the user back to the Dapp. +4. **User reconnects:** Eventually, the user returns to the Dapp. + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking_sign-light.png) + + +### Platform Specific Preparation + + + + Read the specific steps for iOS here: [Platform preparations](./ios/mobile-linking#platform-preparations) + + + + Read the specific steps for Android here: [Platform + preparations](./android/mobile-linking#platform-preparations) + + + + Read the specific steps for Flutter here: [Platform + preparations](./flutter/mobile-linking#platform-preparations) + + + + Read the specific steps for React Native here: [Platform preparations](./react-native/mobile-linking#platform-preparations) + + + +### How to Test + +To experience the desired behavior, try our Sample Wallet and Dapps which use our Mobile linking best practices. These are available on all platforms. + +Once you have completed your integration, you can test it against our sample apps to see if it is working as expected. Download the app and and try your mobile linking integration on your device. + + + + * [Sample Wallet](https://testflight.apple.com/join/09bTAryp) - on TestFlight + * [Sample DApp](https://testflight.apple.com/join/7S1GYcjC) - on TestFlight + + + + * [Sample Wallet](https://appdistribution.firebase.dev/i/6f9437a5f9bf4eec) - + on Firebase - [Sample + DApp](https://appdistribution.firebase.dev/i/5e4fe4b30c8a208d) - on Firebase + + + + * Sample Wallet: - [Sample Wallet for + iOS](https://testflight.apple.com/join/Uv0XoBuD) - [Sample Wallet for + Android](https://appdistribution.firebase.dev/i/2b8b3dce9e2831cd) - AppKit + DApp: - [AppKit Dapp for iOS](https://testflight.apple.com/join/6aRJSllc) - + [AppKit Dapp for + Android](https://appdistribution.firebase.dev/i/2c6573f6956fa7b5) + + + + * Sample Wallet: + * [Sample Wallet for Android](https://appdistribution.firebase.dev/i/e7711e780547234e) + * Sample DApp: + * [Sample App for iOS](https://testflight.apple.com/join/Ivd8bg7s) + * [Sample App for Android](https://appdistribution.firebase.dev/i/0297fbd3de8f1e3f) + + + +## 3. Latency + +Our SDK’s position in the boot chain can lead to up to 15 seconds in throttled network conditions. Lack of loading indicators exacerbates the perceived latency issues, impacting user experience negatively. Additionally, users often do not receive error messages or codes when issues occur or timeouts happen. + +### Target latency + +For **connecting**, the target latency is: + +* **Under 5 seconds** in normal conditions +* **Under 15 seconds** when throttled (3G network speed) + +For **signing**, the target latency is: + +* **Under 5 seconds** in normal conditions +* **Under 10 seconds** when throttled (3G network speed) + +### How to test + +To test latency under suboptimal network conditions, you can enable throttling on your mobile phone. You can simulate different network conditions to see how your app behaves in various scenarios. + +For example, on iOS you need to enable Developer Mode and then go to **Settings > Developer > Network Link Conditioner**. You can then select the network condition you want to simulate. For 3G, you can select **3G** from the list, for no network or timeout simulations, choose **100% Loss**. + +Check this article for how to simulate slow internet connection on iOS & Android, with multiple options for both platforms: [How to simulate slow internet connection on iOS & Android](https://www.browserstack.com/guide/how-to-simulate-slow-network-conditions). + +## 4. Verify API + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect's domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +Possible states: + +* Domain match +* Unverified +* Mismatch +* Threat + + + ![Verify States](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/verify-states-1.png) + + + + ![Verify States](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/verify-states-2.png) + + + + Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + + +### Domain risk detection[](https://docs.reown.com/walletkit/web/verify#domain-risk-detection) + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +* **Domain match:** The domain linked to this request has been verified as this application's domain. + * This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +* **Unverified:** The domain sending the request cannot be verified. + * This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +* **Mismatch:** The application's domain doesn't match the sender of this request. + * This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +* **Threat:** This domain is flagged as malicious and potentially harmful. + * This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Verify API Implementation + +To see how to implement Verify API for your framework, see [Verify API](./features/verify) page and select your platform to see code examples. + +### How to test + +To test Verify API with a malicious domain, you can check out the [Malicious React dapp](https://malicious-app-verify-simulation.vercel.app/), created specifically for testing. This app is flagged as malicious and will have the `isScam` parameter set to `true` in the `verifyContext` of the request. You can use this app to test how your wallet behaves when connecting to a malicious domain. + +### Error messages + + + ![Verify API flagged domain](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/verify-api-flagged-domain.png) + + +*A sample error warning when trying to connect to a malicious domain* + +## 5. Latest SDK + +Numerous features have been introduced, bugs have been identified and fixed over time, stability has improved, but many dapps and wallets continue to use older SDK versions with known issues, affecting overall reliability. + +Make sure you are using the latest version of the SDK for your platform + + + + * **WalletConnectSwiftV2**: [Latest release](https://github.com/reown-com/reown-swift/releases/latest/) + + + + * **WalletConnectKotlinV2**: [Latest + release](https://github.com/WalletConnect/WalletConnectKotlinV2/releases/latest) + + + + * **WalletConnectFlutterV2**: [Latest + release](https://github.com/WalletConnect/WalletConnectFlutterV2/releases/latest) + + + + * **AppKit for React Native**: [Latest release](https://github.com/WalletConnect/reown-react-native/releases/latest) + + + +### Subscribe to updates + +To stay up to date with the latest SDK releases, you can use GitHub's native feature to subscribe to releases. This way, you will be notified whenever a new release is published. You can find the "Watch" button on the top right of the repository page. Click on it, then select "Custom" and "Releases only". You'll get a helpful ping whenever a new release is out. + +![Subscribe to releases](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/subsribe-to-release-updates.png) + +## Resources + +* [React Wallet](https://react-wallet.reown.com/) - for testing dapps, features, Verify API messages, etc. +* [React dapp](https://react-app.reown.com/) - for testing wallets +* [Malicious React dapp](https://malicious-app-verify-simulation.vercel.app/) - for testing Verify API with malicious domain diff --git a/network/wallets/c-sharp/cloud/analytics.mdx b/network/wallets/c-sharp/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/c-sharp/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/c-sharp/cloud/explorer-submission.mdx b/network/wallets/c-sharp/cloud/explorer-submission.mdx new file mode 100644 index 0000000..e5f11c8 --- /dev/null +++ b/network/wallets/c-sharp/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + diff --git a/network/wallets/c-sharp/cloud/relay.mdx b/network/wallets/c-sharp/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/c-sharp/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/c-sharp/installation.mdx b/network/wallets/c-sharp/installation.mdx new file mode 100644 index 0000000..00e9bdf --- /dev/null +++ b/network/wallets/c-sharp/installation.mdx @@ -0,0 +1,13 @@ +--- +title: Installation +--- + +Install the Wallet SDK client package via Nuget. + +```bash +dotnet add package Reown.WalletKit +``` + +## Next Steps + +Now that you've installed Wallet SDK, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/c-sharp/usage.mdx b/network/wallets/c-sharp/usage.mdx new file mode 100644 index 0000000..6de5558 --- /dev/null +++ b/network/wallets/c-sharp/usage.mdx @@ -0,0 +1,378 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section. + +**[Initialization](#initialization)**: Creating a new WalletKit instance and initializing it with a projectId from [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +**Session**: Connection between a dapp and a wallet. + +- [Namespace Builder](#namespace-builder): + Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object +- [Session Approval](#session-approval): + Approving a session sent from a dapp +- [Session Rejection](#session-rejection): + Rejecting a session sent from a dapp +- [Responding to Session Requests](#responding-to-session-requests): + Responding to session requests sent from a dapp +- [Updating a Session](#updating-a-session): + Updating a session sent between a dapp and wallet +- [Extending a Session](#extending-a-session): + Extending a session between a dapp and wallet +- [Session Disconnect](#session-disconnect): + Disconnecting a session between a dapp and wallet + + + +## Initialization + +First you must setup a `Core` instance with a specific `Name` and `ProjectId`. You may optionally specify other `CoreOption` +values, such as `RelayUrl` and `Storage` + +```csharp +var options = new CoreOptions() +{ + ProjectId = "...", + Name = "my-app", +} + +var core = new CoreClient(options); +``` + +Next, you must define a `Metadata` object which describes your Wallet. This includes a `Name`, `Description`, `Url` and `Icons` url. + +```csharp +var metadata = new Metadata() +{ + Description = "An example wallet to showcase Wallet SDK", + Icons = new[] { "https://walletconnect.com/meta/favicon.ico" }, + Name = $"wallet-csharp-test", + Url = "https://walletconnect.com", +}; +``` + +Once you have both the `Core` and `Metadata` objects, you can initialize the `WalletKitClient` + +```csharp +var sdk = await WalletKitClient.Init(core, metadata, metadata.Name); +``` + +## Session + +A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires. + +### Namespace Builder + +To build a namespace mapping for either proposing a session **OR** approving a session, you can use .NET dictionary + class constructors +directly, or use the built-in builder methods + +### C# Constructor Style + +```csharp +var TestNamespaces = new Namespaces() +{ + { + "eip155", new Namespace() + { + Accounts = new [] { "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" }, + Chains = new []{ "eip155:1" }, + Methods = new[] { "eth_signTransaction" }, + Events = new[] { "chainChanged" } + } + }, +}; +``` + +### Builder Style + +```csharp +var TestNamespaces = new Namespaces() + .WithNamespace("eip155", new Namespace() + .WithChain("eip155:1") + .WithMethod("eth_signTransaction") + .WithEvent("chainChanged") + .WithAccount("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb") + ); +``` + +The `Namespaces` mapping is required when approving a proposed session from a dApp. Because of this, you may +also construct a `Namespaces` from a `RequiredNamespaces`, which auto-populates all `Methods`, `Events` and +`Chains` from the given `RequiredNamespaces`. This is provided for convenience. + +### RequiredNamespaces + +```csharp +sdk.SessionProposed += async (sender, @event) => +{ + var proposal = @event.Proposal; + var requiredNamespaces = proposal.RequiredNamespaces; + var approvedNamespaces = new Namespaces(requiredNamespaces); + approvedNamespaces["eip155"].WithAccount("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"); +}; +``` + +The `RequiredNamespaces` is required when setting up a session between a dApp and Wallet. The +dApp will provide a `RequiredNamespaces` when proposing the session. The `RequiredNamespaces` and +`ProposedNamespace` use the same style constructors + builder functions as `Namespaces` and `Namespace`. + +### EVM methods & events + +In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events: + +```ts +{ + //... + methods: [ + "eth_accounts", + "eth_requestAccounts", + "eth_sendRawTransaction", + "eth_sign", + "eth_signTransaction", + "eth_signTypedData", + "eth_signTypedData_v3", + "eth_signTypedData_v4", + "eth_sendTransaction", + "personal_sign", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + "wallet_getPermissions", + "wallet_requestPermissions", + "wallet_registerOnboarding", + "wallet_watchAsset", + "wallet_scanQRCode", + "wallet_sendCalls", + "wallet_getCallsStatus", + "wallet_showCallsStatus", + "wallet_getCapabilities", + ], + events: [ + "chainChanged", + "accountsChanged", + "message", + "disconnect", + "connect", + ] +} +``` + +### Session Approval + +Wallets can pair an incoming session using the session's Uri. Pairing a session lets the Wallet obtain the connection proposal which can then be approved or denied. + +```csharp +var uri = "..."; +await sdk.Pair(uri); +``` + +The wallet can then approve the proposal by constructing an approved `Namespaces`. The approved +`Namespaces` should include the `RequiredNamespaces` under `proposal.RequiredNamespaces`, and may optionally include any optional namespaces +specified under `proposal.OptionalNamespaces` + +```csharp +sdk.SessionProposed += async (sender, @event) => +{ + var proposal = @event.Proposal; + var requiredNamespaces = proposal.RequiredNamespaces; + var approvedNamespaces = new Namespaces(requiredNamespaces); + approvedNamespaces["eip155"].WithAccount("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"); + + var sessionData = await sdk.ApproveSession(proposal.Id, approvedNamespaces); + var sessionTopic = sessionData.Topic; +}; +``` + +You may also just provide the addresses that will connect, and the SDK will create this approved +`Namespaces` for you. This function **will not approve optional namespaces** + +```csharp +sdk.SessionProposed += async (sender, @event) => +{ + var proposal = @event.Proposal; + + var sessionData = await sdk.ApproveSession(proposal, new[] { "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" }); + var sessionTopic = sessionData.Topic; +}; +``` + +or + +```csharp +sdk.SessionProposed += async (sender, @event) => +{ + var proposal = @event.Proposal; + + var sessionData = await sdk.ApproveSession(proposal, "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"); + var sessionTopic = sessionData.Topic; +}; +``` + +### Session Rejection + +The wallet can reject the proposal using the following: + +```csharp +sdk.SessionProposed += async (sender, @event) => +{ + var proposal = @event.Proposal; + await sdk.RejectSession(proposal, "User rejected"); +}; +``` + +### Responding to Session requests + +Responding to session requests is very similar to sending session requests. See dApp usage on how sending session requests works. All custom session requests requires a request class **and** response class to be created that matches the `params` field type in the custom session request. C# is a static typed language, so these types must be given whenever you do a session request (or do any querying for session requests). + +Currently, **WalletKit does not automatically assume the object type for `params` is an array**. This is very important, since most EVM RPC requests have `params` as an array type. **Use `List` to workaround this**. For example, for `eth_sendTransaction`, use `List` instead of `Transaction`. + +Newtonsoft.Json is used for JSON serialization/deserialization, therefore you can use Newtonsoft.Json attributes when defining fields in your request/response classes. + +### Building a Response type + +Create a class for the response and populate it with the JSON properties the response object has. For this example, we will use `eth_getTransactionReceipt` + +The `params` field for `eth_getTransactionReceipt` has the object type + +```csharp +using Newtonsoft.Json; +using System.Numerics; + +[RpcMethod("eth_getTransactionReceipt"), RpcRequestOptions(Clock.ONE_MINUTE, 99995)] +public class TransactionReceipt +{ + [JsonProperty("transactionHash")] + public string TransactionHash; + + [JsonProperty("transactionIndex")] + public BigInteger TransactionIndex; + + [JsonProperty("blockHash")] + public string BlockHash; + + [JsonProperty("blockNumber")] + public BigInteger BlockNumber; + + [JsonProperty("from")] + public string From; + + [JsonProperty("to")] + public string To; + + [JsonProperty("cumulativeGasUsed")] + public BigInteger CumulativeGasUsed; + + [JsonProperty("effectiveGasPrice ")] + public BigInteger EffectiveGasPrice ; + + [JsonProperty("gasUsed")] + public BigInteger GasUsed; + + [JsonProperty("contractAddress")] + public string ContractAddress; + + [JsonProperty("logs")] + public object[] Logs; + + [JsonProperty("logsBloom")] + public string LogBloom; + + [JsonProperty("type")] + public BigInteger Type; + + [JsonProperty("status")] + public BigInteger Status; +} +``` + +The `RpcMethod` class attributes defines the rpc method this response uses, this is optional. The `RpcResponseOptions` class attributes define the expiry time and tag attached to the response, **this is required**. + +### Sending a response + +To respond to requests from a dApp, you must define the class representing the request object type. The request type for `eth_getTransactionReceipt` is the following: + +```csharp +[RpcMethod("eth_getTransactionReceipt"), RpcRequestOptions(Clock.ONE_MINUTE, 99994)] +public class EthGetTransactionReceipt : List +{ + public EthGetTransactionReceipt(params string[] hashes) : base(hashes) + { + } + + // needed for proper json deserialization + public EthGetTransactionReceipt() + { + } +} +``` + +We can handle the `eth_getTransactionReceipt` session request by doing the following: + +```csharp +walletClient.Engine.SessionRequestEvents().OnRequest += OnEthTransactionReceiptRequest; + +private Task OnEthTransactionReceiptRequest(RequestEventArgs e) +{ + // logic for request goes here + // set e.Response to return a response +} +``` + +The callback function gets invoked whenever the wallet receives the `eth_getTransactionReceipt` request from a connected dApp. You may optionally filter further which requests are handled using the `FilterRequests` function + +```csharp +walletClient.Engine.SessionRequestEvents() + .FilterRequests(r => r.Topic == sessionTopic) + .OnRequest += OnEthTransactionReceiptRequest; +``` + +The callback returns a `Task`, so the callback can be made async. To return a response, **you must** set the `Response` field in `RequestEventArgs` with the desired response. + +```csharp +private async Task OnEthTransactionReceiptRequest(RequestEventArgs e) +{ + var txHash = e.Request.Params[0]; + var receipt = await EthGetTransactionReceipt(txHash); + e.Response = receipt; +} +``` + +### Updating a Session + +Update a session, adding/removing additional namespaces in the given topic. + +```csharp +var newNamespaces = new Namespaces(...); +var request = await walletClient.UpdateSession(sessionTopic, newNamespaces); +await request.Acknowledged(); +``` + +### Extending a Session + +Extend a session's expiry time so the session remains open + +```csharp +var request = await walletClient.Extend(sessionTopic); +await request.Acknowledged(); +``` + +### Session Disconnect + +To disconnect a session, use the `Disconnect` function. You may optional provide a reason for the disconnect. + +Disconnecting requires the `topic` of the session to be given. This can be found in the `SessionStruct` object given when a session has been given approval by the Wallet. + +```csharp +var sessionTopic = sessionData.Topic; +await walletClient.Disconnect(sessionTopic); + +// or + +await walletClient.Disconnect(sessionTopic, Error.FromErrorType(ErrorType.USER_DISCONNECTED)); +``` diff --git a/network/wallets/c-sharp/verify.mdx b/network/wallets/c-sharp/verify.mdx new file mode 100644 index 0000000..8aaaf39 --- /dev/null +++ b/network/wallets/c-sharp/verify.mdx @@ -0,0 +1,99 @@ +--- +title: Verify API +--- + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. +Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect's domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +These are: + + + + + +## Disclaimer + +Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + +## Domain risk detection + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +- Domain match: The domain linked to this request has been verified as this application's domain. + - This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +- Unverified: The domain sending the request cannot be verified. + - This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +- Mismatch: The application's domain doesn't match the sender of this request. + - This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +- Threat: This domain is flagged as malicious and potentially harmful. + - This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Implementation + +`Reown.Core.Models.Verify.VerifiedContext` provides a domain verification information about `SessionProposal`, `SessionRequest` and `AuthRequest`. + +It consists of origin of an app from where the request has been sent, validation Enum that says whether origin is `VALID`, `INVALID` or `UNKNOWN` and verify url server. + +```csharp +public class VerifiedContext +{ + [JsonProperty("origin")] + public string Origin; + + [JsonProperty("validation")] + private string _validation; + + public string ValidationString => _validation; + + public Validation Validation + { + get + { + return FromString(); + } + set + { + + _validation = AsString(value); + } + } + + [JsonProperty("verifyUrl")] + public string VerifyUrl { get; set; } + + private Validation FromString() + { + switch (ValidationString.ToLowerInvariant()) + { + case "VALID": + return Validation.Valid; + case "INVALID": + return Validation.Invalid; + default: + return Validation.Unknown; + } + } + + private string AsString(Validation str) + { + switch (str) + { + case Validation.Invalid: + return "INVALID"; + case Validation.Valid: + return "VALID"; + default: + return "UNKNOWN"; + } + } +} + +public enum Validation +{ + Unknown, + Valid, + Invalid, +} +``` diff --git a/network/wallets/chains/adi.mdx b/network/wallets/chains/adi.mdx new file mode 100644 index 0000000..806e467 --- /dev/null +++ b/network/wallets/chains/adi.mdx @@ -0,0 +1,31 @@ +--- +title: ADI Chain +description: "Overview of ADI Chain integration with Wallet SDK." +--- + +ADI Chain is a fully EVM-compatible blockchain. It uses the standard Ethereum JSON-RPC methods for all wallet interactions. + +## Network / Chain Information + +| CAIP-2 | Chain ID | Name | RPC Endpoint | Explorer | Namespace | +| -------------- | -------- | --------- | ------------------------------- | --------------------------------- | --------- | +| `eip155:36900` | `36900` | ADI Chain | `https://rpc.adifoundation.ai` | `https://explorer.adifoundation.ai` | `eip155` | + +## RPC Methods + +As an EVM-compatible chain, ADI Chain supports all standard Ethereum JSON-RPC methods. Wallets implementing ADI Chain support should refer to the [EVM RPC documentation](/network/wallets/chains/evm) for the complete list of supported methods, including: + +- `personal_sign` - Sign a message +- `eth_sign` - Sign data +- `eth_signTypedData` / `eth_signTypedData_v4` - Sign typed data (EIP-712) +- `eth_sendTransaction` - Send a transaction +- `eth_signTransaction` - Sign a transaction without broadcasting +- `eth_sendRawTransaction` - Broadcast a signed transaction + +For detailed method specifications and examples, see the [EVM Chain Support](/network/wallets/chains/evm) page. + +## Additional Resources + +- [ADI Explorer](https://explorer.adifoundation.ai) +- [ADI Bridge](https://bridge.adifoundation.ai) +- [ADI RPC Endpoint](https://rpc.adifoundation.ai) diff --git a/network/wallets/chains/bitcoin.mdx b/network/wallets/chains/bitcoin.mdx new file mode 100644 index 0000000..633e7c9 --- /dev/null +++ b/network/wallets/chains/bitcoin.mdx @@ -0,0 +1,311 @@ +--- +title: Bitcoin +description: "Bitcoin JSON-RPC methods supported by Wallet SDK." +--- + +We define an account as the group of addresses derived using the same account value in their [derivation paths](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#user-content-Path_levels). We use the first address of the [external chain](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#examples) ("first external address"), as the identifier for an account. An account's total balance is defined as the sum of all unspent transaction outputs (UTXOs) belonging to its entire group of addresses. + +1. Dapps **must** only display the first external address as a connected account. +2. Wallets **must** only offer to connect the first external address(es). + +#### Account Definition + +The derivation path levels in the [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#path-levels), [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#user-content-Public_key_derivation), [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki#public-key-derivation), [BIP86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#user-content-Public_key_derivation) standards are: + +``` +m / purpose' / coin_type' / account' / change / address_index +``` + +Addresses with different `purpose`, `change` and `address_index` values are considered to belong to the same account. Valid `purpose` values are 44, 49, 84 and 86. We use the first external Native SegWit (purpose = 84) address as the default account identifier. + +For a specific seed phrase and path `m/84'/0'/0'/0/0` we get account 0 with identifier `bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu`. Its total balance is the sum of all UTXO balances on all addresses with derivation paths: + +* `m/44'/0'/0'/change/address_index` +* `m/49'/0'/0'/change/address_index` +* `m/84'/0'/0'/change/address_index` +* `m/86'/0'/0'/change/address_index` + +If the wallet user changes to account 1 we get path `m/84'/0'/1'/0/0` with identifier `bc1qku0qh0mc00y8tk0n65x2tqw4trlspak0fnjmfz`. Its total balance is the sum of all UTXO balances on all addresses with derivation paths: + +* `m/44'/0'/1'/change/address_index` +* `m/49'/0'/1'/change/address_index` +* `m/84'/0'/1'/change/address_index` +* `m/86'/0'/1'/change/address_index` + +## sendTransfer + +This method is used to sign and submit a transfer of any `amount` of Bitcoin to a single `recipientAddress`, optionally including a `changeAddress` for the change amount and `memo` set as an OP_RETURN output by supporting wallets. The transaction will be signed and broadcast upon user approval. + +### Parameters + +* `Object` + * `account` : `String` - *(Required)* The connected account's first external address. + * `recipientAddress` : `String` - *(Required)* The recipient's public address. + * `amount` : `String` - *(Required)* The amount of Bitcoin to send, denominated in satoshis (Bitcoin base unit). + * `changeAddress` : `String` - *(Optional)* The sender's public address to receive change. + * `memo` : `String` - *(Optional)* The OP_RETURN value as a hex string without 0x prefix, maximum 80 bytes. + +### Returns + +* `Object` + * `txid` : `String` - *(Required)* The transaction id as a hex string without 0x prefix. + +### Example + +The example below specifies a simple transfer of 1.23 BTC (123000000 Satoshi). + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "sendTransfer", + "params": { + "account": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", + "recipientAddress": "bc1pmzfrwwndsqmk5yh69yjr5lfgfg4ev8c0tsc06e", + "amount": "123000000", + "memo": "636861726c6579206c6f766573206865" + } +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": { + "txid": "f007551f169722ce74104d6673bd46ce193c624b8550889526d1b93820d725f7" + } +} +``` + +## getAccountAddresses + +This method returns all current addresses needed for a dapp to fetch all UTXOs, calculate the total balance and prepare transactions. Dapps will typically use an indexing service to query for balances and UTXOs for all addresses returned by this method, such as: + +* [Blockbook API](https://github.com/trezor/blockbook/blob/master/docs/api.md#get-address) +* [Bitcore API](https://github.com/bitpay/bitcore/blob/master/packages/bitcore-node/docs/api-documentation.md#address) + +We recognize that there are two broad classes of wallets in use today: + +1. Wallets that generate a new change or receive address for every transaction ("dynamic wallet"). +2. Wallets that reuse the first external address for every transaction ("static wallet"). + +#### Implementation Details + +* All wallets **should** include the first external address and all addresses with one or more UTXOs, unless they're filtered by `intentions`. +* Dynamic wallets **should** include minimum 2 unused change and receive addresses. Otherwise dapps may have to request [getAccountAddresses](#getaccountaddresses) after every transaction to discover the new addresses and keep track of the user's total balance. +* All wallets **must** return fewer than 20 unused change and receive addresses to avoid breaking the [gap limit](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#address-gap-limit). + +### Parameters + +* `Object` + * `account` : `String` - *(Required)* The connected account's first external address. + * `intentions` : `String[]` - *(Optional)* Filter what addresses to return, e.g. "payment" or "ordinal". + +### Returns + +* `Array` + * `Object` + * `address` : `String` - *(Required)* Public address belonging to the account. + * `publicKey` : `String` - *(Optional)* Public key for the derivation path in hex, without 0x prefix. + * `path` : `String` - *(Optional)* Derivation path of the address e.g. "m/84'/0'/0'/0/0". + * `intention` : `String` - *(Optional)* Intention of the address, e.g. "payment" or "ordinal". + +### Session Properties + +In a connection request, it is recommended to serialize the response to `getAccountAddresses` in `session.sessionProperties.bip122_getAccountAddresses`. This allows dapps to consume an active session without requiring a context switch to re-request all addresses and associated public keys from the wallet. + +### Example: Dynamic Wallet + +The example below specifies a result from a dynamic wallet. For the sake of this example, receive and change addresses with index 3-4 are considered unused and addresses with paths `m/49'/0'/0'/0/7` and `m/84'/0'/0'/0/2` are considered to have UTXOs. + +Assuming the dapp monitors all returned addresses for balance changes, a new request to `getAccountAddresses` is only needed when all UTXOs in provided addresses have been spent, or when all provided `receive` addresses or `change` addresses have been used. + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "getAccountAddresses", + "params": { + "account": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu" + } +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": [ + { + "address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", + "publicKey": "0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c", + "path": "m/84'/0'/0'/0/0" + }, + { + "address": "3KHhcgwPgYF9hE77zaKy2G36dpkcNtvQ33", + "publicKey": "03b90230ca20150142bc2849a3df4517073978f32466214a0ebc00cac52f996989", + "path": "m/49'/0'/0'/0/7" + }, + { + "address": "bc1qp59yckz4ae5c4efgw2s5wfyvrz0ala7rgvuz8z", + "publicKey": "038ffea936b2df76bf31220ebd56a34b30c6b86f40d3bd92664e2f5f98488dddfa", + "path": "m/84'/0'/0'/0/2" + }, + { + "address": "bc1qgl5vlg0zdl7yvprgxj9fevsc6q6x5dmcyk3cn3", + "publicKey": "03de7490bcca92a2fb57d782c3fd60548ce3a842cad6f3a8d4e76d1f2ff7fcdb89", + "path": "m/84'/0'/0'/0/3" + }, + { + "address": "bc1qm97vqzgj934vnaq9s53ynkyf9dgr05rargr04n", + "publicKey": "03995137c8eb3b223c904259e9b571a8939a0ec99b0717684c3936407ca8538c1b", + "path": "m/84'/0'/0'/0/4" + }, + { + "address": "bc1qv6vaedpeke2lxr3q0wek8dd7nzhut9w0eqkz9z", + "publicKey": "03d0d243b6a3176fa20fa95cd7fb0e8e0829b83fc2b52053633d088c1a4ba91edf", + "path": "m/84'/0'/0'/1/3" + }, + { + "address": "bc1qetrkzfslk0d4kqjnu29fdh04tkav9vj3k36vuh", + "publicKey": "02a8dee7573bcc7d3c1e9b9e267dbf0cd717343c31d322c5b074a3a97090a0d952", + "path": "m/84'/0'/0'/1/4" + } + ] +} +``` + +### Example: Static Wallet + +The example below specifies a response from a static wallet. The returned address is used for both change and payments. It's the only address with UTXOs. + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "getAccountAddresses", + "params": { + "account": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu" + } +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": [ + { + "address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", + "publicKey": "0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c", + "path": "m/84'/0'/0'/0/0" + } + ] +} +``` + +## signPsbt + +This method can be used to request the signature of a Partially Signed Bitcoin Transaction (PSBT) and covers use-cases e.g. involving multiple-recipient transactions, requiring granular control over which UTXOs to spend or how to route change. + +### Parameters + +* `Object` + * `account` : `String` - *(Required)* The connected account's first external address. + * `psbt` : `String` - *(Required)* Base64 encoded string of the PSBT to sign. + * `signInputs` : `Array` + * `Object` + * `address` : `String` - *(Required)* The address whose private key to use for signing. + * `index` : `Integer` - *(Required)* Specifies which input to sign. + * `sighashTypes` : `Integer[]` - *(Optional)* Specifies which part(s) of the transaction the signature commits to. Default is `[1]`. + * `broadcast` : `Boolean` - *(Optional)* Whether to finalize and broadcast the transaction after signing it. Default is `false`. + +### Returns + +* `Object` + * `psbt` : `String` - *(Required)* The base64 encoded signed PSBT. + * `txid` : `String` - *(Optional)* The transaction ID as a hex-encoded string, without 0x prefix. This must be returned if the transaction was broadcasted. + +## signMessage + +This method is used to sign a message with one of the connected account's addresses. + +### Parameters + +* `Object` + * `account` : `String` - *(Required)* The connected account's first external address. + * `message` : `String` - *(Required)* The message to be signed by the wallet. + * `address` : `String` - *(Optional)* The address whose private key to use for signing the message. + * `protocol` : `"ecdsa" | "bip322"` - *(Optional)* Preferred signature type. Default is `"ecdsa"`. + +### Returns + +* `Object` + * `address` : `String` - *(Required)* The Bitcoin address used to sign the message. + * `signature` : `String` - *(Required)* Hex encoded bytes of the signature, without 0x prefix. + * `messageHash` : `String` - *(Optional)* Hex encoded bytes of the message hash, without 0x prefix. + +## Events + +### bip122_addressesChanged + +This event is used by wallets to notify dapps about connected accounts' current addresses, for example all addresses with a UTXO and a few unused addresses. The event data has the same format as the [getAccountAddresses](#getaccountaddresses) result. + +#### Implementation Details + +* Wallets **should** emit a `bip122_addressesChanged` event immediately after connection approval of a BIP122 chain. +* Wallets **should** emit a `bip122_addressesChanged` event whenever a UTXO is spent or created for a connected account's addresses. +* Dapps **should** listen for `bip122_addressesChanged` events, collect and monitor all addresses for UTXO and balance changes. + +Example [session_event](https://specs.walletconnect.com/2.0/specs/clients/sign/session-events#session_event) payload as received by a dapp: + +``` +{ + "id": 1675759795769537, + "topic": "95d6aca451b8e3c6d9d176761bf786f1cc0a6d38dffd31ed896306bb37f6ae8d", + "params": { + "event": { + "name": "bip122_addressesChanged", + "data": [ + { + "address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", + "publicKey": "0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c", + "path": "m/84'/0'/0'/0/0" + }, + { + "address": "3KHhcgwPgYF9hE77zaKy2G36dpkcNtvQ33", + "publicKey": "03b90230ca20150142bc2849a3df4517073978f32466214a0ebc00cac52f996989", + "path": "m/49'/0'/0'/0/7" + }, + { + "address": "bc1qp59yckz4ae5c4efgw2s5wfyvrz0ala7rgvuz8z", + "publicKey": "038ffea936b2df76bf31220ebd56a34b30c6b86f40d3bd92664e2f5f98488dddfa", + "path": "m/84'/0'/0'/0/2" + }, + { + "address": "bc1qgl5vlg0zdl7yvprgxj9fevsc6q6x5dmcyk3cn3", + "publicKey": "03de7490bcca92a2fb57d782c3fd60548ce3a842cad6f3a8d4e76d1f2ff7fcdb89", + "path": "m/84'/0'/0'/0/3" + }, + { + "address": "bc1qm97vqzgj934vnaq9s53ynkyf9dgr05rargr04n", + "publicKey": "03995137c8eb3b223c904259e9b571a8939a0ec99b0717684c3936407ca8538c1b", + "path": "m/84'/0'/0'/0/4" + }, + { + "address": "bc1qv6vaedpeke2lxr3q0wek8dd7nzhut9w0eqkz9z", + "publicKey": "03d0d243b6a3176fa20fa95cd7fb0e8e0829b83fc2b52053633d088c1a4ba91edf", + "path": "m/84'/0'/0'/1/3" + }, + { + "address": "bc1qetrkzfslk0d4kqjnu29fdh04tkav9vj3k36vuh", + "publicKey": "02a8dee7573bcc7d3c1e9b9e267dbf0cd717343c31d322c5b074a3a97090a0d952", + "path": "m/84'/0'/0'/1/4" + } + ] + }, + "chainId": "bip122:000000000019d6689c085ae165831e93" + } +} +``` diff --git a/network/wallets/chains/canton.mdx b/network/wallets/chains/canton.mdx new file mode 100644 index 0000000..67cf6dc --- /dev/null +++ b/network/wallets/chains/canton.mdx @@ -0,0 +1,581 @@ +--- +title: Canton +description: "Overview of the Canton JSON-RPC methods supported by Wallet SDK." +--- + +These are the methods that wallets should implement to handle Canton transactions and messages via WalletConnect. + +## Network / Chain Information + +- **Namespace:** `canton` +- **CAIP-2:** `canton:` (e.g. `canton:devnet`, `canton:production`) +- **CAIP-10 Account:** `canton::` (e.g. `canton:devnet:operator%3A%3A1220abc...`) + +Unlike most chains, Canton does not have fixed mainnet/testnet identifiers. Network IDs are **operator-defined** — each wallet is configured with one or more networks, and the `network-id` used in CAIP-2 identifiers comes from that configuration. + +dApps should **not** hardcode specific chain IDs in the session proposal. Instead, request the `canton` namespace without specifying `chains`, and work with whatever network the wallet provides in the approved session. The network ID and party ID are available directly from the session's `canton.accounts` array as CAIP-10 strings (e.g. `canton:production:operator%3A%3A1220abc...`). For full network details, use [`canton_getActiveNetwork`](#canton_getactivenetwork). + +## Registered Methods & Events + +```typescript theme={null} +const CANTON_WC_METHODS = [ + 'canton_prepareSignExecute', + 'canton_listAccounts', + 'canton_getPrimaryAccount', + 'canton_getActiveNetwork', + 'canton_status', + 'canton_ledgerApi', + 'canton_signMessage', +] + +const CANTON_WC_EVENTS = ['accountsChanged', 'statusChanged', 'chainChanged'] +``` + +### Auto-Approve vs Manual-Approve + +Read-only methods are auto-approved by the wallet. Methods that mutate the ledger or perform sensitive operations require explicit user approval. + +| Method | Approval | +| -------------------- | ------------ | +| `canton_listAccounts` | Auto-approve | +| `canton_getPrimaryAccount` | Auto-approve | +| `canton_getActiveNetwork` | Auto-approve | +| `canton_status` | Auto-approve | +| `canton_ledgerApi` | Auto-approve | +| `canton_prepareSignExecute` | Manual | +| `canton_signMessage` | Manual | + +## Method Name Mapping (dApp SDK) + +The dApp SDK's `WalletConnectTransport` maps SDK method names before sending over WC: + +| SDK method | WC method (on the wire) | +| ------------------------ | ------------------------ | +| `canton_prepareExecute` | `canton_prepareSignExecute` | +| `canton_prepareExecuteAndWait` | `canton_prepareSignExecute` | + +All other methods (`canton_listAccounts`, `canton_status`, `canton_ledgerApi`, etc.) are sent as-is. Both SDK methods resolve with the same response — over WalletConnect, every submission blocks until the transaction completes. + +## RPC Methods + +### canton_prepareSignExecute + +Prepare, sign, and execute a Canton ledger transaction. This is the primary method for submitting commands that mutate ledger state. The wallet performs the full prepare → sign → execute cycle and responds when the transaction is complete. + +#### Request + +```typescript theme={null} +interface CantonPrepareSignExecuteRequest { + method: 'canton_prepareSignExecute'; + params: CantonPrepareParams; +} + +interface CantonPrepareParams { + commandId?: string; // auto-generated (UUIDv4) if omitted + commands?: { [k: string]: unknown }; + actAs?: string[]; // defaults to [primaryWallet.partyId] if omitted + readAs?: string[]; // defaults to [] if omitted + disclosedContracts?: Array<{ + templateId?: string; + contractId?: string; + createdEventBlob: string; + synchronizerId?: string; + }>; + packageIdSelectionPreference?: string[]; +} +``` + +#### Example Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_prepareSignExecute", + "params": { + "commands": { + "0": { + "ExerciseCommand": { + "templateId": "#:Module:Template", + "contractId": "00abcdef...", + "choice": "Transfer", + "choiceArgument": { + "receiver": "bob::1220..." + } + } + } + }, + "commandId": "d290f1ee-6c54-4b01-90e6-d701748f0851", + "actAs": ["operator::1220abc..."], + "readAs": [], + "disclosedContracts": [ + { + "templateId": "#:Module:Template", + "contractId": "00abcdef...", + "createdEventBlob": "", + "synchronizerId": "wallet::1220e7b..." + } + ], + "packageIdSelectionPreference": [""] + } + } +} +``` + +#### Signing Providers + +Wallets support multiple signing backends. The signing provider determines the Ledger API flow used: + +| Provider | Flow | +| ---------------- | -------------------------------------------------------------------- | +| `participant` | Single call to `POST /v2/commands/submit-and-wait` (participant signs internally) | +| `wallet-kernel` | `POST /v2/interactive-submission/prepare` → local Ed25519 sign → `POST /v2/interactive-submission/execute` | +| `blockdaemon` | `POST /v2/interactive-submission/prepare` → sign via Blockdaemon API → `POST /v2/interactive-submission/execute` | + +#### Success Response + +```json theme={null} +{ + "id": 1234, + "jsonrpc": "2.0", + "result": { + "status": "executed", + "commandId": "d290f1ee-...", + "payload": { + "updateId": "tx-update-id", + "completionOffset": 42 + } + } +} +``` + +#### Error Response + +```json theme={null} +{ + "id": 1234, + "jsonrpc": "2.0", + "error": { + "code": 5001, + "message": "Transaction execution failed: INVALID_ARGUMENT: ..." + } +} +``` + +#### User Rejected Response + +```json theme={null} +{ + "id": 1234, + "jsonrpc": "2.0", + "error": { + "code": 5000, + "message": "User rejected" + } +} +``` + +--- + +### canton_listAccounts + +Retrieve all configured wallet accounts. + +#### Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_listAccounts", + "params": {} + } +} +``` + +#### Response + +```json theme={null} +{ + "id": 1235, + "jsonrpc": "2.0", + "result": [ + { + "primary": true, + "partyId": "operator::1220abc...", + "status": "allocated", + "hint": "operator", + "publicKey": "", + "namespace": "1220abc...", + "networkId": "canton:production", + "signingProviderId": "participant", + "disabled": false + } + ] +} +``` + +#### Wallet Type + +```typescript theme={null} +interface Wallet { + primary: boolean; + partyId: string; + status: 'initialized' | 'allocated' | 'removed'; + hint: string; + publicKey: string; + namespace: string; + networkId: string; + signingProviderId: string; + externalTxId?: string; + topologyTransactions?: string; + disabled?: boolean; + reason?: string; +} +``` + +--- + +### canton_getPrimaryAccount + +Retrieve the primary wallet account (where `primary === true`). + +#### Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_getPrimaryAccount", + "params": {} + } +} +``` + +#### Response + +```json theme={null} +{ + "id": 1236, + "jsonrpc": "2.0", + "result": { + "primary": true, + "partyId": "operator::1220abc...", + "status": "allocated", + "hint": "operator", + "publicKey": "", + "namespace": "1220abc...", + "networkId": "canton:production", + "signingProviderId": "participant" + } +} +``` + +--- + +### canton_getActiveNetwork + +Retrieve the currently active network configuration. + +#### Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_getActiveNetwork", + "params": {} + } +} +``` + +#### Response + +```json theme={null} +{ + "id": 1237, + "jsonrpc": "2.0", + "result": { + "networkId": "canton:production", + "ledgerApi": "http://127.0.0.1:5003" + } +} +``` + +--- + +### canton_status + +Check the wallet's connectivity to the Canton ledger. + +#### Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_status", + "params": {} + } +} +``` + +#### Response (ledger reachable) + +```json theme={null} +{ + "id": 1238, + "jsonrpc": "2.0", + "result": { + "provider": { + "id": "remote-da", + "version": "3.4.0", + "providerType": "remote" + }, + "connection": { + "isConnected": true, + "isNetworkConnected": true + }, + "network": { + "networkId": "canton:production", + "ledgerApi": "http://127.0.0.1:5003", + "accessToken": "" // optional but recommended + } + } +} +``` + +#### Response (ledger unreachable) + +```json theme={null} +{ + "id": 1238, + "jsonrpc": "2.0", + "result": { + "provider": { + "id": "remote-da", + "version": "3.4.0", + "providerType": "remote" + }, + "connection": { + "isConnected": true, + "isNetworkConnected": false, + "reason": "Ledger unreachable" + } + } +} +``` + +--- + +### canton_ledgerApi + +Proxy raw Canton Ledger API requests through the wallet. The wallet authenticates and forwards the request. + +#### Request + +```typescript theme={null} +interface CantonLedgerApiRequest { + method: 'canton_ledgerApi'; + params: CantonLedgerApiParams; +} + +interface CantonLedgerApiParams { + requestMethod: 'GET' | 'POST'; + resource: string; + body?: string | object; +} +``` + +#### Example Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_ledgerApi", + "params": { + "requestMethod": "POST", + "resource": "/v2/state/active-contracts", + "body": { + "filter": { + "filtersByParty": { + "operator::1220abc...": { + "cumulative": { + "templateFilters": [] + } + } + } + } + } + } + } +} +``` + +#### Response + +```json theme={null} +{ + "id": 1239, + "jsonrpc": "2.0", + "result": {} +} +``` + + +The `result` field contains the raw Ledger API JSON response as-is. + + +--- + +### canton_signMessage + +Sign an arbitrary message with the wallet's Ed25519 private key. + +#### Request + +```typescript theme={null} +interface CantonSignMessageRequest { + method: 'canton_signMessage'; + params: { + message: string; + }; +} +``` + +#### Example Request + +```json theme={null} +{ + "topic": "", + "chainId": "canton:devnet", + "request": { + "method": "canton_signMessage", + "params": { + "message": "Please sign this message to verify your identity" + } + } +} +``` + +#### Success Response + +```json theme={null} +{ + "id": 1240, + "jsonrpc": "2.0", + "result": { + "signature": "", + "publicKey": "" + } +} +``` + +## Events + +### accountsChanged + +Emitted when wallet accounts are added, removed, or modified. + +```json theme={null} +{ + "name": "accountsChanged", + "data": [ + { + "primary": true, + "partyId": "operator::1220abc...", + "status": "allocated", + "hint": "operator", + "publicKey": "...", + "namespace": "1220abc...", + "networkId": "canton:production", + "signingProviderId": "participant" + } + ] +} +``` + +### statusChanged + +Emitted when the wallet's connectivity status changes. + +```json theme={null} +{ + "name": "statusChanged", + "data": { + "provider": { "id": "remote-da", "providerType": "remote" }, + "connection": { "isConnected": true, "isNetworkConnected": true }, + "network": { "networkId": "canton:production" } + } +} +``` + +### chainChanged + +Emitted when the wallet switches to a different network. + +```json theme={null} +{ + "name": "chainChanged", + "data": { + "chainId": "canton:production" + } +} +``` + +## Session Lifecycle + +### Pairing + +The dApp creates a pairing URI and delivers it to the wallet: + +```typescript +const { uri, approval } = await signClient.connect({ + optionalNamespaces: { + canton: { + methods: CANTON_WC_METHODS, + events: CANTON_WC_EVENTS, + }, + }, +}) +``` + +### Session Approval + +The wallet builds approved namespaces including the CAIP-10 account with the URL-encoded partyId: + +```json theme={null} +{ + "canton": { + "chains": ["canton:devnet"], + "accounts": ["canton:devnet:operator%3A%3A1220abc..."], + "methods": ["canton_prepareSignExecute", "canton_listAccounts", "canton_getPrimaryAccount", "canton_getActiveNetwork", "canton_status", "canton_ledgerApi", "canton_signMessage"], + "events": ["accountsChanged", "statusChanged", "chainChanged"] + } +} +``` + +## Error Codes + +| Code | Meaning | +| ------ | ----------------------------------------- | +| `5000` | User rejected | +| `5001` | Execution / handler error | +| `5100` | Canton namespace not found in proposal | +| `6000` | Wallet disconnected | + +## Notes & Considerations + +- All requests and responses comply with JSON-RPC structure (`id`, `jsonrpc`, etc.). +- Canton uses Ed25519 signing for transaction authentication. +- The `ledgerApi` method acts as a transparent proxy — the wallet handles authentication with the Canton Ledger API. Only `GET` and `POST` are supported; other HTTP methods will return a `5001` error. +- Party IDs in CAIP-10 accounts are URL-encoded (e.g. `operator::1220abc...` becomes `operator%3A%3A1220abc...`). +- The `canton_prepareSignExecute` method always performs the full prepare → sign → execute cycle synchronously, responding only when the transaction is complete. +- The WC session `chainId` (e.g. `canton:devnet`) may differ from the `networkId` in wallet/network records (e.g. `canton:production`). The `chainId` identifies the chain at pairing time, while `networkId` reflects the wallet's internal network configuration. diff --git a/network/wallets/chains/evm.mdx b/network/wallets/chains/evm.mdx new file mode 100644 index 0000000..334864a --- /dev/null +++ b/network/wallets/chains/evm.mdx @@ -0,0 +1,338 @@ +--- +title: Ethereum +description: "Overview of the Ethereum JSON-RPC methods supported by Wallet SDK." +--- + +## personal_sign + +The sign method calculates an Ethereum specific signature with:`sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))`. + +By adding a prefix to the message makes the calculated signature recognizable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + +**Note** See ecRecover to verify the signature. + +### Parameters + +message, account + +1. `DATA`, N Bytes - message to sign. +2. `DATA`, 20 Bytes - address. + +### Returns + +`DATA`: Signature + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "personal_sign", + "params":["0xdeadbeaf","0x9b2055d370f73ec7d8a03e965129118dc8f5bf83"], +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" +} +``` + +## eth_sign + +The sign method calculates an Ethereum specific signature with: `sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))`. + +By adding a prefix to the message makes the calculated signature recognizable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + +**Note** the address to sign with must be unlocked. + +### Parameters + +account, message + +1. `DATA`, 20 Bytes - address. +2. `DATA`, N Bytes - message to sign. + +### Returns + +`DATA`: Signature + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "eth_sign", + "params": ["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "0xdeadbeaf"], +} + + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" +} +``` + +An example how to use solidity ecrecover to verify the signature calculated with `eth_sign` can be found [here](https://gist.github.com/bas-vk/d46d83da2b2b4721efb0907aecdb7ebd). The contract is deployed on the testnet Ropsten and Rinkeby. + +## eth_signTypedData + +Calculates an Ethereum-specific signature in the form of `keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))` + +By adding a prefix to the message makes the calculated signature recognizable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + +**Note** the address to sign with must be unlocked. + +### Parameters + +account, message + +1. `DATA`, 20 Bytes - address. +2. `DATA`, N Bytes - message to sign containing type information, a domain separator, and data + +### Example Parameters + +```javascript theme={null} +[ + "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + { + types: { + EIP712Domain: [ + { + name: "name", + type: "string", + }, + { + name: "version", + type: "string", + }, + { + name: "chainId", + type: "uint256", + }, + { + name: "verifyingContract", + type: "address", + }, + ], + Person: [ + { + name: "name", + type: "string", + }, + { + name: "wallet", + type: "address", + }, + ], + Mail: [ + { + name: "from", + type: "Person", + }, + { + name: "to", + type: "Person", + }, + { + name: "contents", + type: "string", + }, + ], + }, + primaryType: "Mail", + domain: { + name: "Ether Mail", + version: "1", + chainId: 1, + verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + }, + message: { + from: { + name: "Cow", + wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + }, + to: { + name: "Bob", + wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + }, + contents: "Hello, Bob!", + }, + }, +]; +``` + +### Returns + +`DATA`: Signature + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "eth_signTypedData", + "params": ["0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", {see above}], +} +' + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" +} +``` + +## eth_sendTransaction + +Creates new message call transaction or a contract creation, if the data field contains code. + +### Parameters + +1. `Object` - The transaction object +2. `from`: `DATA`, 20 Bytes - The address the transaction is send from. +3. `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to. +4. `data`: `DATA` - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Ethereum Contract ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) +5. `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas. +6. `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas +7. `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction +8. `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. + +### Example Parameters + +```javascript theme={null} +[ + { + from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + to: "0xBDE1EAE59cE082505bB73fedBa56252b1b9C60Ce", + data: "0x", + gasPrice: "0x029104e28c", + gas: "0x5208", + value: "0x00", + }, +]; +``` + +### Returns + +`DATA`, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available. + +Use `eth_getTransactionReceipt` to get the contract address, after the transaction was mined, when you created a contract. + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params":[{see above}], +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +## eth_signTransaction + +Signs a transaction that can be submitted to the network at a later time using with `eth_sendRawTransaction` + +### Parameters + +1. `Object` - The transaction object +2. `from`: `DATA`, 20 Bytes - The address the transaction is send from. +3. `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to. +4. `data`: `DATA` - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see [Ethereum Contract ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) +5. `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas. +6. `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas +7. `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction +8. `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce. + +### Example Parameters + +```javascript theme={null} +[ + { + from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", + gas: "0x76c0", // 30400 + gasPrice: "0x9184e72a000", // 10000000000000 + value: "0x9184e72a", // 2441406250 + nonce: "0x117", // 279 + }, +]; +``` + +### Returns + +`DATA` - the signed transaction data + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "eth_signTransaction", + "params":[{see above}], +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` + +## eth_sendRawTransaction + +Creates new message call transaction or a contract creation for signed transactions. + +### Parameters + +1. `DATA`, the signed transaction data. + +### Returns + +`DATA`, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available. + +Use `eth_getTransactionReceipt` to get the contract address, after the transaction was mined, when you created a contract. + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "eth_sendRawTransaction", + "params":[ + "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f07244567" + ], +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" +} +``` diff --git a/network/wallets/chains/overview.mdx b/network/wallets/chains/overview.mdx new file mode 100644 index 0000000..2173402 --- /dev/null +++ b/network/wallets/chains/overview.mdx @@ -0,0 +1,24 @@ +--- +title: Chain Support +sidebarTitle: Overview +--- + +The Wallet SDK is built to be **chain-agnostic** — it supports integrations across multiple blockchain ecosystems by working closely with each chain's foundations and developer communities to standardize namespaces, transaction flows, and JSON-RPC methods. + +## Ecosystem Reference Pages +- [EVM](/network/wallets/chains/evm) +- [Solana](/network/wallets/chains/solana) +- [Bitcoin](/network/wallets/chains/bitcoin) +- [SUI](/network/wallets/chains/sui) +- [Stacks](/network/wallets/chains/stacks) +- [TON](/network/wallets/chains/ton) +- [Tron](/network/wallets/chains/tron) +- [ADI Chain](/network/wallets/chains/adi) +- [Canton](/network/wallets/chains/canton) +- [Stellar](/network/wallets/chains/stellar) + +## Adding New Chain Support + +Interested in adding support for a new blockchain ecosystem? We work closely with chain foundations and developer communities to standardize integration specifications. + +**Contact us to start the process:** [sales@walletconnect.com](mailto:sales@walletconnect.com) diff --git a/network/wallets/chains/solana.mdx b/network/wallets/chains/solana.mdx new file mode 100644 index 0000000..94b37ad --- /dev/null +++ b/network/wallets/chains/solana.mdx @@ -0,0 +1,272 @@ +--- +title: Solana +description: "Overview of the Solana JSON-RPC methods supported by Wallet SDK." +--- + +## solana_getAccounts + +This method returns an Array of public keys available to sign from the wallet. + +### Parameters + +none + +### Returns + +`Array` - Array of accounts: + +* `Object` : + * `pubkey` : `String` - public key for keypair + +### Example + +```typescript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_getAccounts", + "params": {} +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": [{ "pubkey": "722RdWmHC5TGXBjTejzNjbc8xEiduVDLqZvoUGz6Xzbp" }] +} +``` + +## solana_requestAccounts + +This method returns an Array of public keys available to sign from the wallet. + +### Parameters + +none + +### Returns + +`Array` - Array of accounts: + +* `Object` : + * `pubkey` : `String` - public key for keypair + +### Example + +```typescript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_getAccounts", + "params": {} +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": [{ "pubkey": "722RdWmHC5TGXBjTejzNjbc8xEiduVDLqZvoUGz6Xzbp" }] +} +``` + +## solana_signMessage + +This method returns a signature for the provided message from the requested signer address. + +### Parameters + +`Object` - Signing parameters: + +* `message` : `String` - the message to be signed (base58 encoded) +* `pubkey` : `String` - public key of the signer + +### Returns + +`Object`: + +* `signature` : `String` - corresponding signature for signed message + +### Example + +```javascript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_signMessage", + "params": { + "message": "37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7", + "pubkey": "AqP3MyNwDP4L1GJKYhzmaAUdrjzpqJUZjahM7kHpgavm" + } +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": { signature: "2Lb1KQHWfbV3pWMqXZveFWqneSyhH95YsgCENRWnArSkLydjN1M42oB82zSd6BBdGkM9pE6sQLQf1gyBh8KWM2c4" } +} +``` + +## solana_signTransaction + +This method returns a signature over the provided instructions by the targeted public key. + + +Refer always to `transaction` param. The deprecated parameters are not compatible with versioned transactions. + + +### Parameters + +`Object` - Signing parameters:
+ +* `transaction` : `String` - base64-encoded serialized transaction
+* **\[deprecated]** `feePayer` : `String | undefined` - public key of the transaction fee payer
+* **\[deprecated]** `instructions` : `Array` of `Object` or `undefined` - instructions to be atomically executed:
+ - `Object` - instruction
+ - `programId` : `String` - public key of the on chain program
+ - `data` : `String | undefined` - encoded calldata for instruction
+ - `keys` : `Array` of `Object` - account metadata used to define instructions
+ - `Object` - key
+ - `isSigner` : `Boolean` - true if an instruction requires a transaction signature matching `pubkey`
+ - `isWritable` : `Boolean` - true if the `pubkey` can be loaded as a read-write account
+ - `pubkey` : `String` - public key of authorized program
+* **\[deprecated]** `recentBlockhash` : `String | undefined` - a recent blockhash
+* **\[deprecated]** `signatures` : `Array` of `Object` or `undefined` - (optional) previous partial signatures for this instruction set
+ - `Object` - partial signature
+ - `pubkey` : `String` - pubkey of the signer
+ - `signature` : `String` - signature matching `pubkey`
+ +### Returns + +`Object`: + +* `signature`: `String` - corresponding signature for signed instructions +* `transaction`?: `String | undefined` - optional: base64-encoded serialized transaction + +### Example + +```typescript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_signTransaction", + "params": { + "feePayer": "AqP3MyNwDP4L1GJKYhzmaAUdrjzpqJUZjahM7kHpgavm", + "instructions": [{ + "programId": "Vote111111111111111111111111111111111111111", + "data": "37u9WtQpcm6ULa3VtWDFAWoQc1hUvybPrA3dtx99tgHvvcE7pKRZjuGmn7VX2tC3JmYDYGG7", + "keys": [{ + "isSigner": true, + "isWritable": true, + "pubkey": "AqP3MyNwDP4L1GJKYhzmaAUdrjzpqJUZjahM7kHpgavm" + }] + }], + "recentBlockhash": "2bUz6wu3axM8cDDncLB5chWuZaoscSjnoMD2nVvC1swe", + "signatures": [{ + "pubkey": "AqP3MyNwDP4L1GJKYhzmaAUdrjzpqJUZjahM7kHpgavm", + "signature": "2Lb1KQHWfbV3pWMqXZveFWqneSyhH95YsgCENRWnArSkLydjN1M42oB82zSd6BBdGkM9pE6sQLQf1gyBh8KWM2c4" + }], + "transaction": "r32f2..FD33r" + } +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": { signature: "2Lb1KQHWfbV3pWMqXZveFWqneSyhH95YsgCENRWnArSkLydjN1M42oB82zSd6BBdGkM9pE6sQLQf1gyBh8KWM2c4" } +} +``` + +## solana_signAllTransactions + +This method is responsible for signing a list of transactions. The wallet must sign all transactions and return the signed transactions in the same order as received. Wallets must sign all transactions or return an error if it is not possible to sign any of them. + +### Parameters + +`Object` - Signing parameters: + +* `transactions` : `String[]` - base64-encoded serialized list of transactions
+ +### Returns + +`Object`: + +* `transactions` : `String[]` - base64-encoded serialized list of signed transactions in the same order as received
+ +### Example + +```typescript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_signAllTransactions", + "params": { + "transactions": string[] + } +} + +// Response +{ + "id": 1, + "jsonrpc": "2.0", + "result": { + "transactions": string[] + } +} +``` + +## solana_signAndSendTransaction + +This method is responsible for signing and sending a transaction to the Solana network. The wallet must sent the transaction and return the signature that can be used as a transaction id. + +### Parameters + +`Object` - transaction and options:
+ +* `transaction` : `String` - the whole transaction serialized and encoded with base64
+* `sendOptions` : `Object` - options for sending the transaction
+ * `skipPreflight` : `Boolean` - skip preflight checks
+ * `preflightCommitment` : `'processed' | 'confirmed' | 'finalized' | 'recent' | 'single' | 'singleGossip' | 'root' | 'max'` - preflight commitment level
+ * `maxRetries` : `Number` - maximum number of retries
+ * `minContextSlot` : `Number` - minimum context slot
+ +### Returns + +`Object`: + +* `signature` : `String`, - the signature of the transaction encoded with base58 used as transaction id
+ +### Example + +```typescript theme={null} +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "solana_signAndSendTransaction", + "params": { + "transaction": string, + "sendOptions": { + "skipPreflight"?: boolean, + "preflightCommitment"?: 'processed' | 'confirmed' | 'finalized' | 'recent' | 'single' | 'singleGossip' | 'root' | 'max', + "maxRetries"?: number, + "minContextSlot"?: number, + } + } +} + +// Response +{ + "id": 1, + "jsonrpc": "2.0", + "result": { + "signature": string + } +} +``` diff --git a/network/wallets/chains/stacks.mdx b/network/wallets/chains/stacks.mdx new file mode 100644 index 0000000..f91cf2b --- /dev/null +++ b/network/wallets/chains/stacks.mdx @@ -0,0 +1,263 @@ +--- +title: Stacks +description: "Overview of the Stacks JSON-RPC methods supported by Wallet SDK." +--- + +These are the methods that wallets should implement to handle Stacks transfers and messages via WalletConnect. + +## Core Methods (common) + +### stx_getAddresses + +Retrieve active account addresses; primarily Stacks-focused. + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_getAddresses", + "params": {} +} +``` + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "addresses": [ + { + "symbol": "STX", + "address": "SP…" + } + ] + } +} +``` + +**Notes:** +- Use this first to select the wallet's active address. +- Filter on `symbol: "STX"` or by address prefix (SP for mainnet, ST for testnet). + +## Stacks Methods + +### stx_transferStx + +Transfer STX. + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_transferStx", + "params": { + "sender": "SP3F7GQ48JY59521DZEE6KABHBF4Q33PEYJ823ZXQ", + "recipient": "SP3F7GQ48JY59521DZEE6KABHBF4Q33PEYJ823ZXQ", + "amount": "100000000000", + "memo": "", + "network": "mainnet" + } +} +``` + +#### Parameters + +| Parameter | Required? | Data Type | Description | +|-----------|------|-----------|-------------| +| `sender` | Required | `string` | The stacks address of sender (required for multi-account scenarios) | +| `recipient` | Required | `string` | Stacks address | +| `amount` | Required | `string` | micro-STX (uSTX) | +| `memo` | Optional | `string` | Memo string to be included with the transfer transaction | +| `network` | Optional | `string` | "mainnet" \| "testnet" \| "devnet" | + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "txid": "1234567890abcdef1234567890abcdef12345678", + "transaction": "0x…" + } +} +``` + +### stx_signTransaction + +Sign a Stacks transaction. Optional broadcast. + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_signTransaction", + "params": { + "transaction": "0x…", + "broadcast": false, + "network": "mainnet" + } +} +``` + +#### Parameters + +| Parameter | Required? | Data Type | Description | +|-----------|------|-----------|-------------| +| `transaction` | Required | `string` | hex transaction | +| `broadcast` | Optional | `boolean` | default false | +| `network` | Optional | `string` | "mainnet" \| "testnet" \| "devnet" | + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "signature": "0x…", + "transaction": "0x…", + "txid": "1234567890abcdef1234567890abcdef12345678" + } +} +``` + +**Note:** `txid` is present if broadcast=true + +### stx_signMessage + +Sign arbitrary message; supports structured (SIP-018). + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_signMessage", + "params": { + "address": "SP3F7GQ48JY59521DZEE6KABHBF4Q33PEYJ823ZXQ", + "message": "message", + "messageType": "utf8", + "network": "mainnet", + "domain": "example.com" + } +} +``` + +#### Parameters + +| Parameter | Required? | Data Type | Description | +|-----------|------|-----------|-------------| +| `address` | Required | `string` | The stacks address of sender | +| `message` | Required | `string` | Utf-8 string representing the message to be signed by the wallet | +| `messageType` | Optional | `string` | Type of message for signing: `utf8` for basic string or `structured` for structured data | +| `network` | Optional | `string` | Network for signing: `mainnet`, `testnet`, `signet`, `devnet` (note: redundant since chainId is provided) | +| `domain` | Optional | `string` | Domain tuple per SIP-018 (for structured messages only) | + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "signature": "0x…" + } +} +``` + +### stx_signStructuredMessage + +Domain-bound structured signing (SIP-018). + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_signStructuredMessage", + "params": { + "message": "message", + "domain": "domain" + } +} +``` + +#### Parameters + +| Parameter | Required? | Data Type | Description | +|-----------|------|-----------|-------------| +| `message` | Required | `string \| object` | message to be signed | +| `domain` | Required | `string \| object` | domain for structured signing | + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "signature": "0x…", + "publicKey": "0x04…" + } +} +``` + +**Note:** `publicKey` is optional + +### stx_callContract + +Wrapper method for `stx_signTransaction` that calls a Stacks contract. + +#### Request + +```json +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stx_callContract", + "params": { + "contract": "SP3F7GQ48JY59521DZEE6KABHBF4Q33PEYJ823ZXQ.my-contract", + "functionName": "get-balance", + "functionArgs": [] + } +} +``` + +#### Parameters + +| Parameter | Required? | Data Type | Description | +|-----------|------|-----------|-------------| +| `contract` | Required | `string` | Fully qualified contract identifier, including Stacks address and contract name | +| `functionName` | Required | `string` | Name of the function to call | +| `functionArgs` | Required | `string[]` | Arguments to pass to the contract function, encoded as strings | + +#### Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "txid": "stack_tx_id", + "transaction": "raw_tx_hex" + } +} +``` + +- `txid` - is used to identify the transaction on the explorer +- `transaction` - hex-encoded raw transaction + +## Session Properties + +In a connection request, it is recommended to serialize the response to `stx_getAddresses` in `session.sessionProperties.stacks_getAddresses`. This allows dapps to consume an active session without requiring a context switch to re-request all addresses and associated public keys from the wallet. diff --git a/network/wallets/chains/stellar.mdx b/network/wallets/chains/stellar.mdx new file mode 100644 index 0000000..4589dc5 --- /dev/null +++ b/network/wallets/chains/stellar.mdx @@ -0,0 +1,382 @@ +--- +title: Stellar +description: "Overview of the Stellar JSON-RPC methods supported by Wallet SDK." +--- + +These are the methods that wallets should implement to handle Stellar transactions and messages via WalletConnect. + + +The Stellar RPC standard is a proposal still under review and specifications may change. Implementation details and method signatures are subject to updates. + + +## Network / Chain Information + +| Item | Form | +| ------- | -------------------------------------------------------------------------------------------------------- | +| CAIP-2 | `stellar:pubnet` OR `stellar:testnet` | +| CAIP-10 | `stellar:pubnet:G…` — base32 StrKey account ID (56 chars, version byte `0x30`) | +| CAIP-19 | `stellar:pubnet/slip44:148` (XLM) or `stellar:pubnet/asset:{code}-{issuer}` (issued assets) | + +The CAIP-2 reference (`pubnet` / `testnet`) matches the [Stellar CAIP-2 namespace draft](https://github.com/ChainAgnostic/namespaces/blob/main/stellar/caip2.md). It is **not** the network passphrase — that is a separate signing-domain constant wallets bind into every signature, derived from the chain (see [Signing semantics](#signing-semantics)). + +### Account format + +Account IDs returned to the dApp are **CAIP-10 strings**, e.g.: + +```plain +stellar:pubnet:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN +``` + +Wallets MUST return the **G… StrKey** form (Ed25519 public key + CRC16 checksum, base32-encoded). Wallets MUST NOT return: + +- Muxed account (`M…`) IDs — these require a separate spec (CAP-27) and are not universally supported. +- Pre-auth (`T…`) or signer-hash (`X…`) StrKey forms — these are not accounts. +- Raw 32-byte public keys without StrKey encoding. + +### XDR encoding convention + +All transaction payloads cross the wire as **base64-encoded XDR strings**, matching SDF's reference SDKs and Horizon's `/transactions?tx=…` parameter. Specifically: + +- `stellar_signXDR` and `stellar_signAndSubmitXDR` accept and return a base64-encoded **`TransactionEnvelope`** XDR. +- The envelope's discriminant determines tx version: `ENVELOPE_TYPE_TX_V0`, `ENVELOPE_TYPE_TX`, or `ENVELOPE_TYPE_TX_FEE_BUMP`. +- Wallets MUST accept all three; wallets MAY emit signatures only on V1 and fee-bump envelopes (V0 is deprecated). + +## Session Proposal + +A standard WalletConnect session proposal for a Stellar-enabled dApp: + +```json +{ + "optionalNamespaces": { + "stellar": { + "chains": ["stellar:pubnet"], + "methods": [ + "stellar_signXDR", + "stellar_signAndSubmitXDR", + "stellar_signMessage", + "stellar_signAuthEntry" + ], + "events": ["accountsChanged", "chainChanged"] + } + } +} +``` + +| Property | Optional methods | +| ------------------ | --------------------------- | +| Sign transaction | `stellar_signXDR` | +| Sign a message | `stellar_signMessage` | +| Sign and Submit | `stellar_signAndSubmitXDR` | +| Soroban | `stellar_signAuthEntry` | + +## RPC Methods + +### stellar_signXDR + +Asks the wallet to attach a signature to a Stellar `TransactionEnvelope` and return the resulting envelope **without broadcasting it**. The dApp (or a relayer it trusts) is responsible for submission. + +This is the **primary method** for fee-abstracted flows: the dApp constructs an inner transaction whose `source_account` is the buyer; the wallet signs as the buyer; a separate fee-source wraps the result in a `FeeBumpTransactionEnvelope` and submits. + +#### Parameters + +`Object`: + +| Field | Type | Required | Description | +| --------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `xdr` | `string` (base64) | yes | The unsigned (or partially-signed) `TransactionEnvelope` XDR to sign. | +| `chain` | `string` (CAIP-2) | yes | Must equal the session's selected chain — `stellar:pubnet`. Wallet MUST reject signing if the encoded `network_id` inside the tx does not match this chain. | +| `account` | `string` (CAIP-10)| yes | The account that should sign. Wallet MUST reject if it doesn't custody this account. | + +This method **signs only**. To sign and broadcast in a single round-trip, use [`stellar_signAndSubmitXDR`](#stellar-signandsubmitxdr). + +#### Returns + +`Object`: + +| Field | Type | Description | +| --------------- | ------------------ | --------------------------------------------------------------------------------- | +| `signedXDR` | `string` (base64) | The signed `TransactionEnvelope` XDR. Existing signatures in the input are preserved. | +| `signerAddress` | `string` (CAIP-10) | The account that signed (echoes `account`). | + +#### Example + +```json +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "stellar_signXDR", + "params": { + "xdr": "AAAAAgAAAACz/ZNn8sJpz0r1A/8mO0wQVjEPFNG8mU3sk1Wk7TPxIQAAAGQAGYGzAAAACgAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAEsbESgFLrQc4j7yo2Up/EWNqQhgvBYGgYNCu9EuRRl+AAAAAVVTREMAAAAA...", + "chain": "stellar:pubnet", + "account": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} + +// Response +{ + "id": 1, + "jsonrpc": "2.0", + "result": { + "signedXDR": "AAAAAgAAAACz/ZNn8sJpz0r1A/8mO0wQVjEPFNG8mU3sk1Wk7TPxIQAAAGQAGYGzAAAACgAAAAAAAAAAAAAA...AAAAAEFNB7s=", + "signerAddress": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} +``` + +### stellar_signAndSubmitXDR + +Asks the wallet to sign and submit a transaction in one step. The wallet broadcasts via its configured RPC (Horizon or Stellar RPC) and returns the resulting transaction hash. + +Use this method when the dApp does **not** operate a relayer (i.e. the buyer is paying their own XLM fee directly). + +#### Parameters + +`Object`: + +| Field | Type | Required | Description | +| ------------------ | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `xdr` | `string` (base64) | yes | The unsigned `TransactionEnvelope` XDR. | +| `chain` | `string` (CAIP-2) | yes | Must equal the session's selected chain. | +| `account` | `string` (CAIP-10) | yes | Signing account. | +| `waitForInclusion` | `boolean` | no | If `true`, wallet waits up to ledger-close time before responding and returns `successful`. If `false` (default), wallet responds as soon as it receives the submission ack from its RPC. | + +#### Returns + +`Object`: + +| Field | Type | Description | +| ------------ | ------------------ | ------------------------------------------------------------------------------------------------ | +| `tx_hash` | `string` (hex, 64) | The hash of the submitted transaction. | +| `signedXDR` | `string` (base64) | The final signed `TransactionEnvelope` XDR (so the dApp can independently verify the hash). | +| `successful` | `boolean` | Optional. Present only when `waitForInclusion: true`. `true` if the tx landed and `successful=true` in its result envelope. | + +#### Example + +```json +// Request +{ + "id": 2, + "jsonrpc": "2.0", + "method": "stellar_signAndSubmitXDR", + "params": { + "xdr": "AAAAAgAAAACz/ZNn8sJpz0r1A/8mO0wQVjEPFNG8mU3sk1Wk7TPxIQAAAGQAGYGzAAAA...", + "chain": "stellar:pubnet", + "account": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ", + "waitForInclusion": true + } +} + +// Response +{ + "id": 2, + "jsonrpc": "2.0", + "result": { + "tx_hash": "3389e9f0f1a54f04a78fd09a7e0fc0d44f1eecbe8c33a3d56a39c8b46d2a8b48", + "signedXDR": "AAAAAgAAAACz/ZNn8sJpz0r1...AAAAAEFNB7s=", + "successful": true + } +} +``` + +### stellar_signMessage + +Asks the wallet to sign an arbitrary message under a Stellar account's Ed25519 key, **outside** the context of a Stellar transaction. This enables [SEP-10 web auth](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md)-style sign-in flows and dApp session attestation. + +To prevent a malicious dApp from getting a wallet to sign a payload that is also a valid transaction body, wallets MUST prepend a domain-separating prefix before signing: + +```plain +sign(Ed25519, sha256("Stellar Signed Message:\n" || message)) +``` + +The fixed UTF-8 prefix `"Stellar Signed Message:\n"` (with the trailing newline) is concatenated **directly** with the message bytes — no `0x00` separator and no length prefix — then SHA-256 hashed and Ed25519-signed. This matches the finalized [SEP-53](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0053.md) convention (the same domain-separation approach as Bitcoin/Ethereum signed messages) and ensures cross-context replay is impossible — a SEP-10 challenge transaction would never collide with a `stellar_signMessage` payload. + +#### Parameters + +`Object`: + +| Field | Type | Required | Description | +| ----------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------- | +| `message` | `string` (utf-8 OR base64) | yes | The payload to sign. If `messageEncoding: "base64"`, decoded as raw bytes; default `"utf-8"`. | +| `messageEncoding` | `"utf-8"` \| `"base64"` | no | Defaults to `"utf-8"`. | +| `chain` | `string` (CAIP-2) | yes | `stellar:pubnet` (signature is network-agnostic, but the session context is). | +| `account` | `string` (CAIP-10) | yes | Signing account. | + +#### Returns + +`Object`: + +| Field | Type | Description | +| --------------- | ------------------ | ---------------------------------------------- | +| `signature` | `string` (base64) | 64-byte Ed25519 signature, base64-encoded. | +| `signerAddress` | `string` (CAIP-10) | Signing account (echoes input). | + +#### Example + +```json +// Request +{ + "id": 3, + "jsonrpc": "2.0", + "method": "stellar_signMessage", + "params": { + "message": "pay-core://sign-in?nonce=8c4f1a2b&exp=1747746000", + "messageEncoding": "utf-8", + "chain": "stellar:pubnet", + "account": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} + +// Response +{ + "id": 3, + "jsonrpc": "2.0", + "result": { + "signature": "iJ7rH9N2T5q3Vh8U8a3l1eC9bD0fK6mPq9R5/4tZv1c9Ek2y0sJgPpVxT8aBhYf3LqW1uAYR7s2qNlDe6cZyAA==", + "signerAddress": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} +``` + + +**Anti-pattern:** Do NOT sign raw bytes without the domain prefix. Wallets that do so MUST be considered non-compliant — they expose users to transaction-impersonation attacks. + + +### stellar_signAuthEntry (Soroban) + +Signs a Soroban `SorobanAuthorizationEntry`, enabling Soroban contract authorizations to be co-signed by an address that is **not** the transaction's source account. This is the Stellar analogue to Ethereum's EIP-712 typed-data signing for permits / meta-transactions: a user authorizes a specific contract invocation tree, a separate party submits the transaction that consumes the authorization. + +The signing payload is the `HashIDPreimage::SOROBAN_AUTHORIZATION` preimage, computed as: + +```plain +sign(Ed25519, sha256(xdr(HashIDPreimageSorobanAuthorization { + network_id, + nonce, + signature_expiration_ledger, + invocation, +}))) +``` + +All four fields are pulled from the `SorobanCredentials::SOROBAN_CREDENTIALS_ADDRESS` block inside the auth entry. `network_id` is bound by the wallet from the session's CAIP-2 chain (NOT trusted from the request). + +#### Parameters + +`Object`: + +| Field | Type | Required | Description | +| ----------- | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authEntry` | `string` (base64) | yes | The unsigned `SorobanAuthorizationEntry` XDR. Its `credentials` MUST be of type `SOROBAN_CREDENTIALS_ADDRESS` with an empty `signature` SCVal. `SOROBAN_CREDENTIALS_SOURCE_ACCOUNT` entries are not signable via this method — they are authorized implicitly by signing the enclosing transaction. | +| `chain` | `string` (CAIP-2) | yes | Must equal the session's selected chain. | +| `account` | `string` (CAIP-10) | yes | The account that should sign. Wallet MUST verify it matches `credentials.address` inside the entry; reject with `4302` otherwise. | + +The wallet MUST also reject (`4304` — `AUTH_EXPIRED`) if `signature_expiration_ledger` is ≤ the current ledger sequence as known to the wallet, with a small safety margin to account for propagation. + +#### Returns + +`Object`: + +| Field | Type | Description | +| ----------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------- | +| `signedAuthEntry` | `string` (base64) | The updated `SorobanAuthorizationEntry` XDR with the `signature` SCVal populated. Other fields (nonce, expiration, invocation) MUST be byte-identical to the input. | +| `signerAddress` | `string` (CAIP-10) | Echoes `account`. | + +The `signature` SCVal follows Stellar's account-contract signer convention: an `SCMap` with keys `"public_key"` (32-byte Ed25519 pubkey as `SCBytes`) and `"signature"` (64-byte Ed25519 signature as `SCBytes`). Wallets MUST NOT emit a raw 64-byte signature without the map wrapper — Soroban host code rejects it. + +#### Example + +```json +// Request — dApp wants the user to authorize a transfer(from=user, to=merchant, amount=10_0000000) invocation +{ + "id": 4, + "jsonrpc": "2.0", + "method": "stellar_signAuthEntry", + "params": { + "authEntry": "AAAAAQAAAAAAAAAAs/2TZ/LCac9K9QP/JjtMEFYxDxTRvJlN7JNVpO0z8SEAAAAAAAAAAQAGgaUAAAAAAAAAAa1uVUtkbThwc1ZmTGdEYzVlbnVsbAAAAAAAAAAIdHJhbnNmZXIAAAADAAAAEgAAAAAAAAAAs/2TZ/LCac9K9QP/JjtMEFYxDxTRvJlN7JNVpO0z8SEAAAASAAAAAAAAAABLGxEoBS60HOI+8qNlKfxFjakIYLwWBoGDQrvRLkUZfgAAAAoAAAAAAAAAAAAAAAAF9eEAAAAAAAAAAAA=", + "chain": "stellar:pubnet", + "account": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} + +// Response — same entry, signature SCVal now populated with the account-contract signer map +{ + "id": 4, + "jsonrpc": "2.0", + "result": { + "signedAuthEntry": "AAAAAQAAAAAAAAAAs/2TZ/LCac9K9QP/JjtMEFYxDxTRvJlN7JNVpO0z8SEAAAAAAAAAAQAGgaUAAAAAAAAAAa1uVUtkbThwc1ZmTGdEYzVlbnVsbAAAAAAAAAAIdHJhbnNmZXIAAAADAAAAEgAAAAAAAAAAs/2TZ/LCac9K9QP/JjtMEFYxDxTRvJlN7JNVpO0z8SEAAAASAAAAAAAAAABLGxEoBS60HOI+8qNlKfxFjakIYLwWBoGDQrvRLkUZfgAAAAoAAAAAAAAAAAAAAAAF9eEAAAARAAAAAQAAAAIAAAAPAAAACnB1YmxpY19rZXkAAAAAAA0AAAAgs/2TZ/LCac9K9QP/JjtMEFYxDxTRvJlN7JNVpO0z8SEAAAAPAAAACXNpZ25hdHVyZQAAAAAAAA0AAABAi3hvR9N+a5q1Vh8U8a3l1eC9bD0fK6mPq9R5/4tZv1c9Ek2y0sJgPpVxT8aBhYf3LqW1uAYR7s2qNlDe6cZyAA==", + "signerAddress": "stellar:pubnet:GCZ73GTH6LBGTT2K6UB76JR3JQIKMMIPCTI3ZGKN5SJVLJ65GPYSCIBQ" + } +} +``` + +## Events + +| Event | Payload | Notes | +| ----------------- | ------------------------------------ | -------------------------------------------------------------------------------------------- | +| `accountsChanged` | `{ accounts: string[] }` (CAIP-10) | Emitted when the user changes the active account in their wallet, or revokes access for an account. | +| `chainChanged` | `{ chainId: string }` (CAIP-2) | Emitted when the wallet switches the active network (e.g. `stellar:pubnet` ↔ `stellar:testnet`). | + +## Signing semantics + +### Network passphrase binding + +Every Stellar transaction signature is computed over: + +```plain +sign(Ed25519, sha256(network_id || envelope_payload)) +``` + +where `network_id = sha256("Public Global Stellar Network ; September 2015")` for pubnet. This is **inside** the XDR envelope and is the protocol-level replay protection across networks. Wallets MUST: + +1. Decode the envelope's signing payload, **not** the wire bytes, before signing. +2. Compute `network_id` from the network the session belongs to (`stellar:pubnet` → pubnet passphrase). Wallets MUST NOT trust a `network_id` embedded in the request — only the CAIP-2 chain identifier. +3. Refuse to sign if the decoded envelope's internal network reference (when present, e.g. on fee-bump inner txs) does not match the session chain. + +### Fee-bump envelopes + +When the dApp passes a `FeeBumpTransactionEnvelope` to `stellar_signXDR`: + +- The wallet signs **only the inner tx**, not the outer fee-bump envelope. The outer envelope is signed by the `fee_source` account (typically a different party — the relayer). +- Wallets MUST validate that the inner tx's `source_account` is in fact the `account` parameter. +- Wallets MAY warn the user that fees are being paid by a different account (`fee_source`), and SHOULD display both the inner source and outer fee source in the signing UI. + +### Computing the tx hash and explorer discoverability + +The transaction hash is **deterministic from the signed envelope** — signatures are computed over the hash, they are not part of it. As soon as a dApp receives `signedXDR` from `stellar_signXDR`, it can derive the same hash the network will use. + +```plain +tx_hash = sha256( network_id ‖ ENVELOPE_TYPE ‖ tx_payload_xdr ) +``` + +| Component | Value | +| ---------------- | ---------------------------------------------------------------------------------------------------------------- | +| `network_id` | `sha256("Public Global Stellar Network ; September 2015")` — 32 bytes, fixed for pubnet | +| `ENVELOPE_TYPE` | XDR-encoded `EnvelopeType` enum (4 bytes, big-endian): `2` (`ENVELOPE_TYPE_TX`) for normal txs, `5` (`ENVELOPE_TYPE_TX_FEE_BUMP`) for fee-bump txs | +| `tx_payload_xdr` | XDR-encoded **`Transaction`** struct (the inner body — NOT the full envelope with its signatures) | + +Adding, removing, or reordering signatures does NOT change the hash. + +Reference computation: + +```typescript +import { TransactionBuilder, Networks } from "@stellar/stellar-sdk"; + +const { signedXDR } = await session.request({ + topic, + chainId: "stellar:pubnet", + request: { method: "stellar_signXDR", params: { xdr, chain, account } }, +}); + +const tx = TransactionBuilder.fromXDR(signedXDR, Networks.PUBLIC); +const txHash = tx.hash().toString("hex"); // 64-char hex +``` + +**Inner hash vs. fee-bump hash.** When `stellar_signXDR` is used inside a fee-abstraction flow (the wallet signs an inner tx, a relayer wraps it in a `FeeBumpTransaction` before submitting), the hash the dApp computes from the inner tx (`H_inner`) is **not** the hash that lands on-chain (`H_fb`). Horizon resolves **either hash** to the same transaction record — a `GET /transactions/{hash}` request works whether you pass `H_inner` or `H_fb`, and both are exposed on the returned fee-bump record. For stable UX, prefer `H_fb` for explorer links once submission is confirmed; `H_inner` works as an immediate optimistic identifier between sign-time and submission. Note that Horizon will **404** on an `H_inner` lookup until the wrapping fee-bump transaction has been submitted and included in a ledger. + +## Additional Resources + +- [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) and [CAIP-10](https://chainagnostic.org/CAIPs/caip-10) — chain and account identifiers. +- [Stellar CAIP-2 namespace draft](https://github.com/ChainAgnostic/namespaces/blob/main/stellar/caip2.md). +- [Stellar SEP-7](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0007.md), [SEP-10](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md), [SEP-53](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0053.md). +- [Freighter — WalletConnect (mobile)](https://docs.freighter.app/mobile-walletconnect/mobile). +- [Stellar XDR reference](https://developers.stellar.org/docs/encyclopedia/xdr). +- [Fee-bump transactions](https://developers.stellar.org/docs/learn/encyclopedia/transactions-specialized/fee-bump-transactions). diff --git a/network/wallets/chains/sui.mdx b/network/wallets/chains/sui.mdx new file mode 100644 index 0000000..0930de3 --- /dev/null +++ b/network/wallets/chains/sui.mdx @@ -0,0 +1,173 @@ +--- +title: Sui +description: "Overview of the Sui JSON-RPC methods supported by Wallet SDK." +--- + +These are the methods that wallets should implement to handle Sui transactions and messages via WalletConnect. + + +The SUI RPC standard is still under review and specifications may change. Implementation details and method signatures are subject to updates. + + +## sui_getAccounts + +This method returns an Array of public keys and addresses available to sign from the wallet. + +### Parameters + +none + +### Returns + +`Array` - Array of accounts: + +- `Object` : + - `pubkey` : `String` - public key for keypair + - `address` : `String` - the Sui address + +### Example + +```typescript +// Request +{ + "id": 1, + "jsonrpc": "2.0", + "method": "sui_getAccounts", + "params": {} +} + +// Result +{ + "id": 1, + "jsonrpc": "2.0", + "result": [{ "pubkey": "AC68P56WCCTF0nUEX31/V5b1wqiD1pvfc8Fql8dPIPDA", "address":"0x3cd077f41680eebca0176baad3915b2ea26dbbdfd10161865234732bb1f2ac50" }] +} +``` + +### Session Properties +In a connection request, it is recommended to serialize the response to `getAccounts` in `session.sessionProperties.sui_getAccounts`. This allows dapps to consume an active session without requiring a context switch to re-request all addresses and associated public keys from the wallet. + + + +## sui_signTransaction + +Sign a Sui transaction without executing it. + +#### Parameters + +1. `transaction` (object) - The transaction to sign: + - `transaction` (string) - The base64 encoded, BCS encoded, transaction data + - `address` (string) - The sender's Sui address + +#### Returns + +`object` - The signed transaction: +- `signature` (string) - The base64 encoded signature +- `transactionBytes` (string) - The base64 encoded signed transaction bytes + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "sui_signTransaction", + "params": { + "transaction": "AAACAAhkAAAAAAAAAAAgcfGPMPqXhXLvgkjSYSgtJoBBfJN4xPm3bwZGapDhVIICAgABAQAAAQEDAAAAAAEBAHHxjzD6l4Vy74JI0mEoLSaAQXyTeMT5t28GRmqQ4VSCAq3fqx8mNL6p13BcS9bG74Gbh1dowEtQ", + "address": "0xd5f647edb77d4fda31d0304506447fb3c92e55aaf77bc5ed4b77c332dd4605fa" + } +} + +// Response +{ + "jsonrpc": "2.0", + "result": { + "signature": "ACRvdr3yI2mdpeOK+NsJIimdNGcE9R//jjT3HALZ17fFyu818op4jZi/64lPBjpKMDX6ZtxnCFZExTOFdpi3MwEZXLv/ORduxMYX0fw8dbHlnWC8WG0ymrlAmARpEibbhw==", + "transactionBytes": "AAACAAhkAAAAAAAAAAAg1fZH7bd9T9ox0DBFBkR/s8kuVar3e8XtS3fDMt1GBfoCAgABAQAAAQEDAAAAAAEBANX2R+23fU/aMdAwRQZEf7PJLlWq93vF7Ut3wzLdRgX6At/pRJzj2VpZgqXpSvEtd3GzPvt99hR8e/yOCGz/8nbRmA7QFAAAAAAgBy5vStJizn76LmJTBlDiONdR/2rSuzzS4L+Tp/Zs4hZ8cBxYkcSlxBD6QXvgS11E6d+DNek8LiA/beba6iH3l5gO0BQAAAAAIMpdmZjiqJ5GG9di1MAgD4S3uRr2gaMC7S1WsaeBwNIx1fZH7bd9T9ox0DBFBkR/s8kuVar3e8XtS3fDMt1GBfroAwAAAAAAAECrPAAAAAAAAA==" + }, + "id": 1 +} +``` + +### sui_signAndExecuteTransaction + +Sign and execute a Sui transaction. + +#### Parameters + +1. `transaction` (object) - The transaction to sign and execute: + - `transaction` (string) - The base64 encoded, BCS encoded, transaction data + - `address` (string) - The sender's Sui address + +#### Returns + +`object` - The transaction result: +- `digest` (string) - The transaction digest that can be used to look up the transaction in the explorer + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "sui_signAndExecuteTransaction", + "params": { + "transaction": "AAACAAhkAAAAAAAAAAAgcfGPMPqXhXLvgkjSYSgtJoBBfJN4xPm3bwZGapDhVIICAgABAQAAAQEDAAAAAAEBAHHxjzD6l4Vy74JI0mEoLSaAQXyTeMT5t28GRmqQ4VSCAq3fqx8mNL6p13BcS9bG74Gbh1dowEtQ", + "address": "0xd5f647edb77d4fda31d0304506447fb3c92e55aaf77bc5ed4b77c332dd4605fa" + } +} + +// Response +{ + "jsonrpc": "2.0", + "result": { + "digest": "GBqPRFR9sYfWA8rt2wCkcgZrctyYMj8Ufunxkjg5G8zt" + }, + "id": 1 +} +``` + +### sui_signPersonalMessage + +Sign a personal message. + +#### Parameters + +1. `message` (object) - The message to sign: + - `message` (string) - The message to sign (plain text) + - `address` (string) - The account address to sign with + +#### Returns + +`object` - The signed message: +- `signature` (string) - The base64 encoded signature + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "id": 1, + "method": "sui_signPersonalMessage", + "params": { + "message": "This is a message to be signed for SUI", + "address": "0xd5f647edb77d4fda31d0304506447fb3c92e55aaf77bc5ed4b77c332dd4605fa" + } +} + +// Response +{ + "jsonrpc": "2.0", + "result": { + "signature": "APsZ7PvuAynXYxxfeo0Py4DWOnrUpwqHhJJ1F8aGB2nmS5Wv9dvVo8Gr7DKaXwPMqFaFNKsHb0Hej07R0L0NpQsZXLv/ORduxMYX0fw8dbHlnWC8WG0ymrlAmARpEibbhw==" + }, + "id": 1 +} +``` + +## Additional Resources + +For more information about Sui RPC methods and implementation details, please refer to the [official Sui documentation](https://docs.sui.io/sui-api-ref). diff --git a/network/wallets/chains/ton.mdx b/network/wallets/chains/ton.mdx new file mode 100644 index 0000000..a588eed --- /dev/null +++ b/network/wallets/chains/ton.mdx @@ -0,0 +1,208 @@ +--- +title: TON +description: "Overview of the TON JSON-RPC methods supported by Wallet SDK." +--- + +## Network / Chain Information + +| CAIP-2 | Chain ID | Name | RPC Endpoint | Namespace | +| ---------- | -------- | ----------- | ---------------------------------------------- | --------- | +| `ton:-239` | `-239` | TON Mainnet | `https://toncenter.com/api/v2/jsonRPC` | `ton` | +| `ton:-3` | `-3` | TON Testnet | `https://testnet.toncenter.com/api/v2/jsonRPC` | `ton` | + +## RPC Methods + +Wallets must support the following JSON-RPC methods over WalletConnect sessions. No events are required. + +## ton_sendMessage + +Submit one or more transaction messages to the TON network. + +### Request + +```typescript theme={null} +interface TonSendMessageRequest { + method: 'ton_sendMessage'; + params: TonSendTransactionParams[]; +} + +interface TonSendTransactionParams { + valid_until?: number; // optional UNIX timestamp + from?: string; // optional sender address (TEP-123 format) + messages: TonTransactionMessage[]; +} + +interface TonTransactionMessage { + address: string; // recipient in TEP-123 format + amount: number | string; // value in nanotons + payload?: string; // optional base64 BoC + stateInit?: string; // optional base64 BoC +} +``` + +### Example Request + +```json theme={null} +{ + "id": 123, + "jsonrpc": "2.0", + "params": { + "chainId": "ton:-239", + "request": { + "method": "ton_sendMessage", + "params": [ + { + "valid_until": 1658253458, + "from": "EQDmnxDMhId6v1Ofg_h5KR5coWlFG6e86Ro3pc7Tq4CA0-Jn", + "messages": [ + { + "address": "EQBBJBB3HagsujBqVfqeDUPJ0kXjgTPLWPFFffuNXNiJL0aA", + "amount": "20000000", + "stateInit": "base64boc..." + }, + { + "address": "EQDmnxDMhId6v1Ofg_h5KR5coWlFG6e86Ro3pc7Tq4CA0-Jn", + "amount": "60000000", + "payload": "base64boc..." + } + ] + } + ] + } + } +} +``` + +### Success Response + +```json theme={null} +{ + "jsonrpc": "2.0", + "id": 123, + "result": "base64bocEncodedTransaction" +} +``` + +### Error Response + +```json theme={null} +{ + "jsonrpc": "2.0", + "id": 123, + "error": { + "code": , + "message": "" + } +} +``` + +## ton_signData + +Sign an off-chain payload (text, binary, or cell) for authentication or verification by dApps. + +### Request + +```typescript theme={null} +interface TonSignDataRequest { + method: 'ton_signData'; + params: TonSignDataParams[]; +} + +type TonSignDataParams = + | { type: 'text'; text: string; from?: string } + | { type: 'binary'; bytes: string; from?: string } + | { type: 'cell'; schema: string; cell: string; from?: string }; +``` + +### Example Request + +```json theme={null} +{ + "id": 123, + "jsonrpc": "2.0", + "params": { + "chainId": "ton:-239", + "request": { + "method": "ton_signData", + "params": [ + { + "type": "text", + "text": "Confirm new 2FA number:\\n+1 234 567 8901", + "from": "EQDmnxDMhId6v1Ofg_h5KR5coWlFG6e86Ro3pc7Tq4CA0-Jn" + } + ] + } + } +} +``` + +### Success Response + +```json theme={null} +{ + "jsonrpc": "2.0", + "id": 123, + "result": { + "signature": "base64_signature", + "address": "raw_wallet_address", + "timestamp": 1658253458, + "domain": "yourapp.com", + "payload": { + "type": "text", + "text": "Confirm new 2FA number:\\n+1 234 567 8901" + } + } +} +``` + +### Error Response + +```json theme={null} +{ + "jsonrpc": "2.0", + "id": 123, + "error": { + "code": , + "message": "" + } +} +``` + +## Session Properties + + +Wallets must include `ton_getPublicKey` and `ton_getStateInit` in the session properties when approving a session. This is mandatory for TON Connect compatibility. + + +When approving a session, wallets must serialize the following properties into `session.sessionProperties`: + +- `ton_getPublicKey`: The Ed25519 public key of the wallet (hex-encoded) +- `ton_getStateInit`: The StateInit of the wallet contract (base64-encoded BoC) + +These properties are essential for TON Connect support because: +- The public key is required for signature verification +- The StateInit is needed to compute and verify the wallet address, as TON addresses are derived from the contract code and initial data + +### Example Session Approval + +```typescript +// When approving a session, include the TON session properties +const session = await walletKit.approveSession({ + id: proposal.id, + namespaces: approvedNamespaces, + sessionProperties: { + ton_getPublicKey: "a1b2c3d4e5f6...", // hex-encoded Ed25519 public key + ton_getStateInit: "te6cckEBAQEA..." // base64-encoded StateInit BoC + } +}); +``` + +This allows dApps to consume an active session without requiring additional requests to retrieve the wallet's public key and state initialization data. + +## Notes & Considerations + +* If `from` is omitted, the wallet should prompt the user to select an address. +* All requests and responses must comply with JSON-RPC structure (`id`, `jsonrpc`, etc.). +* Signature verification can be done using `ed25519.verify` on the original bytes. +* `stateInit` support is needed when your wallet supports contract deployment flows. +* The `domain` field in responses indicates the originating application (dApp) domain. diff --git a/network/wallets/chains/tron.mdx b/network/wallets/chains/tron.mdx new file mode 100644 index 0000000..03f119a --- /dev/null +++ b/network/wallets/chains/tron.mdx @@ -0,0 +1,263 @@ +--- +title: Tron +description: "Tron JSON-RPC Methods" +--- + +These are the methods that wallets should implement to handle Tron transactions and messages via WalletConnect. + +## Network / Chain Information + +| CAIP-2 | Chain ID | Name | RPC Endpoint | Namespace | +| ----------------- | ---------------- | ------------- | --------------------------- | --------- | +| `tron:0x2b6653dc` | `0x2b6653dc` | Tron Mainnet | `https://api.trongrid.io` | `tron` | +| `tron:0xcd8690dc` | `0xcd8690dc` | Tron Shasta | `https://api.shasta.trongrid.io` | `tron` | +| `tron:0x94a9059e` | `0x94a9059e` | Tron Nile | `https://nile.trongrid.io` | `tron` | + +## Session Properties + +To enable the new simplified transaction structure, wallets should include `tron_method_version: "v1"` in their `sessionProperties` during the connection handshake: + +```json +{ + "sessionProperties": { + "tron_method_version": "v1" + } +} +``` + +When `tron_method_version` is set to `"v1"`, the transaction structure is simplified to remove the nested `transaction.transaction` format. If not set, the legacy nested format is used for backward compatibility. + +### tron_signTransaction + +Sign a Tron transaction without executing it. + +#### Parameters + +- The transaction to sign: + - `address` (string) - The sender's Tron address + - `transaction` (object) - The transaction object to sign + +#### Returns + +- The signed transaction: + - `txID` (string) - The transaction ID (deterministically derived from raw transaction) + - `signature` (array) - Array of signature strings + - `raw_data` (object) - The raw transaction data + - `raw_data_hex` (string) - The hex-encoded raw transaction data + - `visible` (boolean) - Whether addresses are in visible format + +#### Example (New Format with tron_method_version: "v1") + +Request with the simplified format: + +```json +{ + "request": { + "method": "tron_signTransaction", + "params": { + "address": "TKZRPqoV7WLFvjhT4cEyBLv27Rvv1RNWGj", + "transaction": { + "visible": false, + "txID": "539f218871fdd87e94eb03a0dd617107ba722005f37a5ddb82cb65aa4f3b73b0", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "data": "095ea7b300000000000000000000000069319ea845b1c35a1f7b0e1429f4f303e8f791330000000000000000000000000000000000000000000000000000000000000000", + "owner_address": "4169319ea845b1c35a1f7b0e1429f4f303e8f79133", + "contract_address": "41eca9bc828a3005b9a3b909f2cc5c2a54794de05f" + }, + "type_url": "type.googleapis.com/protocol.TriggerSmartContract" + }, + "type": "TriggerSmartContract" + } + ], + "ref_block_bytes": "7803", + "ref_block_hash": "16138f9255a1db91", + "expiration": 1756201572000, + "fee_limit": 200000000, + "timestamp": 1756201512720 + }, + "raw_data_hex": "0a027803220816138f9255a1db9140a0ad95ae8e335aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a154169319ea845b1c35a1f7b0e1429f4f303e8f79133121541eca9bc828a3005b9a3b909f2cc5c2a54794de05f2244095ea7b300000000000000000000000069319ea845b1c35a1f7b0e1429f4f303e8f79133000000000000000000000000000000000000000000000000000000000000000007090de91ae8e3390018084af5f" + } + }, + "expiryTimestamp": 1756201811 + }, + "chainId": "tron:0xcd8690dc" +} +``` + +- Response: + +```json +{ + "visible": false, + "txID": "539f218871fdd87e94eb03a0dd617107ba722005f37a5ddb82cb65aa4f3b73b0", + "raw_data": { + "contract": [ + { + "parameter": { + "value": { + "data": "095ea7b300000000000000000000000069319ea845b1c35a1f7b0e1429f4f303e8f791330000000000000000000000000000000000000000000000000000000000000000", + "owner_address": "4169319ea845b1c35a1f7b0e1429f4f303e8f79133", + "contract_address": "41eca9bc828a3005b9a3b909f2cc5c2a54794de05f" + }, + "type_url": "type.googleapis.com/protocol.TriggerSmartContract" + }, + "type": "TriggerSmartContract" + } + ], + "ref_block_bytes": "7803", + "ref_block_hash": "16138f9255a1db91", + "expiration": 1756201572000, + "fee_limit": 200000000, + "timestamp": 1756201512720 + }, + "raw_data_hex": "0a027803220816138f9255a1db9140a0ad95ae8e335aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a154169319ea845b1c35a1f7b0e1429f4f303e8f79133121541eca9bc828a3005b9a3b909f2cc5c2a54794de05f2244095ea7b300000000000000000000000069319ea845b1c35a1f7b0e1429f4f303e8f79133000000000000000000000000000000000000000000000000000000000000000007090de91ae8e3390018084af5f", + "signature": [ + "1c2dd921c15fd83ca1dec4fd999b801f08c8bb073702f4bfafa4132a6e129421ed6267ec81c7dd2e4ef04ce077b101186ec2cda86d69f9f44255c216398cc9c601" + ] +} +``` + +### tron_signMessage + +Sign a personal message. + +#### Parameters + +The message to sign: + +- `message` (string) - The message to sign (plain text) +- `address` (string) - The account address to sign with + +#### Returns + +The signed message: + +- `signature` (string) - The signature string + +#### Example + +- Request: + +```json +{ + "request": { + "method": "tron_signMessage", + "params": { + "address": "TXUEmLr...", + "message": "This is a message to be signed for Tron" + }, + "expiryTimestamp": 1758269816 + }, + "chainId": "tron:0xcd8690dc" +} +``` + +- dApp result (what client.request(...) resolves to): + +```json +{ "signature": "0x1ec623ee6e4716f5a116d0a2755b158ac05dfbc3e9118cca..." } +``` + + +The methods below are not part of the required wallet surface in the Reown official Tron Wallet example. +dApps may perform these directly against a Tron node or gateway. Wallets may implement them for convenience, but they're not required. + + +### tron_sendTransaction (optional) + +Broadcast a signed transaction to the Tron network. + +#### Parameters + +The signed transaction object: + +- `txID` (string) - The transaction ID +- `signature` (array) - Array of signature strings +- `raw_data` (object) - The raw transaction data +- `raw_data_hex` (string) - The hex-encoded raw transaction data + +#### Returns + +The transaction result: + +- `result` (boolean) - Whether the transaction was successfully broadcast +- `txid` (string) - The transaction ID that can be used to look up the transaction + +#### Example + +- Request: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tron_sendTransaction", + "params": { + "signedTransaction": { + "txID": "66e79c6993f29b02725da54ab146ffb0453ee6a43b4083568ad9585da305374a", + "signature": [ + "7e760cef94bc82a7533bc1e8d4ab88508c6e13224cd50cc8da62d3f4d4e19b99514f..." + ], + "raw_data_hex": "0a02885b2208baa1c278fd0a309f4090c1dbe5e7325aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a15411cb0b7348eded93b8d0816bbeb819fc1d7a51f31121541a614f803b6fd780986a42c78ec9c7f77e6ded13c2244095ea7b30000000000000000000000001cb0b7348eded93b8d0816bbeb819fc1d7a51f3100000000000000000000000000000000000000000000000000000000000000007082f4d7e5e73290018084af5f" + } + } +} +``` + +- Response: + +```json +{ + "jsonrpc": "2.0", + "result": { + "result": true, + "txid": "66e79c6993f29b02725da54ab146ffb0453ee6a43b4083568ad9585da305374a" + }, + "id": 1 +} +``` + +### tron_getBalance (optional) + +Get the TRX balance of a Tron address. + +#### Parameters + +1. `address` (string) - The Tron address to query + +#### Returns + +`number` - The balance in SUN (1 TRX = 1,000,000 SUN) + +#### Example + +- Request: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tron_getBalance", + "params": { + "address": "TLyqzVGLV1srkB7dToTAEqgDSfPtXRJZYH" + } +} +``` + +- Response: + +```json +{ + "jsonrpc": "2.0", + "result": 1000000000, + "id": 1 +} +``` + +## Additional Resources + +For more information about Tron RPC methods and implementation details, please refer to the [official Tron documentation](https://developers.tron.network/). diff --git a/network/wallets/custodians/app-access-control.mdx b/network/wallets/custodians/app-access-control.mdx new file mode 100644 index 0000000..c45f9b1 --- /dev/null +++ b/network/wallets/custodians/app-access-control.mdx @@ -0,0 +1,46 @@ +--- +title: How to Control Which Apps Can Connect to Your Users’ Wallets +sidebarTitle: Managing Dapp Access +--- + +As a wallet provider or a custodian, you may want to restrict access to certain dapps to maintain control over which applications can connect to your users’ wallets. This can be useful for a variety of reasons, such as to prevent users from using certain apps that are not compliant with your policies or to simply block certain apps from connecting to your users' wallets. + +Using the Wallet SDK, you can block apps from connecting to your users' wallets by rejecting session requests from certain apps. + +## Prerequisites + +- Please ensure you have integrated Wallet SDK into your wallet. +- Please ensure that you have obtained and configured the project ID from the [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +## Maintaining a Blocklist of Apps + +Wallet SDK allows you to identify malicious apps using [Verify API](/network/wallets/features/verify). However, as a wallet, you will need to build your own logic for the UI and UX of blocking certain apps. + +If there are specific apps that you want to block (not flagged as malicious by Verify API), you will need to maintain a blocklist of apps by storing the app's metadata in a database or a file. + +## Inspecting Session Requests + +When receiving `onSessionProposal` events, check the dapp's metadata (name, URL, description) from `proposal.proposer.metadata`. + +After this, you can reject unwanted connections by calling `rejectSession()` for apps you want to block. For example: + +```javascript +walletKit.on('session_proposal', (event) => { + const dappUrl = event.params.proposer.metadata.url; + + // Your blocklist logic + if (isBlocked(dappUrl)) { + walletKit.rejectSession({ + id: event.id, + reason: getSdkError('USER_REJECTED') + }); + return; + } + + // Otherwise show approval UI +}); +``` + +## Conclusion + +By following the steps above, you can block apps from connecting to your users' wallets by rejecting session requests from certain apps. diff --git a/network/wallets/custodians/app-extended-sessions.mdx b/network/wallets/custodians/app-extended-sessions.mdx new file mode 100644 index 0000000..eeeb9c5 --- /dev/null +++ b/network/wallets/custodians/app-extended-sessions.mdx @@ -0,0 +1,77 @@ +--- +title: Extended WalletConnect Sessions Request for Apps +--- + +This guide will walk you through how an app developer can customize the session request expiry in WalletConnect using the **`expiry`** parameter. + +## Extended Session Expiry - what does it mean? + +When an app sends a request through WalletConnect (for example, a signature request), it stays “active” until the expiry time is reached. If the wallet does not respond before the expiry, the request automatically fails with a timeout. + +By default, the expiry is short, i.e., 5 minutes. Extending the session expiry time allows the wallet and app to keep the request open longer, **up to 7 days**. This is useful for cases like off-hours approvals, delayed custody flows, or multi-party signing. + +### What do apps need to do? + +An app must: + +- Keep track of outstanding requests and handle delayed responses. +- Have a UI that tolerates waiting for a response as long as the expiry is configured. + +Extended durations may not be suitable for **time-bounded actions** (e.g., swaps with quotes, flash opportunities) where blockchain state changes invalidate the request. + +Hence an app must align **WalletConnect expiry** with any **contract-level expiry** to avoid mismatched timing. + +### Limits + +- **Minimum:** 300 seconds (5 min) +- **Maximum:** 604,800 seconds (7 days) + +## How can I extend the session request expiry as an app? + +Developers can define how long a WalletConnect session request remains active by using the **`expiry`** parameter in the session request payload. + +### Parameter + +`expiry`: Optional field to set session expiry time. Must be in seconds. + +### Implementation + +Below are the examples of how to implement the `expiry` parameter in the session request payload for different providers. + + + ```javascript Sign Client + const result = await signClient.request({ + topic: 'xyz', + request: { + method: 'personal_sign', + params: [ + '0xdeadbeef', + '0x000000000000000000000000000000000000dead' + ] + }, + chainId: 'eip155:1', + expiry: 600 // <-- add this for 10 minutes expiry in seconds + }); + ``` + ```javascript Universal Provider + const result = await universalProvider.request( + { + method: "personal_sign", + params: ["0xdeadbeef", "0x000000000000000000000000000000000000dead"], + }, + "eip155:1", + 600, // <-- add this for 10 minutes expiry in seconds + ); + ``` + ```javascript Ethereum Provider + await ethereumProvider.request( + { + method: "personal_sign", + params: ["0xdeadbeef", "0x000000000000000000000000000000000000dead"], + }, + 600, // <-- add this for 10 minutes expiry in seconds + ); + ``` + + +**Apps should store pending request IDs in local storage to handle delayed responses, app reload or crash scenarios.** \ No newline at end of file diff --git a/network/wallets/custodians/contract-access-control.mdx b/network/wallets/custodians/contract-access-control.mdx new file mode 100644 index 0000000..fe0fcc4 --- /dev/null +++ b/network/wallets/custodians/contract-access-control.mdx @@ -0,0 +1,130 @@ +--- +title: How to Control Which Smart Contracts Your Users Can Interact With +sidebarTitle: Managing Smart Contract Access +--- + +As a wallet provider or custodian, you may want to limit which smart contracts your users can interact with to maintain tighter control over onchain activity. This can be useful for enforcing compliance requirements, reducing exposure to malicious or unverified contracts, or simply restricting access to certain protocols that don’t align with your policies. + +Using the Wallet SDK, you can inspect and filter contract interaction requests to block or approve transactions based on your own criteria, such as contract addresses, function signatures, or network-specific rules. + +## Prerequisites + +- Please ensure you have integrated Wallet SDK into your wallet. +- Please ensure that you have obtained and configured the project ID from the [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +## Managing Smart Contract Access + +Wallet SDK does not provide a built-in way to create and manage smart contract allowlists for access control. However, you can use the Wallet SDK to inspect the `session_proposal` and `session_request` payloads and review it to approve or reject the proposal before a session is established and/or a transaction is signed respectively. + +### Inspecting Session Proposals + +When a Web3 app is trying to establish a session or connect to your wallet, it will send a `session_proposal` payload to your wallet as shown below. + +After this, as a wallet, you can do the following: + +1. Check `verifyContext.origin` and `validation` to confirm the dapp is trusted. +2. Approve or reject the proposal before the session is created. + +```json +{ + "id": 1685471520923476, + "topic": "proposal_topic", + "params": { + "requiredNamespaces": { + "eip155": { + "chains": ["eip155:1"], + "methods": ["eth_sendTransaction", "personal_sign"], + "events": ["chainChanged", "accountsChanged"] + } + }, + "proposer": { + "metadata": { + "name": "Aave", + "description": "Aave App", + "url": "https://app.aave.com", + "icons": ["https://aave.com/icon.png"] + } + }, + "verifyContext": { + "origin": "https://app.aave.com", + "validation": "VALID", + "verifyUrl": "https://verify.walletconnect.com/record/abc123" + } + } +} +``` + +### Inspecting Session Requests + +After a session is approved, Web3 apps may request to sign a transaction or a message. As a wallet, you will receive a JSON-RPC request from the Web3 app as shown below. + +Inside the request payload, you will find the contract address (`to: 0xContractAddress`) that is being interacted with and the function that is being called. + +```json +{ + "id": 1685471630000123, + "topic": "session_topic", + "params": { + "chainId": "eip155:1", + "request": { + "method": "eth_sendTransaction", + "params": [ + { + "from": "0xCustodianSubAccount", + "to": "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", + "data": "0xa9059cbb0000000000000000000000000F1b5...", + "value": "0x0" + } + ] + }, + "verifyContext": { + "origin": "https://app.aave.com", + "validation": "VALID" + } + } +} +``` + +### Enforcing Smart Contract Allowlists + +As a wallet or custodian, you would need to code your own logic to enforce the smart contract allowlists. Please refer to the example implementation below that works for all EVM chains. + +```javascript +const ALLOWED_CONTRACTS = { + "eip155:1": [ + "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", // Lido + "0x7Be8076f4EA4A4AD08075C2508e481d6C946D12b" // OpenSea + ] +}; + +function handleRequest(payload) { + const chain = payload.params.chainId; + const request = payload.params.request; + + if (request.method === "eth_sendTransaction") { + const tx = request.params[0]; + if (!tx.to) { + throw new Error("Contract creation transactions are not allowed."); + } + const contract = tx.to.toLowerCase(); + + const allowed = (ALLOWED_CONTRACTS[chain] || []).map(a => a.toLowerCase()); + + if (!allowed.includes(contract)) { + throw new Error(`Blocked transaction to unapproved contract: ${contract}`); + } else { + // Forward to signing flow + signAndBroadcast(tx); + } + } +} + +// Example placeholder for your signing logic +function signAndBroadcast(tx) { + console.log("Signing and broadcasting transaction:", tx); +} +``` + +## Conclusion + +By following the steps above, you can block your users from interacting with certain smart contracts from certain apps. diff --git a/network/wallets/custodians/extended-sessions.mdx b/network/wallets/custodians/extended-sessions.mdx new file mode 100644 index 0000000..33e18f8 --- /dev/null +++ b/network/wallets/custodians/extended-sessions.mdx @@ -0,0 +1,35 @@ +--- +title: Extended WalletConnect Sessions Request +--- + +This guide will walk you through how a wallet developer can customize the session request expiry in WalletConnect using the **`expiry`** parameter. + +## Extended Session Expiry - what does it mean? + +When an app sends a request through WalletConnect (for example, a signature request), it stays “active” until the expiry time is reached. If the wallet does not respond before the expiry, the request automatically fails with a timeout. + +By default, the expiry is short, i.e., 5 minutes. Extending the session expiry time allows the wallet and app to keep the request open longer, **up to 7 days**. This is useful for cases like off-hours approvals, delayed custody flows, or multi-party signing. + +### What do wallets need to do? + +A wallet must: +- Maintain pending state until expiry or completion. +- Gracefully discard expired requests. +- Verify user intent remains valid after long delays. + +### Limits + +- **Minimum:** 300 seconds (5 min) +- **Maximum:** 604,800 seconds (7 days) + +## How can I extend the session request expiry as a wallet? + +Wallets must correctly interpret and enforce the expiry. + +- Parse `expiry` in seconds from incoming request metadata. +- Keep pending requests active until they’re resolved or the expiry time elapses. +- Notify the user of pending and expired requests. +- If the expiry has passed, return an error response (`code: 4100`, “Request expired”). +- Optional UX: display countdown timers or “expires in X hours”. + +Please refer to the [Best Practices](/network/wallets/best-practices#session-request-expiry) section to learn how you can implement this in your code. \ No newline at end of file diff --git a/network/wallets/custodians/overview.mdx b/network/wallets/custodians/overview.mdx new file mode 100644 index 0000000..528456f --- /dev/null +++ b/network/wallets/custodians/overview.mdx @@ -0,0 +1,33 @@ +--- +title: WalletConnect for Custodians and Institutions +--- + +**WalletConnect** enables custodians and institutions to offer curated, policy-enforced access to decentralized finance (DeFi) through a secure, modular SDK. + +Integrating WalletConnect and the Wallet SDK provides **institutional-grade control** while maintaining **interoperability** across thousands of dapps. Custodians can enforce granular permissions, from domain and contract verification to policy-based transaction controls, all while retaining full custody of client assets. + +## Why WalletConnect? + +WalletConnect provides the **largest and most established gateway to DeFi**, designed for scale and institutional reliability. + +### $400 Billion Total Network Volume + +Total Network Volume (TNV) is the total value of all transactions routed through the WalletConnect network in a given time (annually, in this case). + +So this represents how much money actually flows through the WalletConnect. + +WalletConnect has long been the quiet backbone of Web3 and not "just a QR code". It’s the invisible glue that connects users, dApps, and wallets, and now the scale finally shows it. + + + +### Fully Chain-Agnostic + +WalletConnect supports 300+ EVM chains, Bitcoin, Solana, and 70+ other networks. Any network with a CAIP-25 namespace is supported. + +### Available on 70,000+ dApps + +WalletConnect is available on 70,000+ dApps, making it the most widely used wallet connection protocol in the world. + +### Available on 500+ wallets + +WalletConnect is available on 500+ wallets, making it the most robust and user-friendly. You can find the list of wallets [here](https://walletguide.walletconnect.network/). \ No newline at end of file diff --git a/network/wallets/features/chain-abstraction.mdx b/network/wallets/features/chain-abstraction.mdx new file mode 100644 index 0000000..163422e --- /dev/null +++ b/network/wallets/features/chain-abstraction.mdx @@ -0,0 +1,87 @@ +--- +title: Chain Abstraction +--- +Chain Abstraction allows users to spend stablecoins across different networks seamlessly. +This solution provides wallet developers with a toolkit to integrate cross-chain functionality using WalletKit. + + +💡 Support for Chain Abstraction is currently in early access phase. + + + + +## How it works + +When an application sends a `wallet_sendTransaction` request for an ERC-20 transfer (such as USDC), +the wallet checks for available tokens across all supported networks. If the user has sufficient funds on any supported network, +they can complete the transaction instantly, regardless of which network holds their tokens. + +For example, consider a scenario where an app requests a transfer of 225 USDC on the Base Network. +Even if the user doesn't have USDC on Base, their wallet can automatically source the funds from other networks, +making the experience seamless for both the user and the application. + + +💡 Make sure you have enough gas fees in other networks from which bridging will happen. +For example, in given scenario, you need to have enough gas fees on OP Mainnet and Arbitrum. + + +The diagram below shows an example scenario where a user is interacting with an app and is asked to transfer 225 USDC to the app on Base Network. +The user does not have any USDC on Base, but their wallet seamlessly allows them to source the funds from other networks. + +![Chain Abstraction Example](https://mintcdn.com/reown-5552f0bb/27-yRRcu0Ky--oPV/images/assets/chain_abstraction_demo.png?w=1100&fit=max&auto=format&n=27-yRRcu0Ky--oPV&q=85&s=53d32b39551a6a8be0a3569d3bae1c5a) + +## Get Started + + + + Get started with WalletKit in Android. + + + + Get started with WalletKit in iOS. + + + + Get started with WalletKit in Flutter. + + + + Get started with WalletKit in React Native. + + + + Get started with WalletKit in Web. + + + + +## FAQ + +### What are the available networks for Chain Abstraction? + +Chain Abstraction is available on the following networks: + +- Base +- Arbitrum +- OP Mainnet +- Solana + +### What are the supported tokens and networks? + +Chain Abstraction supports the following tokens across different networks: + +| Network | Assets | +|-----------|-----------------| +| Optimism | USDC, USDT, ETH | +| Arbitrum | USDC, USDT, ETH | +| Base | USDC, USDS, ETH | +| Solana | USDC | + + +### What are the limitations? + +We currently support 1:1 transfers i.e. sourcing funds from one address to another. Make sure that you're transferring minimum 0.6$ worth of tokens and have enough gas to pay bridging fees. diff --git a/network/wallets/features/link-mode.mdx b/network/wallets/features/link-mode.mdx new file mode 100644 index 0000000..d22f633 --- /dev/null +++ b/network/wallets/features/link-mode.mdx @@ -0,0 +1,39 @@ +--- +title: Link Mode +--- + +WalletKit Link Mode is a low latency mechanism for transporting One-Click Auth requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection. + + + + + +## When and How can Link Mode help? + +Let's assume that a user is trying to connect their wallet to a native (mobile) dApp while commuting on a train with spotty internet. + +Now, if the user wants to sign a message on the dApp using their mobile wallet and the dApp relies on typical WebSocket connections to relay the session request. Due to unstable connectivity, the connection drops or lags, causing the wallet to not receive the sign message request promptly. + +**Using Link Mode, the dApp sends a Universal Link directly to the wallet app.** Since this doesn’t rely on maintaining a WebSocket session, the wallet receives the connection or signature request instantly and reliably, even in weak network conditions. + +## Get Started + + + + Get started with Link Mode in WalletKit - Android. + + + Get started with Link Mode in WalletKit - iOS. + + + Get started with Link Mode in WalletKit - Flutter. + + + Get started with Link Mode in WalletKit - React Native. + + diff --git a/network/wallets/features/notifications.mdx b/network/wallets/features/notifications.mdx new file mode 100644 index 0000000..7449d83 --- /dev/null +++ b/network/wallets/features/notifications.mdx @@ -0,0 +1,22 @@ +--- +title: Notifications +--- + +Enrich your wallet experience with Web3 Notifications and provide your community with direct access to critical and powerful updates from their favorite apps. +Build in-wallet notification features that allow users to subscribe, set permissions, and receive notifications from their favorite apps. + +## Get Started + + + + Get started with WalletKit in Android. + + + + Get started with WalletKit in iOS. + + + + Get started with WalletKit in React Native. + + diff --git a/network/wallets/features/one-click-auth.mdx b/network/wallets/features/one-click-auth.mdx new file mode 100644 index 0000000..3d2e2cc --- /dev/null +++ b/network/wallets/features/one-click-auth.mdx @@ -0,0 +1,31 @@ +--- +title: One-Click Auth +--- + +Enable your users to connect to web3 through a single tap with One-Click Auth, improving connectivity speeds and creating all-around better UX and friction-free user journeys. +With one-tap multi-chain and multi-account signing, let users authenticate multiple chains and accounts simultaneously. + +## Get Started + + + + Get started with WalletKit in Web. + + + + Get started with WalletKit in Android. + + + + Get started with WalletKit in iOS. + + + + Get started with WalletKit in React Native. + + + + Get started with WalletKit in Flutter. + + + diff --git a/network/wallets/features/verify.mdx b/network/wallets/features/verify.mdx new file mode 100644 index 0000000..9c998c1 --- /dev/null +++ b/network/wallets/features/verify.mdx @@ -0,0 +1,56 @@ +--- +title: Verify API +sidebarTitle: Verify +--- + +App Verification is a first-of-its-kind layered security solution that enables wallets to help users protect themselves from phishing attacks, with robust architecture enabling wallets to support users in better identifying the veracity of a domain they are attempting to connect to. + + + + + +## Security providers + +Verify API combines WalletConnect's domain registry with threat intelligence from leading web3 security providers. If any of them flags the domain behind a session proposal or session request as malicious, the `verifyContext` of that request is returned with `isScam` set to `true`. + + + + Real-time detection of malicious contracts, transactions and web3 threats. + + + + Crypto-native anti-phishing intelligence, including scam domain detection and takedowns. + + + + Real-time monitoring of malicious dapps, wallet drainers and phishing domains. + + + +## Get Started + + + + Get started with WalletKit in Android. + + + + Get started with WalletKit in iOS. + + + + Get started with WalletKit in Flutter. + + + + Get started with WalletKit in React Native. + + + + Get started with WalletKit in Web. + + + + Get started with WalletKit in .NET. + + diff --git a/network/wallets/flutter/chain-abstraction.mdx b/network/wallets/flutter/chain-abstraction.mdx new file mode 100644 index 0000000..8e97310 --- /dev/null +++ b/network/wallets/flutter/chain-abstraction.mdx @@ -0,0 +1,244 @@ +--- +title: Chain Abstraction +--- + +import HowItWorks from "/snippets/walletkit/shared/chain-abstraction/intro.mdx"; +import ErrorHandling from "/snippets/walletkit/shared/chain-abstraction/error-handling.mdx"; + + + +## Methods + +The following methods from Wallet SDK are used in implementing chain abstraction. + + +💡 Chain abstraction is currently in the early access phase + + +### Prepare + +This method is used to check if chain abstraction is needed. If it is, it will return a `PrepareDetailedResponseSuccessCompat` object with the necessary transactions and funding information. +If it is not, it will return a `PrepareResponseNotRequiredCompat` object with the original transaction. + +```swift +Future prepare({ + required String chainId, + required String from, + required CallCompat call, + Currency? localCurrency, +}); +``` + +### Execute + +This method is used to execute the chain abstraction operation. The method will handle broadcasting all transactions in the correct order and monitor the cross-chain transfer process. It returns an `ExecuteDetails` object with the transaction status and results. + +```swift +Future execute({ + required UiFieldsCompat uiFields, + required List routeTxnSigs, + required String initialTxnSig, +}) +``` + +## Usage + +When sending a transaction, first check if chain abstraction is needed using the `prepare` method. Call the `execute` method to broadcast the routing and initial transactions and wait for it to be completed. + +If the operation is successful, you need to broadcast the initial transaction and await the transaction hash and receipt. +If the operation is not successful, send a JsonRpcError to the dapp and display the error to the user. + +```swift +final response = await _walletKit.prepare( + chainId: chainId, // selected chain id + from: from, // sender address + call: CallCompat( + to: to, // contract address + input: input, // calldata + ), +); +response.when( + success: (PrepareDetailedResponseSuccessCompat deatailResponse) { + deatailResponse.when( + available: (UiFieldsCompat uiFieldsCompat) { + // If the route is available, present a CA transaction UX flow and sign hashes when approved + final TxnDetailsCompat initial = uiFieldsCompat.initial; + final List route = uiFieldsCompat.route; + + final String initialSignature = signHashMethod(initial.transactionHashToSign); + final List routeSignatures = route.map((route) { + final String rSignature = signHashMethod(route.transactionHashToSign); + return rSignature; + }).toList(); + + await _walletKit.execute( + uiFields: uiFields, + initialTxnSig: initialSignature, + routeTxnSigs: routeSignatures, + ); + }, + notRequired: (PrepareResponseNotRequiredCompat notRequired) { + // user does not need to move funds from other chains + // proceeds as normal transaction with notRequired.initialTransaction + }, + ); + }, + error: (PrepareResponseError prepareError) { + // Show an error + // contains prepareError.error as BridgingError and could be either: + // noRoutesAvailable, insufficientFunds, insufficientGasFunds + }, +); +``` + +### Implementation during Session Request + +If you are looking to trigger Chain Abstraction during a eth_sendTransaction Session Request you should do it inside the session request handler as explained in [Responding to Session requests](./usage#responding-to-session-requests) section. + +```swift +Future _ethSendTransactionHandler(String topic, dynamic params) async { + final SessionRequest pendingRequest = _walletKit.pendingRequests.getAll().last; + final int requestId = pendingRequest.id; + final String chainId = pendingRequest.chainId; + + final transaction = (params as List).first as Map; + + // Intercept to check if Chain Abstraction is required + if (transaction.containsKey('input') || transaction.containsKey('data')) { + final inputData = transaction.containsKey('input') ?? transaction.containsKey('data'); + final response = await _walletKit.prepare( + chainId: chainId, + from: transaction['from'], + call: CallCompat( + to: transaction['to'], + input: inputData, + ), + ); + response.when( + success: (PrepareDetailedResponseSuccessCompat deatailResponse) { + deatailResponse.when( + available: (UiFieldsCompat uiFieldsCompat) { + // Only if the route is available, present a Chain Abstraction approval modal + // and proceed with execute() method + if (approved) { + final TxnDetailsCompat initial = uiFieldsCompat.initial; + final List route = uiFieldsCompat.route; + + final String initialSignature = signHashMethod(initial.transactionHashToSign); + final List routeSignatures = route.map((route) { + final String rSignature = signHashMethod(route.transactionHashToSign); + return rSignature; + }).toList(); + + final executeResponse = await _walletKit.execute( + uiFields: uiFields, + initialTxnSig: initialSignature, + routeTxnSigs: routeSignatures, + ); + + // Respond to the session request. Flow shouldn't end here as the transaction was processed + return await _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: '2.0', + result: executeResponse.initialTxnReceipt, + ), + ); + } + }, + // If deatailResponse is not `available` type + // then let the flow to continue to regular send transacrion + ); + }, + ); + } + + // display a prompt for the user to approve or reject the request + // if approved + if (approved) { + final signedTx = await sendTransaction(transaction, int.parse(chainId)); + // respond to requester + await _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: '2.0', + result: signedTx, + ), + ); + } + + // if rejected + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: id, + jsonrpc: '2.0', + error: const JsonRpcError(code: 5001, message: 'User rejected method'), + ), + ); +} + +``` + +For example, check out implementation of chain abstraction in [sample wallet](https://github.com/reown-com/reown_flutter/blob/develop/packages/reown_walletkit/example/lib/dependencies/chain_services/evm_service.dart) with Flutter. + +### Token Balance + +You can use this method to query the token balance of the given address + +```swift +Future erc20TokenBalance({ + required String chainId, // chain id + required String token, // token address + required String owner, // user address +}) +``` + + ## Android + + If you didn't do it already, in your android (project's) build.gradle file add support for Jitpack: + + ``` + allprojects { + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } // <- add jipack url + } + } + ``` + + It shouldn't happen but if you encounter issues with minification, add the below rules to your application: + + ``` + -keepattributes *Annotation* + -keep class com.sun.jna.** { *; } + -keepclassmembers class com.sun.jna.** { + native ; + *; + } + -keep class uniffi.** { *; } + # Preserve all public and protected fields and methods + -keepclassmembers class ** { + public *; + protected *; + } + -dontwarn uniffi.** + -dontwarn com.sun.jna.** + ``` + + + +## Testing + +Best way to test Chain Abstraction is to use our Sample wallet. +- [Sample Wallet for iOS](https://testflight.apple.com/join/Uv0XoBuD) +- [Sample Wallet for Android](https://appdistribution.firebase.dev/i/2b8b3dce9e2831cd) + +You can also use the [AppKit laboratory](https://appkit-lab.reown.com/library/wagmi/) and try sending [USDC/USDT](/network/wallets/features/chain-abstraction#what-are-the-supported-tokens-and-networks%3F) with any chain abstraction-supported wallet. + + diff --git a/network/wallets/flutter/cloud/analytics.mdx b/network/wallets/flutter/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/flutter/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/flutter/cloud/explorer-submission.mdx b/network/wallets/flutter/cloud/explorer-submission.mdx new file mode 100644 index 0000000..e5f11c8 --- /dev/null +++ b/network/wallets/flutter/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + diff --git a/network/wallets/flutter/cloud/relay.mdx b/network/wallets/flutter/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/flutter/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/flutter/eip5792.mdx b/network/wallets/flutter/eip5792.mdx new file mode 100644 index 0000000..cdc8e64 --- /dev/null +++ b/network/wallets/flutter/eip5792.mdx @@ -0,0 +1,284 @@ +--- +title: Wallet Call API +--- + +WalletConnect supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. +Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities. + +- `wallet_sendCalls`: Requests that a wallet submits a batch of calls. +- `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet_sendCalls. +- `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet_sendCalls. +- `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication). + +## Usage + + + + ## Capabilities in CAIP-25 Connection Requests + +CAIP-25 defines how capabilities can be expressed in wallet-to-dapp connections. These capabilities control how methods like `wallet_sendCalls` behave. + +### Session Properties + +In a connection request, dapps can request capabilities via `sessionProperties`. These can be universal (across all chains) or chain-specific: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": [], + "strict": [], + "exoticThirdThing": [] + }, + "atomic": { + "status": "supported" + } +} +``` + +### Scoped Properties + +For chain-specific capabilities, dapps use `scopedProperties`: + +```json +"scopedProperties": { + "eip155:8453": { + "paymasterService": { + "supported": true + }, + "sessionKeys": { + "supported": true + } + }, + "eip155:84532": { + "auxiliaryFunds": { + "supported": true + } + } +} +``` + +### Wallet Response + +A wallet's response should indicate which capabilities it actually supports, following EIP-5792 and CAIP-25: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": ["halt", "continue"], + "strict": ["continue"] + }, + "atomic": { + "status": "ready" + } +}, +"scopedProperties": { + "eip155:1": { + "atomic": { + "status": "supported" + } + }, + "eip155:137": { + "atomic": { + "status": "unsupported" + } + }, + "eip155:84532": { + "eip155:83532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": { + "auxiliaryFunds": { + "supported": false + }, + "atomic": { + "status": "supported" + } + } + } +} +``` +- Capabilities shared across all address in a namespace can be expressed at top-level +- Address-specific capabilities can include exceptions to scope-wide capabilities + +### Atomic Capability + +According to EIP-5792, the `atomic` capability specifies how the wallet will execute batches of transactions. It has three possible values: + +- `supported` - The wallet will execute calls atomically and contiguously +- `ready` - The wallet can upgrade to support atomic execution pending user approval +- `unsupported` - The wallet provides no atomicity guarantees + +This capability is expressed per chain and is crucial for determining how `wallet_sendCalls` with `atomicRequired: true` will be handled. + + ### Example + The `wallet_getCapabilities` method is used to request information about what capabilities a wallet supports. Following EIP-5792, here's how it should be implemented: + + #### Request + ```json + { + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_getCapabilities", + "params": ["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]] + } + ``` + + #### Response + The wallet should return a response following EIP-5792, where capabilities are organized by chain ID: + + ```json + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "0x2105": { + "atomic": { + "status": "supported" + } + }, + "0x14A34": { + "atomic": { + "status": "unsupported" + } + } + } + } + ``` + + + + ### Implementation + When implementing `wallet_sendCalls`, wallets must follow these requirements: + + #### Connection Approval + - Only approve this method during the connection approval flow if your wallet can implement it correctly + - Define the `atomic` capability per chain/account in the CAIP-25 response + + #### Request Format + ```json + { + "id": 12345, + "version": "2.0", + "method": "wc_sessionRequest", + "params": { + "chainId": "caip-2-chain-id", + "request": { + "method": "wallet_sendCalls", + "params": { + "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "chainId": "0x01", + "atomicRequired": true, + "calls": [ + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x182183", + "data": "0xfbadbaf01" + } + ] + } + } + } + } + ``` + + #### Core Implementation Requirements + - Execute calls in the exact order specified in the request + - Do not wait for any calls to be finalized before completing the batch + - If the user rejects the request, do not send any calls + + #### Atomic Execution Behavior + When `atomicRequired` is `true`: + - Execute all calls atomically (either all succeed or none have any effect) + - Execute all calls contiguously (no other transactions between batch calls) + - If your wallet can upgrade from `ready` to `supported` atomicity, do so before executing + + When `atomicRequired` is `false`: + - You may execute calls sequentially without atomicity guarantees + - You may execute atomically if your wallet supports it + - You may upgrade to `supported` atomicity and execute atomically + + #### Response Enrichment + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + + + ### Example + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + To implement this functionality, the response for wallet_sendCalls should be enriched with capabilities: + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + Specify the `scopedProperties` when approving a session: + + ```json + "scopedProperties": { + "eip155": { + "walletService": [{ + "url": "", + "methods": ["wallet_getCallsStatus"] + }] + } + } + ``` + + ### Response Format + The response format for `wallet_getCallsStatus` varies based on the execution method: + + #### For Atomic Execution + ```json + { + "receipts": [/* single receipt or array of receipts */], + "atomic": true + } + ``` + + #### For Non-Atomic Execution + ```json + { + "receipts": [/* array of receipts for all transactions */], + "atomic": false + } + ``` + + + For non-atomic execution, include all transactions in the receipts array, even those that were included on-chain but eventually reverted. + + + + +## References +- EIP-5792: https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability +- CAIP-25 namespaces: https://github.com/ChainAgnostic/namespaces/blob/main/eip155/caip25.md diff --git a/network/wallets/flutter/installation.mdx b/network/wallets/flutter/installation.mdx new file mode 100644 index 0000000..4b2f6a5 --- /dev/null +++ b/network/wallets/flutter/installation.mdx @@ -0,0 +1,33 @@ +--- +title: Installation +--- + +- Add `reown_walletkit` as dependency in your `pubspec.yaml` and run `flutter pub get` (check out the [latest version](https://pub.dev/packages/reown_walletkit/install)) +- Or simply run `flutter pub add reown_walletkit` + + + +If you are on **Android** add jitpack support to your android (project's) build.gradle file + + ``` + allprojects { + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } // <- add jipack url + } + } + ``` + +If you are on **MacOS** add the following to your `DebugProfile.entitlements` and `Release.entitlements` files to connect to the WebSocket server. + +```xml +com.apple.security.network.client + +``` + + + +## Next Steps + +Now that you've installed Wallet SDK SDK, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/flutter/link-mode.mdx b/network/wallets/flutter/link-mode.mdx new file mode 100644 index 0000000..5394c03 --- /dev/null +++ b/network/wallets/flutter/link-mode.mdx @@ -0,0 +1,106 @@ +--- +title: Link Mode +--- + +WalletKit Link Mode is a low latency mechanism for transporting [One-Click Auth](/network/wallets/flutter/one-click-auth) requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection. + +By enabling it, the wallet and dapp will communicate through declared Universal Links on iOS and/or App Links on Android **even without an internet connection.** + + +Make sure that [One-Click Auth](/network/wallets/flutter/one-click-auth) is implemented before enabling Link Mode. + + +### How to enable it: + +1. Add a Universal Link for your wallet in the **Explorer** tab of your [**Cloud project configuration**](https://dashboard.walletconnect.com/sign-in), under the **Mobile Linking** section + +2. Configure your `PairingMetadata`'s `redirect:` object with that Universal Link + +3. Set the `linkMode` property to `true`: + +```javascript {12,13} +final _walletKit = ReownWalletKit( + core: ReownCore( + projectId: '{YOUR_PROJECT_ID}', + ), + metadata: PairingMetadata( + name: 'Example Wallet', + description: 'Example wallet description', + url: 'https://example.com/', + icons: ['https://example.com/logo.png'], + redirect: Redirect( + native: 'examplewallet://', + universal: 'https://example.com/wallet', + linkMode: true, + ), + ), +); +``` + +Once everything is properly configured, and the user interacts with a Link Mode-supporting dApp, your wallet will receive requests through it. + +In Flutter, there are several plugins that can help you integrate Universal/App Links. However, regardless of which one you choose, it is crucial that, when capturing an incoming link, you pass it to WalletKit so it can process the request. + +```javascript +void _onLinkCaptured(String link) async { + await _walletKit.dispatchEnvelope(link); +} +``` + +### Platform specifics: + + + + +1. Ensure that you handle incoming Universal Links in the appropriate methods of `AppDelegate` or `SceneDelegate`. +2. Ensure that you have enabled the Associated Domains Capability in your XCode project and that your Universal Link is properly configured. _(Depending on the previous states of your Provisioning Profiles it may be necessary to update or create new ones)_ + +```xml + + + + + com.apple.developer.associated-domains + + applinks:your_wallet_universal_link.com + + + +``` + +3. Update/Create your domain's `.well-known/apple-app-site-association` file accordingly. + +For more information on how to configure universal links for your app, refer to the [Apple Documentation](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content?language=swift).
+For a debugging guide, visit the [Debugging Universal Links](https://developer.apple.com/documentation/technotes/tn3155-debugging-universal-links) page.
+ +You can check our Flutter's Wallet SDK sample [AppDelegate file](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_walletkit/example/ios/Runner/AppDelegate.swift) as a reference. + +
+ + +1. Ensure that you handle incoming App Links in your Activity's `onCreate` method and in `onNewIntent` callback. +2. Ensure that your App Link is properly configured in your app's `AndroidManifest.xml` file with the `autoVerify` set to `true`: + +```xml + + + + + + + + + + +``` + +3. Update/Create your domains's `.well-known/assetlinks.json` file accordingly + +For more information on how to configure app links for your app, refer to the [Android Documentation](https://developer.android.com/training/app-links/verify-android-applinks).
+For enabling links to app content check [this](https://developer.android.com/training/app-links/deep-linking) documentation page.
+For more information on how to interact with other apps using intents, see [Android Intent Documentation](https://developer.android.com/training/basics/intents). + +You can check our Flutter's Wallet SDK sample [MainActivity file](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_walletkit/example/android/app/src/main/kotlin/com/example/wallet/MainActivity.kt) as a reference. + +
+
diff --git a/network/wallets/flutter/mobile-linking.mdx b/network/wallets/flutter/mobile-linking.mdx new file mode 100644 index 0000000..686c7c8 --- /dev/null +++ b/network/wallets/flutter/mobile-linking.mdx @@ -0,0 +1,232 @@ +--- +title: Mobile Linking +--- + +import HowToTest from "/snippets/walletkit/shared/mobile-linking.mdx"; + + + + +This feature is only relevant to native platforms. + + + +## Usage + +Mobile Linking allows your wallet to automatically redirect back to the Dapp allowing for less user interactions and hence a better UX for your users. + +### Establishing Communication Between Mobile Wallets and Apps + +When integrating a wallet with a mobile application, it's essential to understand how they communicate. The process involves two main steps: + +1. **QR Code Handshake:** The mobile app (Dapp) generates a unique URI (Uniform Resource Identifier) and displays it as a QR code. This URI acts like a secret handshake. When the user scans the QR code using their wallet app, they establish a connection. It's like saying, "Hey, let's chat!" +2. **Deep Links and Universal Links:** The URI from the QR code allows the wallet app to create a [deep link](https://support.google.com/google-ads/answer/10023042?hl=en#:~:text=Deep%20links%20send%20mobile%20device,%2C%20Shopping%2C%20and%20Display%20campaigns.) or [universal link](https://developer.apple.com/ios/universal-links/). These links work on both Android and iOS. They enable seamless communication between the wallet and the app. + + + +**Developers should prefer Deep Linking over Universal Linking.** + +Universal Linking may redirect the user to a browser, which might not provide the intended user experience. Deep Linking ensures the user is taken directly to the app. + + + +### Key Behavior to Address + +In some scenarios, wallets use redirect metadata provided in session proposals to open applications. This can cause unintended behavior, such as: + +Redirecting to the wrong app when multiple apps share the same redirect metadata (e.g., a desktop and mobile version of the same Dapp). +Opening an unrelated application if a QR code is scanned on a different device than where the wallet is installed. + +#### Recommended Approach + +To avoid this behavior, wallets should: + +- **Restrict Redirect Metadata to Deep Link Use Cases**: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. + +The connection and sign request flows are similar across platforms. + +### Connection Flow + +- **Dapp Prompts User:** The Dapp asks the user to connect. +- **User Chooses Wallet:** The user selects a wallet from a list of compatible wallets. +- **Redirect to Wallet:** The user is redirected to their chosen wallet. +- **Wallet Approval:** The wallet prompts the user to approve or reject the session (similar to granting permission). +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reunites with Dapp:** After all the interactions, the user ends up back in the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking-light.png) + + +### Sign Request Flow + +When the Dapp needs the user to sign something (like a transaction), a similar pattern occurs: + +- **Automatic Redirect:** The Dapp automatically sends the user to their previously chosen wallet. +- **Approval Prompt:** The wallet asks the user to approve or reject the request. +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reconnects:** Eventually, the user returns to the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking_sign-light.png) + + +## Platform preparations + + + + +In order for Dapps to be able to trigger your wallet for a connection or sign request using deep links you first need to add your custom scheme under [`CFBundleURLTypes`](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleurltypes) key in your Info.plist file. + +For instance, if your Wallet's name is Example Wallet, your custom scheme would be more likely as `examplewallet://`, therefor you will add the following in your iOS's Info.plist file: + +```ruby +CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleURLSchemes + + examplewallet + + + +``` + + + +In order for Dapps to be able to trigger your wallet for a connection or sign request using deep links you first need to declare an [``](https://developer.android.com/training/app-links/deep-linking#adding-filters) in your wallet's Manifest.xml as follows: + +For instance, if your Wallet's name is Example Wallet, your custom scheme would be more likely as `examplewallet://`, therefor you will add the following intent filter in your Android's Manifest.xml file: + +```xml + + + + + + +``` + + + + +Since Flutter leverages on native APIs, you must follow iOS and Android steps for each native platform. + +**Additionally**, you would have to set FlutterDeepLinkingEnabled key to true on iOS's Info.plist file. + +```xml +FlutterDeepLinkingEnabled + +``` + +More information in official documentation: https://docs.flutter.dev/ui/navigation/deep-linking + + + + + + +Dapps developers must do the same for their own custom schemes if they want the wallet to be able to navigate back after a session approval or a sign request response + + + + + +## Integration + +Either you are approving a session proposal or responding to a session request, redirecting back to the Dapp is as simply as launching requester's `redirect` object in `PairingMetadata`, the same way as Dapps would call your wallet's `redirect` object on their side: + +A dapp would call `examplewallet://wc?uri={pairingUri}` from their side when they request to connect with your wallet, and given the fact that `examplewallet` is your registered custom scheme then your wallet will be opened. + +### Redirecting back to dapp (proposer) after session approval: + +Wallet SDK exports a handy method for easy redirection back to the requester app, whether it be after a session proposal, a session authentication or a session request. + +```javascript +Future redirectToDapp({ + required String topic, + required Redirect? redirect, +}) +``` + +After Session Proposal: + +```javascript +_walletKit!.onSessionProposal.subscribe(_onSessionProposal); +// +void _onSessionProposal(SessionProposalEvent? event) async { + if (event != null) { + // Process session proposal + // .... + // Redirect back to proposer dapp + try { + await _walletKit.redirectToDapp( + topic: topic, + redirect: event.params.proposer.metadata.redirect, + ); + } catch (e) { + ... + } + } +} +``` + +After Session Authenticate: + +```javascript +// If your wallet supports One-Click Auth +_walletKit!.onSessionAuthRequest.subscribe(_onSessionAuthRequest); +// +void _onSessionAuthRequest(SessionAuthRequest? event) async { + if (event != null) { + // Process session authentication + // .... + // Redirect back to proposer dapp + try { + await _walletKit.redirectToDapp( + topic: topic, + redirect: event.params.proposer.metadata.redirect, + ); + } catch (e) { + ... + } + } +} +``` + +A dapp would call `examplewallet://` (or even better `session.peer?.metadata.redirect?.native` object) from their side when they request to sign a transaction, and given the fact that `session.peer?.metadata.redirect?.native` contains your registered custom scheme (`examplewallet://`) then your wallet will be opened. + +**Redirecting back to dapp (proposer) after responding to a sign request:** + +```javascript +// Your registered request handler for the given requested method will be triggered +Future personalSignRequestHandler(String topic, dynamic parameters) async { + // Process signing requests + // ... + // With the given topic with retrieve the current session data + final session = _walletKit.sessions.get(topic); + // And we get the peer metadata to trigger dapp's redirect value + try { + await _walletKit.redirectToDapp( + topic: topic, + redirect: session!.peer.metadata.redirect, + ); + } catch (e) { + ... + } +} +``` + + + +`launchUrlString()` from [url_launcher](https://pub.dev/packages/url_launcher) official package was used as an example to explain the mechanism, you can choose whatever other package you would like. + + diff --git a/network/wallets/flutter/one-click-auth.mdx b/network/wallets/flutter/one-click-auth.mdx new file mode 100644 index 0000000..40655f2 --- /dev/null +++ b/network/wallets/flutter/one-click-auth.mdx @@ -0,0 +1,146 @@ +--- +title: One-click Auth +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/authenticatedSessions-light.png) + + +## Handling Authentication Requests + +To handle incoming authentication requests, subscribe to the `onSessionAuthRequest` event. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```javascript +// subscribe to onSessionAuthRequest with a handler +_walletKit!.onSessionAuthRequest.subscribe(_onSessionAuthRequest); +// +void _onSessionAuthRequest(SessionAuthRequest? args) { + if (args != null) { + // Process the authentication request here. + // Steps include: + // 1. Populate the authentication payload with the supported chains and methods + // 2. Format the authentication message using the payload and the user's account + // 3. Present the authentication message to the user + // 4. Sign the authentication message(s) to create a verifiable authentication object(s) + // 5. Approve the authentication request with the authentication object(s) + } +} +``` + +## Authentication Objects/Payloads + +```javascript +final supportedChains = ['eip155:1', 'eip155:10', 'eip155:137']; +final supportedMethods = ['personal_sign', 'eth_sendTransaction']; +final SessionAuthPayload authPayload = AuthSignature.populateAuthPayload( + authPayload: args.authPayload, + chains: supportedChains, + methods: supportedMethods, +); +final cacaoRequestPayload = CacaoRequestPayload.fromSessionAuthPayload( + newAuthPayload, +); + +// Prepare the user's address in CAIP10(https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) format +final iss = 'eip155:1:0x59e2f66C0E96803206B6486cDb39029abAE834c0'; +// Now you can use the authPayload to format the authentication message +final message = _walletKit!.formatAuthMessage( + iss: iss, + cacaoPayload: cacaoRequestPayload, +); + +// Present the authentication message to the user +... +``` + +## Approving Authentication Requests + + + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + + +```javascript +// Approach 1 +// Sign the authentication message(s) to create a verifiable authentication object(s) +final credentials = EthPrivateKey.fromHex('$privateKey'); +final signature = credentials.signPersonalMessageToUint8List( + Uint8List.fromList(message.codeUnits), +); +final hexSignature = bytesToHex(signature, include0x: true); +// Build the authentication object(s) +final cacao = AuthSignature.buildAuthObject( + requestPayload: cacaoRequestPayload, + signature: CacaoSignature( + t: CacaoSignature.EIP191, + s: hexSignature, + ), + iss: iss, +); + +// Approve +await _walletKit!.approveSessionAuthenticate( + id: args.id, + auths: [cacao], +); + +// Approach 2 +// Note that you can also sign multiple messages for every requested chain/address pair +final List cacaos = []; +for (var chain in newAuthPayload.chains) { + final message = _walletKit!.formatAuthMessage( + iss: iss, + cacaoPayload: cacaoRequestPayload, + ); + final credentials = EthPrivateKey.fromHex('$privateKey'); + final signature = credentials.signPersonalMessageToUint8List( + Uint8List.fromList(message.codeUnits), + ); + final hexSignature = bytesToHex(signature, include0x: true); + final cacao = AuthSignature.buildAuthObject( + requestPayload: cacaoRequestPayload, + signature: CacaoSignature( + t: CacaoSignature.EIP191, + s: hexSignature, + ), + iss: iss, + ); + cacaos.add(cacao) +} + +// Approve +await _walletKit!.approveSessionAuthenticate( + id: args.id, + auths: cacaos, +); +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method. + +```javascript +await _walletKit!.rejectSessionAuthenticate( + id: args.id, + reason: Errors.getSdkError(Errors.USER_REJECTED_AUTH).toSignError(), +); +``` + +## Testing One-click Auth + +You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/flutter/usage.mdx b/network/wallets/flutter/usage.mdx new file mode 100644 index 0000000..7587fe4 --- /dev/null +++ b/network/wallets/flutter/usage.mdx @@ -0,0 +1,448 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section. + +**[Initialization](#initialization)**: Creating a new ReownWalletKit instance and initializing it with a projectId from [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +**Session**: Connection between a dapp and a wallet. + +- [Namespace Builder](#namespace-builder): + Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object +- [Session Approval](#session-approval): + Approving a session sent from a dapp +- [Session Rejection](#session-rejection): + Rejecting a session sent from a dapp +- [Responding to Session Requests](#responding-to-session-requests): + Responding to session requests sent from a dapp +- [Updating a Session](#updating-a-session): + Updating a session sent between a dapp and wallet +- [Extending a Session](#extending-a-session): + Extending a session between a dapp and wallet +- [Session Disconnect](#session-disconnect): + Disconnecting a session between a dapp and wallet +- [Formatted Errors](#formatted-errors): + A list of useful error objects to be used + + + +## Initialization + +To create an instance of ReownWalletKit, you need to pass in the `core` and `metadata` parameters. + +```javascript +final _walletKit = ReownWalletKit( + core: ReownCore( + projectId: '{YOUR_PROJECT_ID}', + ), + metadata: PairingMetadata( + name: 'Example Wallet', + description: 'Example wallet description', + url: 'https://example.com/', + icons: ['https://example.com/logo.png'], + redirect: Redirect( + native: 'examplewallet://', + universal: 'https://reown.com/examplewallet', + ), + ), +); +``` + +## Session + +A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires. + +### Namespace Builder + +On flutter you don't need to worry about Namespace Builder as Flutter SDK would handle that for you and generate a namespace object with the supported ones for you to approve. + +All you have to do is make sure you register... + +1. **wallet's accounts** with `_walletKit.registerAccount()` for accounts you want events and methods to be enabled on. This is essential if you want to properly form a session object between your wallet and the requester dapp. +2. **request handlers** with `_walletKit.registerRequestHandler()` for methods you want to support on your wallet. Optional but **highly recommended** if you want to seamlessly create a session object, as we will see in the coming section. +3. **events emitters** with `_walletKit.registerEventEmitter()` for events you want to support on your wallet. Optional but recommended if you plan to send events such as `chainChanged` and `accountsChanged`. + +And you'll have to do this **for every chain** you want to support on your wallet. + +```dart +// Quick example: + +List supportedChains = ['eip155:1', 'eip155:10', ...]; +List walletAddresses = ['0x1234......']; +List supportedEvents = ['chainChanged', 'accountsChanged', ...]; + +Map get _methodHandlers => { + 'personal_sign': personalSignHandler, + 'eth_sendTransaction': ethSendTransactionHandler, +}; + +for (final chainId in supportedChains) { + for (var address in walletAddresses) { + _walletKit!.registerAccount( + chainId: chainId, // CAIP-2 format chain id + accountAddress: address, // 0x.... address + ); + } + + for (var handler in _methodHandlers.entries) { + _walletKit.registerRequestHandler( + chainId: chainId, + method: handler.key, + handler: handler.value, + ); + } + + for (final event in supportedEvents) { + _walletKit.registerEventEmitter( + chainId: chainId, + event: event, + ); + } +} +``` + +When a dApp propose a session, with declared namespaces, your wallet will be able to approve an **already generated set of namespaces** based on your registered accounts, methods and events. + +You can access this object in **SessionProposalEvent** during `onSessionProposal` event by querying `event.params.generatedNamespaces`. (See [Session Approval](#session-approval) below) + + +You can choose **not to use** `registerRequestHandler` to configure your supported methods and rather define them during session approval (See [Session Approval](#session-approval) below) + +By not using `registerRequestHandler` your methods requests are going to be sent through `onSessionRequest` event subscription. + +If you do choose to use `registerRequestHandler` **(highly recommended)** then `onSessionRequest` event subscription is not going to be called. + + +Flutter SDK provides a handy `MethodsConstants` and `EventsConstants` for already defined set of required and optional values. + +### EVM methods & events + +In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events: + +```ts +{ + //... + methods: [ + "eth_accounts", + "eth_requestAccounts", + "eth_sendRawTransaction", + "eth_sign", + "eth_signTransaction", + "eth_signTypedData", + "eth_signTypedData_v3", + "eth_signTypedData_v4", + "eth_sendTransaction", + "personal_sign", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + "wallet_getPermissions", + "wallet_requestPermissions", + "wallet_registerOnboarding", + "wallet_watchAsset", + "wallet_scanQRCode", + "wallet_sendCalls", + "wallet_getCallsStatus", + "wallet_showCallsStatus", + "wallet_getCapabilities", + ], + events: [ + "chainChanged", + "accountsChanged", + "message", + "disconnect", + "connect", + ] +} +``` + +### Session Approval + +As mentioned before, the `SessionProposalEvent` is emitted when a dapp initiates a new session with your wallet. The event object will include the information about the dapp and requested namespaces. The wallet should display a prompt for the user to approve or reject the session. + +To approve a session, subscribe to `onSessionProposal` event and call `approveSession()` passing in the `event.id` and the namespaces object. + +```javascript +_walletKit.onSessionProposal.subscribe((SessionProposalEvent? event) { + // display a prompt for the user to approve or reject the session + // .... + // If approved + _walletKit.approveSession( + id: event.id, + namespaces: event.params.generatedNamespaces ?? {}, + ); +}); +``` + + +As mentioned before, `namespaces:` should be either `event.params.generatedNamespaces!` if you decided to use `registerRequestHandler` method to configure your supported methods or a `Map` object defined by yourself if you decided **not** to use `registerRequestHandler` method + + +#### Pairing + +The `pair` method initiates a pairing process with a dapp using the given `uri` (QR code from the dapps). To learn more about pairing, checkout out the [docs](https://specs.walletconnect.com/2.0/specs/clients/core/pairing/). + +Scan the QR code and parse the URI, and pair with the dapp. +Upon the first pairing, you will immediately receive `onSessionProposal` and `onAuthRequest` events. + +```javascript +Uri uri = Uri.parse(scannedUriString); +await _walletKit.pair(uri: uri); +``` + +### Session Rejection + +To reject the request, pass in an error code and reason according to [protocol specs](https://specs.walletconnect.com/2.0/specs/clients/sign/error-codes). See also [Formatted Errors](#formatted-errors) section. + +To reject a session: + +```javascript +_walletKit.onSessionProposal.subscribe((SessionProposalEvent? event) async { + // display a prompt for the user to approve or reject the session + // .... + // If rejected + await _walletKit.rejectSession( + id: event.id, + reason: Errors.getSdkError(Errors.USER_REJECTED).toSignError(), + ); +}); +``` + +### Responding to Session requests + +To handle a session request, such as `personal_sign`, you have two ways as explained before, and they are mutually exclusive, so, either you use onSessionRequest event subscription or your methods handlers configured with `registerRequestHandler`. + +1. The **recommended one** is to register a request handler for the methods and chains you want to support. So let's say your wallet supports `eip155:1` and `eip155:137`. This would translate to: + +```javascript +final supportedChains = ['eip155:1', 'eip155:137']; +Map supportedMethods = { + 'personal_sign': _personalSignHandler, + 'eth_sendTransaction': _ethSendTransactionHandler, +}; +// Register your handlers as stated in Namespace Builder section +for (var chainId in supportedChains) { + for (var method in supportedMethods.entries) { + _walletKit.registerRequestHandler( + chainId: chainId, + method: method.key, + handler: method.value, + ); + } +} + +Future _personalSignHandler(String topic, dynamic params) async { + final SessionRequest pendingRequest = _walletKit.pendingRequests.getAll().last; + final int requestId = pendingRequest.id; + + // message should arrive encoded + final decoded = hex.decode(params.first.substring(2)); + final message = utf8.decode(decoded); + + // display a prompt for the user to approve or reject the request + // if approved + if (approved) { + // Your code to sign the message here + final signature = await signMessage(message); + + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: '2.0', + result: signature, + ), + ); + } + + // if rejected + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: id, + jsonrpc: '2.0', + error: const JsonRpcError(code: 5001, message: 'User rejected method'), + ), + ); +} + +Future _ethSendTransactionHandler(String topic, dynamic params) async { + final SessionRequest pendingRequest = _walletKit.pendingRequests.getAll().last; + final int requestId = pendingRequest.id; + final String chainId = pendingRequest.chainId; + + final transaction = (params as List).first as Map; + + // display a prompt for the user to approve or reject the request + // if approved + if (approved) { + final signedTx = await sendTransaction(transaction, int.parse(chainId)); + // respond to requester + await _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: requestId, + jsonrpc: '2.0', + result: signedTx, + ), + ); + } + + // if rejected + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: id, + jsonrpc: '2.0', + error: const JsonRpcError(code: 5001, message: 'User rejected method'), + ), + ); +} +``` + +2. The other way is subscribing to `onSessionRequest` events (if you didn't use `generatedNamespaces` object) and handle the request based on the method that is firing the event. + +```javascript +_walletKit.onSessionRequest.subscribe(_onSessionRequest); + +void _onSessionRequest(SessionRequestEvent? event) async { + if (event != null) { + final id = event.id; + final topic = event.topic; + final method = event.method; + final chainId = event.chainId; + final params = event.params as List; + + // message should arrive encoded + final decoded = hex.decode(params.first.substring(2)); + final message = utf8.decode(decoded); + + // display a prompt for the user to approve or reject the request + // if approved + if (approved) { + // Your code to sign the message here + final signature = ... + + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: id, + jsonrpc: '2.0', + result: signature, + ), + ); + } + // if rejected + return _walletKit.respondSessionRequest( + topic: topic, + response: JsonRpcResponse( + id: id, + jsonrpc: '2.0', + error: const JsonRpcError(code: 5001, message: 'User rejected method'), + ), + ); + } +} +``` + + +Remember that if you have handlers registered these are going to be triggered **instead of** the `onSessionRequest` event. + + +### Updating a Session + +If you wish to include new accounts, chains or methods in an existing session, `updateSession` allows you to do so. +You need pass in the `topic` and a new `Namespaces` object that contains all of the existing namespaces as well as the new data you wish to include. + +After you update the session, the dapp connected to your wallet will receive a `SessionUpdate` event. + +```javascript +await _walletKit.updateSession(topic: 'topic', namespaces: '{}') +``` + +### Extending a Session + +To extend the session, call the `extendSession` method and pass in the new `topic`. The `SessionUpdate` event will be emitted from the wallet. + +```javascript +await _walletKit.extendSession(topic: 'topic') +``` + +### Session Disconnect + +To initiate a session disconnect, call the `disconnectSession` method and pass in the `topic` and a `reason`. + +When either the dapp or the wallet disconnects from a session, a `SessionDelete` event will be emitted. It's important to subscribe to this event so you could keep your state up-to-date. + +```javascript +await _walletKit.disconnectSession( + topic: session.topic, + reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(), +); +``` + +Using `disconnectSession()` alone will make the pairing topic persist, i.e, it can be re-used until it expires. If you want to disconnect (remove) the pairing topic as well you would have add another call as follows: + +```javascript +await _walletKit.core.pairing.disconnect( + topic: pairing.topic, +); +``` + +#### Supporting session events + +In order to support session events, such as `chainChanged` or `accountChanged`, you would have to register an event emitter for such events, for every chain you want to emit an event for (similar to request handlers). + +```javascript +final supportedChains = ['eip155:1', 'eip155:137']; +const supportedEvents = ['chainChanged', 'accountChanged']; +for (var chainId in supportedChains) { + for (var event in supportedEvents) { + _walletKit.registerEventEmitter( + chainId: chainId, + event: event, + ); + } +} +``` + +And to emit an event, call `emitSessionEvent()` as follows: + +```javascript +await _walletKit.emitSessionEvent( + topic: session.topic, + chainId: 'eip155:1', + event: SessionEventParams( + name: 'chainChanged', + data: 1, + ), +); +``` + +For a better understanding please check out the [example wallet](https://github.com/reown-com/reown_flutter/tree/master/packages/reown_walletkit/example/lib) and, in particular, the [EVMService](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_walletkit/example/lib/dependencies/chain_services/evm_service.dart) inside of it. + +### Formatted Errors + +Our SDK exports a variety of ready-made error objects for you to use in the different situations. Most commonly used are... + +```javascript +// When user rejects session proposal or method request. +final userRejectedError = Errors.getSdkError(Errors.USER_REJECTED).toSignError(); + +// When the request coming to your wallet can not be unparsed +final malformedRequest = Errors.getSdkError(Errors.MALFORMED_REQUEST_PARAMS).toSignError(); + +// When user disconnects the session +final userDisconnected = Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(); + +// When dapp request an unsupported method to your wallet +final unsupportedMethods = Errors.getSdkError(Errors.UNSUPPORTED_METHODS).toSignError(); +``` + +But you can check the full list of [available errors here](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_core/lib/utils/errors.dart) diff --git a/network/wallets/flutter/verify.mdx b/network/wallets/flutter/verify.mdx new file mode 100644 index 0000000..ca3b621 --- /dev/null +++ b/network/wallets/flutter/verify.mdx @@ -0,0 +1,46 @@ +--- +title: Verify API +--- + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. +Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect's domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +These are: + + + + + +## Disclaimer + +Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + +## Domain risk detection + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +- Domain match: The domain linked to this request has been verified as this application's domain. + - This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +- Unverified: The domain sending the request cannot be verified. + - This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +- Mismatch: The application's domain doesn't match the sender of this request. + - This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +- Threat: This domain is flagged as malicious and potentially harmful. + - This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Implementation + +To check the Verify API validations and whether or not your user is interacting with potentially malicious dapp, you can do so by accessing the `verifyContext` included in the `SessionProposalEvent`: + +```javascript +_walletKit!.onSessionProposal.subscribe((SessionProposalEvent? args) { + if (args != null) { + final scamApp = args.verifyContext?.validation.scam; + final invalidApp = args.verifyContext?.validation.invalid; + final validApp = args.verifyContext?.validation.valid; + final unknown = args.verifyContext?.validation.unknown; + } +}); +``` \ No newline at end of file diff --git a/network/wallets/guides/tonconnect-walletconnect.mdx b/network/wallets/guides/tonconnect-walletconnect.mdx new file mode 100644 index 0000000..43abea8 --- /dev/null +++ b/network/wallets/guides/tonconnect-walletconnect.mdx @@ -0,0 +1,179 @@ +--- +title: TON Connect WalletConnect Integration +sidebarTitle: TON Connect + WalletConnect +description: "Learn how to enable WalletConnect support in your TON Connect application." +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +This guide explains how to enable WalletConnect support in your [TON Connect](https://www.npmjs.com/package/@tonconnect/sdk) application, allowing users to connect with WalletConnect-compatible wallets. + +## Prerequisites + +Before enabling WalletConnect in your TON Connect application, ensure you have the following: + +### 1. TON Connect Project + +You should have an existing TON Connect project initialized with the [@tonconnect/sdk](https://www.npmjs.com/package/@tonconnect/sdk) package. If you haven't set up TON Connect yet, please refer to the [TON Connect documentation](https://docs.ton.org/develop/dapps/ton-connect/overview) to get started. + +### 2. WalletConnect Project ID + +Create a new project on the WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. You will need this project ID to initialize WalletConnect in your application. + + + +### 3. Allowlist Your Domains + +To help prevent malicious use of your project ID, you are strongly encouraged to set an allowlist of [origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) where your project ID is used. You can manage your allowlist in the [WalletConnect Dashboard](https://dashboard.walletconnect.com) under the project settings. + +The allowlist supports a list of origins in the format `[scheme://]`. Using `localhost` (or `127.0.0.1`) is always permitted, and if the allowlist is empty, all origins are allowed. Updates take 15 minutes to apply. + +Examples of possible origins in the allowlist: +- `example.com` - allows `https://example.com` or `http://example.com` but not `https://www.example.com` +- `https://example.com` - allows `https://example.com` but not `http://example.com` +- `https://*.example.com` - allows `https://www.example.com` but not `https://example.com` + + +Requests from origins not in the allowlist will be denied. Make sure to add all domains where your app will be deployed. + + +## Enable WalletConnect + +To enable WalletConnect in your TON Connect application, use the `initializeWalletConnect()` function from the `@tonconnect/sdk` package along with the `UniversalConnector` from `@reown/appkit-universal-connector`. + +```typescript +import { initializeWalletConnect } from '@tonconnect/sdk'; +import { UniversalConnector } from '@reown/appkit-universal-connector'; + +initializeWalletConnect(UniversalConnector, { + projectId: 'YOUR_PROJECT_ID', + metadata: { + name: 'My DApp', + description: 'My awesome DApp', + url: 'https://mydapp.com', + icons: ['https://mydapp.com/icon.png'] + } +}); +``` + +### Configuration Options + +The `initializeWalletConnect` function accepts the following configuration options: + +| Option | Type | Required | Description | +|--------|------|----------|-------------| +| `projectId` | `string` | Yes | Your WalletConnect project ID from the [Dashboard](https://dashboard.walletconnect.com) | +| `metadata.name` | `string` | Yes | The name of your application | +| `metadata.description` | `string` | Yes | A brief description of your application | +| `metadata.url` | `string` | Yes | The URL of your application | +| `metadata.icons` | `string[]` | Yes | An array of icon URLs for your application | + +### Example Implementation + +Here's a complete example of integrating WalletConnect into a TON Connect application: + +```typescript +import { TonConnect } from '@tonconnect/sdk'; +import { initializeWalletConnect } from '@tonconnect/sdk'; +import { UniversalConnector } from '@reown/appkit-universal-connector'; +import { + TonConnectUIProvider, + TonConnectButton, +} from '@tonconnect/ui-react'; + +// Initialize WalletConnect support +initializeWalletConnect(UniversalConnector, { + projectId: 'YOUR_PROJECT_ID', + metadata: { + name: 'My TON DApp', + description: 'A decentralized application on TON', + url: 'https://mytonapp.com', + icons: ['https://mytonapp.com/icon.png'] + } +}); + + +export function App() { + // Create TON Connect instance + const tonConnect = new TonConnect({ + manifestUrl: 'https://mytonapp.com/tonconnect-manifest.json' + }); + + return ( +
+

WalletConnect + TON React Example

+ + + +
+ ) +} +``` + +## Handling `ton_proof` + +When using TON Connect with WalletConnect, `ton_proof` is requested and returned as part of the connection response using the [CAIP-222](https://chainagnostic.org/CAIPs/caip-222) authentication flow. The proof payload is passed via the `authentication` parameter during `connect()`, and the signed proof is available on `session.authentication` after the connection is established. + +### Requesting `ton_proof` During Connection + +To request `ton_proof` during the WalletConnect session establishment, pass the `authentication` parameter when calling `connect()` on the underlying `UniversalConnector` provider: + +```typescript +import { UniversalConnector } from '@reown/appkit-universal-connector'; + +const connector = await UniversalConnector.init({ + projectId: 'YOUR_PROJECT_ID', + metadata: { + name: 'My TON DApp', + description: 'A decentralized application on TON', + url: 'https://mytonapp.com', + icons: ['https://mytonapp.com/icon.png'] + }, + networks: [{ + namespace: 'ton', + chains: [tonMainnet], + methods: ['ton_sendMessage', 'ton_signData'], + events: [] + }] +}); + +const session = await connector.provider.connect({ + optionalNamespaces: { + ton: { + methods: ['ton_sendMessage', 'ton_signData'], + chains: ['ton:-239'], + events: [] + } + }, + authentication: [{ + uri: 'https://mytonapp.com', + domain: 'mytonapp.com', + chains: ['ton:-239'], + nonce: '', + ttl: 86400, + statement: '' + }] +}); +``` + +### Reading the Proof Result + +After a successful connection, the proof result is available on `session.authentication` as an array of [CAIP-222 Cacao](https://chainagnostic.org/CAIPs/caip-222) objects: + +```typescript +const authenticationResults = session?.authentication; + +if (authenticationResults && authenticationResults.length > 0) { + // Each result is a Cacao object containing the signed proof + const proof = authenticationResults[0]; + console.log('ton_proof result:', proof); +} +``` + + +The `ton_proof` result is **not** available in `onStatusChange` when using WalletConnect. You must read it from `session.authentication` directly after the connection is established. + + +## Next Steps + +After integrating WalletConnect into your TON Connect application, users will be able to connect using any WalletConnect-compatible wallet. For more information about TON-specific RPC methods supported by WalletConnect, see the [TON Chain Support](/network/wallets/chains/ton) documentation. diff --git a/network/wallets/ios/best-practices.mdx b/network/wallets/ios/best-practices.mdx new file mode 100644 index 0000000..a75a736 --- /dev/null +++ b/network/wallets/ios/best-practices.mdx @@ -0,0 +1,213 @@ +--- +title: Best Practices +--- + +The purpose of this guide is to show the best practices in regards of the WalletKit client usage. The goal is to provide the best user experience that just works in every circumstances. + + +In order to ensure the best user experience and flawless connection flow, please make sure that WalletKit is initialized immediately after your app launch, especially if launched via a WalletConnect Deep Link. It guarantees that websocket connection is opened immediately and all requests are received by your wallet + + +## Pairing + +A pairing is a connection between a wallet and a dapp that has fixed permissions to only allow a dapp to propose a session through it. Dapp can propose infinite number of sessions on one pairing. Wallet must use a pair method from the WalletKit client to pair with dapp. + +```swift +let uri = WalletConnectURI(string: urlString) + +if let uri { +Task { +try await WalletKit.instance.pair(uri: uri) +} +} + +``` + +### Pairing State + +A pairing state is a primitive exposed by the WalletKit client for a wallet to indicate whether it should await a session proposal. The pairing state is `true` when a wallet scans a QR and awaits a session proposal. Once the session proposal is received by the wallet, the pairing state is changed to `false`. +When `true` wallet should show a loading indicator awaiting a session proposal, when changed to `false` a proposal dialog should be displayed. + +```swift +WalletKit.instance.pairingStatePublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] isPairing in + self?.showPairingLoading = isPairing +}.store(in: &disposeBag) +``` + +### Pairing Expiry + +A pairing expiry event is triggered whenever a pairing is expired. The expiry for inactive pairing is 5 mins, whereas for active pairing is 30 days. A pairing becomes active when a session proposal is received and user successfully approves it. This event helps to know when given pairing expires and update UI accordingly. + +```Swift +WalletKit.instance.pairingExpirationPublisher + .receive(on: DispatchQueue.main) + .sink { pairing in + guard !pairing.active else { return } + // let user know that pairing has expired +}.store(in: &publishers) +``` + +### Expected User flow + +### Pairing Flow + + + + + +### Pairing Error + + + + + +### Expected Errors + +While pairing the following errors might occur: + +- No Internet connection error or pairing timeout when scanning QR with no Internet connection + - User should pair again with Internet connection +- Pairing expired error when scanning a QR code with expired pairing + - User should refresh a QR code and scan again +- Pairing with existing pairing is not allowed + - User should refresh a QR code and scan again. I usually happens when user scans an already paired QR code. + +## Session Proposal + +A session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Whenever a user wants to establish a connection between a wallet and a dapp, one should approve a session proposal. + +### User Action Feedback + +Whenever user approves or rejects a session proposal, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +Session Approve +```swift +do { + try await WalletKit.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces, sessionProperties: proposal.sessionProperties) + // Update UI, remove loader +} catch { + // present error +} +``` + +Session Reject + +```swift +do { + try await WalletKit.instance.reject(proposalId: proposal.id, reason: .userRejected) + // Update UI, remove loader +} catch { + // present error +} +``` + +### Session Proposal Expiry + +A session proposal expiry is 5 mins. It means a given proposal is stored for 5 mins in the SDK storage and user has 5 mins for approval or rejection decision. After that time the below event is emitted and proposal modal should be removed from the app's UI. + +```swift +WalletKit.instance.sessionProposalExpirationPublisher.sink { _ in + // let user know that session proposal has expired, update UI +}.store(in: &publishers) +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session proposal the following errors might occurs: + +- No Internet connection + - It happens when a user tries to approve or reject session proposal with no Internet connection +- Session proposal expired + - It happens when users tries to approve or reject expired session proposal +- Invalid namespaces + - It happens when a validation of session namespaces fails +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Session Request + +A session request represents the request sent by a dapp to a wallet. + +### User Action Feedback + +Whenever user approves or rejects a session request, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +```swift +do { + try await WalletKit.instance.respond(requestId: request.id, signature: signature, from: account) + // update UI -> remove the loader +} catch { + // present error to the user +} +``` + +### Session Request Expiry + +A session request expiry is defined by a dapp. It's value must be between now() + 5mins and now() + 7 days. After the session request expires the below event is emitted and session request modal should be removed from the app's UI. + +```swift +WalletKit.instance.requestExpirationPublisher.sink { _ in + // let user know that request has expired +}.store(in: &publishers) +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + +### Error Handling + + + +### Expected Errors + +While approving or rejecting a session request the following error might occur: + +- Invalid session + - This error might happen when user approves or rejects a session request on expired session +- Session request expired + - This error might happen when user approves or rejects a session request that already expires +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Web Socket Connection State + +The Web Socket connection state tracks the connection with the relay server, event is emitted whenever a connection state changes. + +```swift +WalletKit.instance.socketConnectionStatusPublisher + .receive(on: DispatchQueue.main) + .sink { status in + switch status { + case .connected: + // ... + case .disconnected: + // ... + } +}.store(in: &publishers) +``` + +### Expected User flow + +### Connection State + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/connection_state.gif) + \ No newline at end of file diff --git a/network/wallets/ios/chain-abstraction.mdx b/network/wallets/ios/chain-abstraction.mdx new file mode 100644 index 0000000..a25e241 --- /dev/null +++ b/network/wallets/ios/chain-abstraction.mdx @@ -0,0 +1,92 @@ +--- +title: Chain Abstraction +--- + +import HowItWorks from "/snippets/walletkit/shared/chain-abstraction/intro.mdx"; +import ErrorHandling from "/snippets/walletkit/shared/chain-abstraction/error-handling.mdx"; + + + +## Methods + +The following methods from Wallet SDK are used in implementing chain abstraction. + + +💡 Chain abstraction is currently in the early access phase, use with careful + + +### Prepare + +This method is used to check if chain abstraction is needed. If it is, it will return a response with the necessary transactions. +If it is not, it will return a response with the original transaction. + +```swift +@available(*, message: "This method is experimental. Use with caution.") +public func prepare(chainId: String, from: FfiAddress, call: Call, accounts: [String], localCurrency: Currency) async throws -> PrepareDetailedResponse +} +``` + +### Execute + +This method is used to execute the chain abstraction operation. The method will handle broadcasting all transactions in the correct order and monitor the cross-chain transfer process. It returns an `ExecuteDetails` object with the transaction status and results. + +```swift +@available(*, message: "This method is experimental. Use with caution.") +public func execute(uiFields: UiFields, routeTxnSigs: [FfiPrimitiveSignature], initialTxnSig: FfiPrimitiveSignature) async throws -> ExecuteDetails { +} +``` + +## Usage + +When sending a transaction, first check if chain abstraction is needed using the `prepare` method. Call the `execute` method to broadcast the routing and initial transactions and wait for it to be completed. + +If the operation is successful, you need to broadcast the initial transaction and await the transaction hash and receipt. +If the operation is not successful, send a JsonRpcError to the dapp and display the error to the user. + +```swift +let routeResponseSuccess = try await WalletKit.instance.ChainAbstraction.prepare( + chainId: selectedNetwork.chainId.absoluteString, + from: myAccount.address, + call: call, + accounts: caip10Accounts, + localCurrency: .usd +) + +switch routeResponseSuccess { +case .success(let routeResponse): + switch routeResponse { + case .available(let UiFileds): + // If the route is available, present a CA transaction flow + for txnDetails in uiFields.route { + let hash = txnDetails.transactionHashToSign + let sig = try! signer.signHash(hash) + routeTxnSigs.append(sig) + } + + // sign initial transaction hash + let initialTxHash = uiFields.initial.transactionHashToSign + let initialTxnSig = try! signer.signHash(initialTxHash) + + let executeDetails = try await WalletKit.instance.ChainAbstraction.execute(uiFields: uiFields, routeTxnSigs: routeTxnSigs, initialTxnSig: initialTxnSig) + + case .notRequired: + // user does not need to move funds from other chains, sign and broadcast original transaction + + } +case .error(let routeResponseError): + // Show an error +} +``` + +For example, check out implementation of chain abstraction in [sample wallet](https://github.com/reown-com/reown-swift/blob/develop/Example/WalletApp/PresentationLayer/Wallet/CATransactionModal/CATransactionPresenter.swift) with Swift. + + + +## Testing + +Best way to test Chain Abstraction is to use [sample wallet](https://testflight.apple.com/join/09bTAryp). +You can also use the [AppKit laboratory](https://appkit-lab.reown.com/library/wagmi/) and try sending any supported [tokens](/network/wallets/features/chain-abstraction#what-are-the-supported-tokens-and-networks%3F) with any chain abstraction-supported wallet. + + diff --git a/network/wallets/ios/cloud/analytics.mdx b/network/wallets/ios/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/ios/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/ios/cloud/explorer-submission.mdx b/network/wallets/ios/cloud/explorer-submission.mdx new file mode 100644 index 0000000..e5f11c8 --- /dev/null +++ b/network/wallets/ios/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + diff --git a/network/wallets/ios/cloud/relay.mdx b/network/wallets/ios/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/ios/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/ios/eip5792.mdx b/network/wallets/ios/eip5792.mdx new file mode 100644 index 0000000..cdc8e64 --- /dev/null +++ b/network/wallets/ios/eip5792.mdx @@ -0,0 +1,284 @@ +--- +title: Wallet Call API +--- + +WalletConnect supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. +Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities. + +- `wallet_sendCalls`: Requests that a wallet submits a batch of calls. +- `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet_sendCalls. +- `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet_sendCalls. +- `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication). + +## Usage + + + + ## Capabilities in CAIP-25 Connection Requests + +CAIP-25 defines how capabilities can be expressed in wallet-to-dapp connections. These capabilities control how methods like `wallet_sendCalls` behave. + +### Session Properties + +In a connection request, dapps can request capabilities via `sessionProperties`. These can be universal (across all chains) or chain-specific: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": [], + "strict": [], + "exoticThirdThing": [] + }, + "atomic": { + "status": "supported" + } +} +``` + +### Scoped Properties + +For chain-specific capabilities, dapps use `scopedProperties`: + +```json +"scopedProperties": { + "eip155:8453": { + "paymasterService": { + "supported": true + }, + "sessionKeys": { + "supported": true + } + }, + "eip155:84532": { + "auxiliaryFunds": { + "supported": true + } + } +} +``` + +### Wallet Response + +A wallet's response should indicate which capabilities it actually supports, following EIP-5792 and CAIP-25: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": ["halt", "continue"], + "strict": ["continue"] + }, + "atomic": { + "status": "ready" + } +}, +"scopedProperties": { + "eip155:1": { + "atomic": { + "status": "supported" + } + }, + "eip155:137": { + "atomic": { + "status": "unsupported" + } + }, + "eip155:84532": { + "eip155:83532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": { + "auxiliaryFunds": { + "supported": false + }, + "atomic": { + "status": "supported" + } + } + } +} +``` +- Capabilities shared across all address in a namespace can be expressed at top-level +- Address-specific capabilities can include exceptions to scope-wide capabilities + +### Atomic Capability + +According to EIP-5792, the `atomic` capability specifies how the wallet will execute batches of transactions. It has three possible values: + +- `supported` - The wallet will execute calls atomically and contiguously +- `ready` - The wallet can upgrade to support atomic execution pending user approval +- `unsupported` - The wallet provides no atomicity guarantees + +This capability is expressed per chain and is crucial for determining how `wallet_sendCalls` with `atomicRequired: true` will be handled. + + ### Example + The `wallet_getCapabilities` method is used to request information about what capabilities a wallet supports. Following EIP-5792, here's how it should be implemented: + + #### Request + ```json + { + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_getCapabilities", + "params": ["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]] + } + ``` + + #### Response + The wallet should return a response following EIP-5792, where capabilities are organized by chain ID: + + ```json + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "0x2105": { + "atomic": { + "status": "supported" + } + }, + "0x14A34": { + "atomic": { + "status": "unsupported" + } + } + } + } + ``` + + + + ### Implementation + When implementing `wallet_sendCalls`, wallets must follow these requirements: + + #### Connection Approval + - Only approve this method during the connection approval flow if your wallet can implement it correctly + - Define the `atomic` capability per chain/account in the CAIP-25 response + + #### Request Format + ```json + { + "id": 12345, + "version": "2.0", + "method": "wc_sessionRequest", + "params": { + "chainId": "caip-2-chain-id", + "request": { + "method": "wallet_sendCalls", + "params": { + "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "chainId": "0x01", + "atomicRequired": true, + "calls": [ + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x182183", + "data": "0xfbadbaf01" + } + ] + } + } + } + } + ``` + + #### Core Implementation Requirements + - Execute calls in the exact order specified in the request + - Do not wait for any calls to be finalized before completing the batch + - If the user rejects the request, do not send any calls + + #### Atomic Execution Behavior + When `atomicRequired` is `true`: + - Execute all calls atomically (either all succeed or none have any effect) + - Execute all calls contiguously (no other transactions between batch calls) + - If your wallet can upgrade from `ready` to `supported` atomicity, do so before executing + + When `atomicRequired` is `false`: + - You may execute calls sequentially without atomicity guarantees + - You may execute atomically if your wallet supports it + - You may upgrade to `supported` atomicity and execute atomically + + #### Response Enrichment + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + + + ### Example + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + To implement this functionality, the response for wallet_sendCalls should be enriched with capabilities: + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + Specify the `scopedProperties` when approving a session: + + ```json + "scopedProperties": { + "eip155": { + "walletService": [{ + "url": "", + "methods": ["wallet_getCallsStatus"] + }] + } + } + ``` + + ### Response Format + The response format for `wallet_getCallsStatus` varies based on the execution method: + + #### For Atomic Execution + ```json + { + "receipts": [/* single receipt or array of receipts */], + "atomic": true + } + ``` + + #### For Non-Atomic Execution + ```json + { + "receipts": [/* array of receipts for all transactions */], + "atomic": false + } + ``` + + + For non-atomic execution, include all transactions in the receipts array, even those that were included on-chain but eventually reverted. + + + + +## References +- EIP-5792: https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability +- CAIP-25 namespaces: https://github.com/ChainAgnostic/namespaces/blob/main/eip155/caip25.md diff --git a/network/wallets/ios/installation.mdx b/network/wallets/ios/installation.mdx new file mode 100644 index 0000000..3fbed1e --- /dev/null +++ b/network/wallets/ios/installation.mdx @@ -0,0 +1,47 @@ +--- +title: Installation +--- + +WalletConnect Wallet SDK is available via [Swift Package Manager](https://swift.org/package-manager/) or [Cocoapods](https://cocoapods.org/). + + + + +You can add a WalletConnect SDK to your project with Swift Package Manager. In order to do that: + +1. Open XCode +2. Go to File -> Add Packages +3. Paste the repo GitHub URL: https://github.com/reown-com/reown-swift +4. Tap Add Package +5. Select WalletConnect check mark + + + + +**WARNING** + +Cocoapods support may be deprecated soon, use SPM instead. + + +1. Update Cocoapods spec repos. Type in terminal `pod repo update` +2. Initialize Podfile if needed with `pod init` +3. Add pod to your Podfile: + +```ruby +pod 'reown-swift' +``` + +4. Install pods with `pod install` + +If you encounter any problems during package installation, you can specify the exact path to the repository + +```ruby +pod 'reown-swift', :git => 'https://github.com/reown-com/reown-swift.git', :tag => '1.0.0' +``` + + + + +## Next Steps + +Now that you've installed Wallet SDK, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/ios/link-mode.mdx b/network/wallets/ios/link-mode.mdx new file mode 100644 index 0000000..0776646 --- /dev/null +++ b/network/wallets/ios/link-mode.mdx @@ -0,0 +1,43 @@ +--- +title: Link Mode +--- + +Wallet SDK Link Mode is a low latency mechanism for transporting [One-Click Auth](/network/wallets/ios/one-click-auth) requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection. + +To support Link Mode add a universal link for your wallet in Cloud project configuration dashboard, configure your `AppMetadata.Redirect` with a valid universal link and set the `linkMode` property to `true`: + + +Make sure that [1-Click Auth](/network/wallets/ios/one-click-auth) is implemented before enabling Link Mode. + + +```swift {5,6} +let metadata = AppMetadata( + ... + redirect: try! AppMetadata.Redirect( + native: "exampleApp://", + universal: "https://example.com/example_wallet", + linkMode: true + ) +) + +WalletKit.configure( + metadata: metadata, + ... +) +``` + +Once link mode and universal linking are properly configured and the user interacts with a link mode supporting dApp, your wallet will receive requests over universal linking. You must pass these requests to WalletKit so it can process them: + +```swift +try WalletKit.instance.dispatchEnvelope(url.absoluteString) +``` + +Ensure to handle incoming universal links in different methods of `AppDelegate` or `SceneDelegate`. + +For more information on how to configure universal links for your app, refer to the [Apple Documentation](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content?language=objc). + +For a debugging guide, visit the [Debugging Universal Links](https://developer.apple.com/documentation/technotes/tn3155-debugging-universal-links) page. + +You can also find this [article](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app?language=objc) helpful. + + diff --git a/network/wallets/ios/mobile-linking.mdx b/network/wallets/ios/mobile-linking.mdx new file mode 100644 index 0000000..73502d4 --- /dev/null +++ b/network/wallets/ios/mobile-linking.mdx @@ -0,0 +1,244 @@ +--- +title: Mobile Linking +--- + +import HowToTest from "/snippets/walletkit/shared/mobile-linking.mdx"; + + + +**Note** + +This feature is only relevant to native platforms. + + +## Usage + +Mobile Linking allows your wallet to automatically redirect back to the Dapp allowing for less user interactions and hence a better UX for your users. + +### Establishing Communication Between Mobile Wallets and Apps + +When integrating a wallet with a mobile application, it's essential to understand how they communicate. The process involves two main steps: + +1. **QR Code Handshake:** The mobile app (Dapp) generates a unique URI (Uniform Resource Identifier) and displays it as a QR code. This URI acts like a secret handshake. When the user scans the QR code using their wallet app, they establish a connection. It's like saying, "Hey, let's chat!" +2. **Deep Links and Universal Links:** The URI from the QR code allows the wallet app to create a [deep link](https://support.google.com/google-ads/answer/10023042?hl=en#:~:text=Deep%20links%20send%20mobile%20device,%2C%20Shopping%2C%20and%20Display%20campaigns.) or [universal link](https://developer.apple.com/ios/universal-links/). These links work on both Android and iOS. They enable seamless communication between the wallet and the app. + + + +**Developers should prefer Deep Linking over Universal Linking.** + +Universal Linking may redirect the user to a browser, which might not provide the intended user experience. Deep Linking ensures the user is taken directly to the app. + + +#### Recommended Approach + +To avoid this behavior, wallets should: + +- **Restrict Redirect Metadata to Deep Link Use Cases**: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. + +#### Recommended Approach + +To avoid this behavior, wallets should: + +Restrict Redirect Metadata to Deep Link Use Cases: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. +Ensure Unique Redirect URIs for Cross-Platform Apps: Cross-platform Dapps should use distinct redirect URIs for their mobile and desktop versions to avoid conflicts. + +The connection and sign request flows are similar across platforms. + +### Connection Flow + +- **Dapp Prompts User:** The Dapp asks the user to connect. +- **User Chooses Wallet:** The user selects a wallet from a list of compatible wallets. +- **Redirect to Wallet:** The user is redirected to their chosen wallet. +- **Wallet Approval:** The wallet prompts the user to approve or reject the session (similar to granting permission). +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reunites with Dapp:** After all the interactions, the user ends up back in the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking-light.png) + + +### Sign Request Flow + +When the Dapp needs the user to sign something (like a transaction), a similar pattern occurs: + +- **Automatic Redirect:** The Dapp automatically sends the user to their previously chosen wallet. +- **Approval Prompt:** The wallet asks the user to approve or reject the request. +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reconnects:** Eventually, the user returns to the Dapp. + + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/mobileLinking_sign-light.png) + + +## Platform preparations + +In order for Dapps to be able to trigger your wallet for a connection or sign request using deep links you first need to add your custom scheme under [`CFBundleURLTypes`](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleurltypes) key in your Info.plist file. + +```ruby +CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleURLSchemes + + examplewallet + + + +``` + + + +Dapps developers must do the same for their own custom schemes if they want the wallet to be able to navigate back after a session approval or a sign request response + + + + +## Integration + +### iOS Wallet Support + +iOS has some more caveats to the integration but we ensure to make it as straightforward as possible. Since its operating system is not designed to handle multiple applications subscribing to the same deep linking schema, we've designed the AppKit to list supporting wallets on our [WalletGuide](https://walletguide.walletconnect.network/) and target specific deep links or universal links for each wallet. + +To add your own wallet to the Explorer, login to your [WalletConnect Dashboard](https://dashboard.walletconnect.com/sign-in) account. + +```bash +# For deep links +examplewallet://wc?uri=wc:94caa59c77dae0dd234b5818fb7292540d017b27d41f7f387ee75b22b9738c94@2?relay-protocol=irn&symKey=ce3a2c7724c03cf1769ba8b1bdedad5414cc7b920aa3fb72112b997d1916266f + +# For universal links +https://example.wallet/wc?uri=wc:94caa59c77dae0dd234b5818fb7292540d017b27d41f7f387ee75b22b9738c94@2?relay-protocol=irn&symKey=ce3a2c7724c03cf1769ba8b1bdedad5414cc7b920aa3fb72112b997d1916266f +``` + +Additionally when there is a signing request triggered by the Dapp it will hit the deep link with an incomplete URI, this should be ignored and not considered valid as it's only used for automatically redirecting the users to approve or reject a signing request. + +```bash +# For deep links +examplewallet://wc?uri=wc:00e46b69-d0cc-4b3e-b6a2-cee442f97188@2 + +# For universal links +https://example.wallet/wc?uri=wc:00e46b69-d0cc-4b3e-b6a2-cee442f97188@2 +``` + +--- + +### WalletConnectRouter + +### Overview + +WalletConnectRouter simplifies navigation by automatically redirecting users back to the DApp after they've interacted with a wallet via a deep link. This eliminates the need for users to manually navigate back after approving a session or confirming a transaction. + +### Key Features + +**Automatic Redirection:** By invoking WalletConnectRouter.goBack(uri: "example://")—where "example://" is the DApp's custom scheme as declared in their AppMetadata redirect field—users are seamlessly returned to the DApp. + +### Important Consideration + +**Mandatory redirect Field:** Starting with WalletConnect SDK version 1.9.5, specifying the redirect field in the AppMetadata object is mandatory to avoid redirection issues. + +### Installation and Usage + +```swift +import WalletConnectRouter + +try await Sign.instance.approve(proposalId: , namespaces: ) + +if let uri = proposal.proposer.redirect?.native { + WalletConnectRouter.goBack(uri: uri) +} else { + // Inform the user to manually return to the DApp +} +``` + +--- + +### Limitations + +This section outlines some of the known limitations and constraints when using WalletConnect on iOS. + +### Redirects on iOS 17 and Above + +Automatic redirection to browser-based DApps after wallet interaction is not possible from iOS 17 onwards. Developers should adjust their app's UI to inform users about manual navigation back to the browser. + +For iOS versions below 17, `WalletConnectRouter.goBack(uri: uri)` facilitates automatic redirection. + + + + + +### iOS Universal Links Constraints + + + +**Developers should prefer Deep Linking over Universal Linking.** + +In the case of Universal Linking, the user may be redirected to the browser, which may not be the desired behavior. Deep Linking ensures that the user is redirected to the app, providing a seamless experience. + + +When using WalletConnect on iOS and triggering a wallet interaction (e.g. when sending a transaction or signing a message), you may experience issues where the native app is not opened as expected and a browser navigation occurs instead. + +This issue occurs because Universal Links (app links) on iOS will only open the native app when the following rules are followed: + +- **The wallet interaction must be triggered by a user-initiated event,** e.g. in a click handler rather than on page load or in an asynchronous callback. +- **The wallet interaction must be triggered as soon as possible within the event handler.** Any preceding asynchronous work (e.g. estimating gas, resolving an ENS name, fetching a nonce) should have already completed before the event handler fires. This may require you to design the user experience around this constraint, preventing users from initiating a wallet interaction until it's ready rather than doing the work lazily. + +**Note that even if your own code follows these rules, libraries you depend on may be running their own asynchronous logic before triggering a wallet interaction.** For example, [Ethers asynchronously populates transactions before sending them.](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) Known workarounds are documented below, but if you're still experiencing these issues, you should raise them with the relevant library maintainers. + +### For Ethers v5 (Legacy) + +These are the known workarounds for avoiding app linking issues on iOS when using [Ethers v5](https://docs.ethers.io/v5). + +### When sending a transaction + +1. **[`signer.sendTransaction`](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) + should be avoided in favor of + [`signer.sendUncheckedTransaction`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#JsonRpcSigner-sendUncheckedTransaction)** +
+  This avoids an asynchronous call to retrieve the internal block number which + Ethers uses to resolve a complete [`TransactionResponse`](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionResponse) + object. +
+  Note that as a result of this optimization, `sendUncheckedTransaction` returns + a mock transaction response that only contains the `hash` property and a `wait` + method. All other properties are `null`. +2. **The transaction's `to` property should be a plain address rather than an ENS name** +
+ This avoids an asynchronous call to automatically resolve ENS names during the + send process. +
+  If you still want to support ENS name resolution, you should manually run + [`provider.resolveName`](https://docs.ethers.io/v5/api/providers/provider/#Provider-ResolveName) + ahead of time, storing the result before the user attempts to send a transaction. + Do not resolve ENS names in the event handler. +3. **The transaction's `gasLimit` property should be set** +
+ This avoids the asynchronous work performed in `sendTransaction` which automatically + estimates the gas limit if it's missing. +
+  If you still want to use the same gas limit estimation logic from `sendTransaction`, + you should manually run [`provider.estimateGas`](https://docs.ethers.io/v5/api/providers/provider/#Provider-estimateGas) + ahead of time, storing the result before the user attempts to send the transaction. + Do not estimate gas in the event handler. + +### When calling a write method on a contract + +1. **[`contract.METHOD_NAME`](https://docs.ethers.io/v5/api/contract/contract/#contract-functionsSend) + should be avoided if favor of calling + [`contract.populateTransaction.METHOD_NAME`](https://docs.ethers.io/v5/api/contract/contract/#contract-populateTransaction) + ahead of time, then sending the populated transaction with + [`signer.sendUncheckedTransaction`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#JsonRpcSigner-sendUncheckedTransaction).** + +2. When sending the populated transaction, you should [follow the same guidelines as regular + transactions](#when-sending-a-transaction) to avoid any asynchronous logic breaking the app link + navigation. Do not populate the contract transaction in the event handler. + +### When signing a message + +If the message depends on the result of an asynchronous call (e.g. retrieving a nonce when implementing [Sign-In With Ethereum](https://login.xyz)), you should do this work ahead of time, storing the result before the user attempts to sign the message. Do not perform this asynchronous work in the event handler. diff --git a/network/wallets/ios/notifications/notify/installation.mdx b/network/wallets/ios/notifications/notify/installation.mdx new file mode 100644 index 0000000..ed9852f --- /dev/null +++ b/network/wallets/ios/notifications/notify/installation.mdx @@ -0,0 +1,42 @@ +--- +title: Installation +--- + +Notify API is available via [Swift Package Manager](https://swift.org/package-manager/) or [Cocoapods](https://cocoapods.org/). + + + + +You can add the WalletConnect Notify package to your project with the Swift Package Manager. In order to do that: + +1. Open XCode +2. Go to File -> Add Packages +3. Paste the repo GitHub URL: https://github.com/reown-com/reown-swift +4. Tap Add Package +5. Select `WalletConnectNotify` check mark + + + + +1. Update Cocoapods spec repos. Type in terminal `pod repo update` +2. Initialize Podfile if needed with `pod init` +3. Add pod to your Podfile: + +```ruby +pod 'WalletConnectSwiftV2/WalletConnectNotify' +``` + +4. Install pods with `pod install` + +If you encounter any problems during package installation, you can specify the exact path to the repository + +```ruby +pod 'WalletConnectSwiftV2/WalletConnectNotify', :git => 'https://github.com/reown-com/reown-swift.git', :tag => '1.8.0' +``` + + + + +## Next Steps + +Now that you've installed WalletConnect Notify, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the Notify API. diff --git a/network/wallets/ios/notifications/notify/overview.mdx b/network/wallets/ios/notifications/notify/overview.mdx new file mode 100644 index 0000000..cdfead0 --- /dev/null +++ b/network/wallets/ios/notifications/notify/overview.mdx @@ -0,0 +1,26 @@ +--- +title: Overview +--- + + +For those integrating notifications related to wallet pairing and sign requests, please check [here](../push). + + +The WalletConnect Notify API is designed to enhance the interaction between wallet users and dapps by offering a robust notification system. This API empowers wallet developers to implement a dynamic notification experience directly within their wallets. It provides the functionality for users to opt-in to notifications, ensuring they stay informed about critical events and interactions. + +The Notify API is versatile, with support for both iOS and Android platforms, making it an ideal choice for cross-platform wallet applications. + +Coupled with the AppKit Notifications, the Notify API forms part of a comprehensive toolkit that enables seamless integration of web3 communication and messaging features into dapps. This ensures a more connected and interactive experience for users in the decentralized ecosystem. + +## Features + +Some of the key features of the Notify API include: + +- **Push Notifications for Desktop and Native Platforms**: This feature enables dapps to directly send vital notifications to user wallets, ensuring timely and relevant communication. +- **Robust Spam Protection**: Users have complete authority over which dapps can send them notifications, effectively eliminating any unsolicited messages from unknown sources. Furthermore, users can fine-tune their preferences to only receive notifications types they are interested in, like new features or some important events occurrence. +- **Chain Agnostic Architecture**: The Notify API is built to be compatible with any blockchain, allowing seamless multi-chain support without the need for writing additional integration code. **As of November 2023, the Notify Server and Clients are equipped to support EVM chains. Plans to extend support to non-EVM chains are in progress and are a significant part of our upcoming development roadmap.** + +_Example integration_ + +![Web3Inbox](/images/w3i-hero.png) + \ No newline at end of file diff --git a/network/wallets/ios/notifications/notify/resources.mdx b/network/wallets/ios/notifications/notify/resources.mdx new file mode 100644 index 0000000..5979679 --- /dev/null +++ b/network/wallets/ios/notifications/notify/resources.mdx @@ -0,0 +1,19 @@ +--- +title: Resources +--- + +Valuable assets for developers interested in integrating Notify API into their wallet. + +- [Web3Inbox.com app](https://app.web3inbox.com) - Inbox web app that simulates wallet experience. +- [GM dapp](https://gm.walletconnect.com/) - Example dapp that sends notification every hour. +- [GM hackers](https://github.com/WalletConnect/gm-hackers) - Template used in hackathons sponsored by WalletConnect. + +## Wallet Resources + +To check more in details go and visit our [WalletKit Swift implementation app](https://github.com/reown-com/reown-swift/tree/main/Example/WalletApp). Sample Wallet sample apps can be found under the Example directory in [Swift's V2 repository](https://github.com/reown-com/reown-swift/tree/main/Example) + +If you need to test your app's integration, you can use one [our GM dapp.](https://gm.walletconnect.com/) + +## Need Technical Support?[](https://docs.reown.com/walletkit/namespaces#need-technical-support) + +If you require technical support along the way, please drop a message on the [WalletConnect GitHub](https://github.com/orgs/WalletConnect/discussions/categories/web3inbox-sdk-support) and our team will get back to you as soon as possible. diff --git a/network/wallets/ios/notifications/notify/spam-protection.mdx b/network/wallets/ios/notifications/notify/spam-protection.mdx new file mode 100644 index 0000000..d1a2bd6 --- /dev/null +++ b/network/wallets/ios/notifications/notify/spam-protection.mdx @@ -0,0 +1,27 @@ +--- +title: Spam Protection +--- + +Users play a critical role in web3. That’s why, with Web3Inbox, we’re committed to ensuring users can enjoy a safe, seamless, and reliable experience that puts them in the driver’s seat. As part of that pledge, Web3Inbox provides a number of user-first, anti-spam features and elements that ensure users are always in control of their web3 communications. + +## How are users protected from spam with Web3Inbox? + +### Becoming a Web3Inbox customer + +When a wallet offers app notifications to their users via Web3Inbox, the feature will always be optional. If users decide they want to receive notifications from selected apps via their wallet, they’ll be able to ‘opt-in’ and subscribe to an app’s notifications by signing a message request. Similarly, when accessing notifications through the [Web3Inbox.com app](https://app.web3inbox.com), users will be met with the same request for each application they choose to subscribe to. This feature not only enables users to experience a customized, ‘app-by-app’ approach to staying connected in web3, but also ensures they only ever hear from the apps they choose to — no unsolicited notifications or spam from unknown senders. Its their curated inbox, connected with only those they choose. + +### Setting customized notification preferences + +Once users have subscribed to their chosen apps, they have the option to define and set which types of notifications they receive from those apps. For example, a user may wish to receive only information regarding changes to their portfolio from a DEX, or, they might want to receive notifications from an NFT marketplace — but only notifications regarding their own NFT collections. In these scenarios, they’ll have the ability to disable other notification types, like marketing updates, and ensure their feed is curated to show only information that’s meaningful to them. As apps set their own notification types, they have unlimited optionality to really build out a notification structure they know can support their users’ needs — no ‘one size fits all’ approach, but a personable, community-oriented structure that puts both app and user needs’ at the forefront of communication. + +### Rate limiting + +Apps are limited to a maximum number of notifications they’re able to send to their community. Specifically, apps may send accounts notifications twice an hour on average, but may exceed that average in bursts of up to 50 at a time. + +## Our continued pledge on spam protection + +We’re constantly working on improving and growing our products, and we have a number of impactful anti-spam features and functions in the works set to increase the overall protection and user experience of Web3Inbox users: + +### User reporting + +Users will have the ability to report applications that appear to be acting or engaging with their community in a malicious or suspicious manner. Projects that are flagged as malicious may be removed from the Web3Inbox discover page and have notification functionality disabled. diff --git a/network/wallets/ios/notifications/notify/usage.mdx b/network/wallets/ios/notifications/notify/usage.mdx new file mode 100644 index 0000000..3d6743f --- /dev/null +++ b/network/wallets/ios/notifications/notify/usage.mdx @@ -0,0 +1,184 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + + +In this section, we showcase the aspects of using the Notify API. We'll guide you through the initial steps of initializing the Notify client and logging in a blockchain account. You'll also learn how to manage your subscriptions and messages. Additionally, we cover the process of setting up and displaying push notifications on your preferred platform. To ensure a good user experience, we include best practices for spam protection, helping you to enable the users to maintain control over the notifications wallet receives. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out Extra (Platform Specific) under this section. + +- [Initialization](#initialization): + Creating a new Notify Client instance and initializing it with a projectId from [[WalletConnect Dashboard](https://dashboard.walletconnect.com/). +- [Account login](#account-login): + A SIWE message must be signed by the user in order to authorize the client to use Notify API +- [Subscribing to a new dapp](#subscribing-to-a-new-dapp): + Opt-in to receive notifications from dapp +- [Fetching active subscriptions](#fetching-active-subscriptions): + Get active subscriptions +- [Fetching subscription’s notification](#fetching-subscriptions-notifications): + Get notifications of a subscription +- [Updating subscriptions notification settings](#updating-subscriptions-notification-settings): + Change allowed notification types sent by dapp +- [Unsubscribe from a dapp](#unsubscribe-from-a-dapp): + Opt-out from receiving notifications from a dapp +- [Account logout](#account-logout): + To stop receiving notifications to this client, accounts can logout of using Notify API +- [Apple Push Notification service setup](?platform=ios#apple-push-notification-service-setup): + Configuring iOS app in order to decrypt notifications + +## Initialization + + + +Important: Confirm you have configured the [Network Client](https://docs.reown.com/advanced/api/core/relay) first. + +Configure the `Notify` instance with: + +```swift +try Notify.configure(environment: APNSEnvironment, crypto: CryptoProvider) +``` + +`environment` - Use `debug` environment for debug builds and `release` for release and TestFlight builds. + +`crypto` - CryptoProvider is a protocol, you are required to provide an implementation of `recoverPubKey` and `keccak256` methods. + +## Account login + +In order to register account in Notify API to be able to subscribe to any dapp to start receiving notifications, account needs to sign SIWE message to prove ownership. Developers can check if an account is registered by calling **`isRegistered()`** function. If the account is not registered, developers should call **`prepareRegistration()`** and then **`register()`** function to register the account. + +To login to manage notifications, you must request message to sign with `prepareRegistration()` method and register signature with `register()` method. Once logged in, cross-device syncing will be enabled. + +```swift +let params = try await Notify.instance.prepareRegistration(account: account, domain: "com.YOURAPPDOMAIN") +let signature = onSign(message: params.message) // Sign message with your signer +try await Notify.instance.register(params: params, signature: signature) +``` + +- `account` - An CAIP-10 account that the identity key will be issued for +- `domain` - A domain of your wallet, you should use your bundle ID + +Provide your own sign function implementation that returns CacaoSignature. If SIWE is not implemented on your app you can always use our [MessageSignerFactory](https://github.com/reown-com/reown-swift/blob/main/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift) and [DefaultSignerFactory](https://github.com/reown-com/reown-swift/blob/main/Example/Shared/DefaultSignerFactory.swift) from our sample app that uses Web3 SPM package. + +```swift +func onSign(message: String) -> CacaoSignature { + let privateKey = Data(hex: privateKey) + let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() + let signature = try! signer.sign(message: message, privateKey: privateKey, type: .eip191) + return signature +} +``` + +## Subscribing to a new dapp + +To begin receiving notifications from a dapp, users must opt-in by subscribing. This subscription process grants permission for the dapp to send notifications to the user. These notifications can serve a variety of purposes, such as providing updates on the user's blockchain account activities or informing them about ongoing campaigns within the dapp. Upon initial subscription, clients will be automatically enrolled to receive all types of notifications as defined by the dapp at that moment. Users have the flexibility to modify their notification settings later, allowing them to tailor the types of alerts they receive according to their preferences. + +```swift +public func subscribe(appDomain: String, account: Account) async throws +``` + +`appDomain` - dapp domain fetched from WalletConnect explorer + +`account` - an account you want to associate a subscription with + +#### Combine event + +```swift +public var subscriptionsPublisher: AnyPublisher<[NotifySubscription], Never> +``` + +## Fetching active subscriptions + +To fetch the current list of subscriptions an account has, call **`getActiveSubscriptions()`**. + +Method will return an array of NotifySubscription objects that indicates actual subscriptions state + +```swift +public func getActiveSubscriptions(account: Account) -> [NotifySubscription] +``` + +`account` - subscriptions owner account + +## Fetching subscription’s notifications + +To fetch subscription’s notifications by calling **`getNotificationHistory()`**. + +Method will return an array of NotifyMessageRecord objects that indicates current notify messages state. This do not include old messages that aren't loaded yet. Useful for displaying initial notifications view state. For more info about pagination, check `fetchHistory` method. + +Use this method together with: + +- `messagesPublisher(topic: String)` +- `fetchHistory` + +```swift +public func getMessageHistory(topic: String) -> [NotifyMessageRecord] +``` + +`topic` - unique subscription's topic + +#### Combine events + +Publisher that send messages update event for specific topic only + +```swift +public func messagesPublisher(topic: String) -> AnyPublisher<[NotifyMessageRecord], Never> +``` + +Publisher that send event on every messages update (for all subscriptions) + +```swift +public var messagesPublisher: AnyPublisher<[NotifyMessageRecord], Never> +``` + +## Updating subscriptions notification settings + +Users can alter their notification settings to filter out unwanted alerts from a dapp. During this process, they review and select the types of notifications they wish to receive, based on the latest options provided by the dapp. + +```swift +public func update(topic: String, scope: Set) async throws +``` + +`topic` - topic of the subscription to update + +`scope` - The new space delimited list of scopes + +## Unsubscribe from a dapp + +To opt-out of receiving notifications from a dap, a user can decide to unsubscribe from dapp. + +```swift +try await Notify.instance.deleteSubscription(topic: String) +``` + +`topic` - subscription's topic + +## Account logout + +If an account is removed from the client or a user no longer wants to receive notifications for this account, you can logout the account from Notify API by calling **`unregister()`**. This will remove all subscriptions and messages for this account from the client’s storage. + +```swift +public func unregister(account: Account) async throws +``` + +`account` - account ot unregister + +## Fetch notification history (Pagination) + +Method that fetches notification history and saves it to SDK's database. When async method finishes execution, `messagesPublisher(topic: String)` will send the event with actual Notify messages for the specified topic. + +```swift +func fetchHistory(subscription: NotifySubscription, after: String?, limit: Int) async throws -> Bool +``` + +`subscription` - subscription for which notification history is requested +`after?` - id of last notification loaded. Recent notifications will be loaded if provided nil +`limit` - notifications to load count + +`Returns` - Returns True if there are still not fetched notifications + +## Apple Push Notification service setup + +To setup Apple Push Notification service please follow our [Push Notifications docs](../push). diff --git a/network/wallets/ios/notifications/push.mdx b/network/wallets/ios/notifications/push.mdx new file mode 100644 index 0000000..ba96488 --- /dev/null +++ b/network/wallets/ios/notifications/push.mdx @@ -0,0 +1,92 @@ +--- +title: Push Notifications +--- + +WalletKit provides the functionality for wallets to receive push notifications through Firebase Cloud Messaging (FCM) and Apple Push Notification Service (APNs) via the Push Server. This feature ensures that wallets are promptly notified of incoming signature requests. Each push notification contains the encrypted details of the signature request. Upon receiving the notification, it can be decrypted and presented to the developer, allowing for customization of the message according to their requirements. + +## Server setup + +For the push notifications to be forwarded to FCM or APNs, the [Push Server](https://docs.reown.com/advanced/push-server) will need to be configured with your FCM or APNs server API credentials. + +## App setup + +### Register the device token + +To enable a device for push notifications, it's essential to register the device token using `WalletKit.registerDeviceToken`. This token can be obtained from either FCM or APNS, depending on the platform used. + +In your AppDelegate, you need to register your device token for push notifications. To enable encrypted push notifications, set the `enableEncrypted` flag to `true`. + +```Swift +func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + Task(priority: .high) { + try await WalletKit.instance.register(deviceToken: deviceToken, enableEncrypted: true) + } +} +``` + +### Receiving push notifications + +After the device token is registered, the next step involves setting up the notification service specific to the platform being used. This service will decrypt the incoming requests and forward them to the developer for further processing and integration. + +When using encrypted push notifications via APNs, the payload will look like this: + +```json +{ + "aps": { + "content-available": 1, + "mutable-content": 1 + }, + "message": "String", // Encrypted payload + "topic": "String", // Subscription topic + "tag": "String" // Tag of the associated relay message +} +``` + +To decrypt a push notification, follow these steps: + +1. Instantiate [UNNotificationServiceExtension](https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension) + +2. Modify the content of newly delivered notifications. + Learn more about [modifying content in newly delivered notifications](https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications). + +3. Create a Shared [Keychain Group](https://developer.apple.com/documentation/security/keychain_services/keychain_items/sharing_access_to_keychain_items_among_a_collection_of_apps) + +Ensure you have a keychain group that is shared between your wallet application and the notification service. This is set in the app during the Networking Client configuration as shown below: + +```Swift +Networking.configure( + groupIdentifier: "group.com.walletconnect.sdk", + projectId: InputConfig.projectId, + socketFactory: DefaultSocketFactory() +) +``` + +4. Instantiate WalletKitDecryptionService + +Use the same group name inside your notification service extension. + +```Swift +override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.contentHandler = contentHandler + self.bestAttemptContent = request.content + + if let content = bestAttemptContent, + let topic = content.userInfo["topic"] as? String, + let ciphertext = content.userInfo["message"] as? String, + let tag = content.userInfo["tag"] as? UInt { + + if WalletKitDecryptionService.canHandle(tag: tag) { + let mutableContent = handleWalletKitNotification(content: content, topic: topic, tag: tag, ciphertext: ciphertext) + contentHandler(mutableContent) + } else if NotifyDecryptionService.canHandle(tag: tag) { + let mutableContent = handleNotifyNotification(content: content, topic: topic, ciphertext: ciphertext) + contentHandler(mutableContent) + } else { + let mutableContent = content.mutableCopy() as! UNMutableNotificationContent + mutableContent.title = "Error: unknown message tag" + } + } + } +``` + +`handleWalletKitNotification` and `handleNotifyNotification` methods can be found in our [Sample App](https://github.com/reown-com/reown-swift/blob/main/Example/PNDecryptionService/NotificationService.swift) \ No newline at end of file diff --git a/network/wallets/ios/one-click-auth.mdx b/network/wallets/ios/one-click-auth.mdx new file mode 100644 index 0000000..a503349 --- /dev/null +++ b/network/wallets/ios/one-click-auth.mdx @@ -0,0 +1,102 @@ +--- +title: One-click Auth +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem. + +![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/w3w/authenticatedSessions-light.png) + + + +## Handling Authentication Requests + +To handle incoming authentication requests, subscribe to the authenticateRequestPublisher. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```swift +WalletKit.instance.authenticateRequestPublisher + .receive(on: DispatchQueue.main) + .sink { result in + // Process the authentication request here. + // This involves displaying UI to the user. + } + .store(in: &subscriptions) // Assuming `subscriptions` is where you store your Combine subscriptions. +``` + +## Authentication Objects/Payloads + +To interact with authentication requests, first build authentication objects (AuthObject). These objects are crucial for approving authentication requests. This involves: + +- **Creating an Authentication Payload** - Generate an authentication payload that matches your application's supported chains and methods. +- **Formatting Authentication Messages** - Format the authentication message using the payload and the user's account. +- **Signing the Authentication Message** - Sign the formatted message to create a verifiable authentication object. + +Example Implementation: + +```swift +func buildAuthObjects(request: AuthenticationRequest, account: Account, privateKey: String) throws -> [AuthObject] { + let requestedChains = Set(request.payload.chains.compactMap { Blockchain($0) }) + let supportedChains: Set = [Blockchain("eip155:1")!, Blockchain("eip155:137")!, Blockchain("eip155:69")!] + let commonChains = requestedChains.intersection(supportedChains) + let supportedMethods = ["personal_sign", "eth_sendTransaction"] + + var authObjects = [AuthObject]() + for chain in commonChains { + let accountForChain = Account(blockchain: chain, address: account.address)! + let supportedAuthPayload = try WalletKit.instance.buildAuthPayload( + payload: request.payload, + supportedEVMChains: Array(commonChains), + supportedMethods: supportedMethods + ) + let formattedMessage = try WalletKit.instance.formatAuthMessage(payload: supportedAuthPayload, account: accountForChain) + let signature = // Assume `signMessage` is a function you've implemented to sign messages. + signMessage(message: formattedMessage, privateKey: privateKey) + + let authObject = try WalletKit.instance.buildSignedAuthObject( + authPayload: supportedAuthPayload, + signature: signature, + account: accountForChain + ) + authObjects.append(authObject) + } + return authObjects +} + +``` + +## Approving Authentication Requests + + +**Note** + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + +To approve an authentication request, construct AuthObject instances for each supported blockchain, sign the authentication messages, build AuthObjects and call approveSessionAuthenticate with the request ID and the authentication objects. + +```swift +let session = try await WalletKit.instance.approveSessionAuthenticate(requestId: requestId, auths: authObjects) +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method. + +```swift +try await WalletKit.instance.rejectSession(requestId: requestId) +``` + +## Testing One-click Auth + +You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/ios/resources.mdx b/network/wallets/ios/resources.mdx new file mode 100644 index 0000000..cb6ed48 --- /dev/null +++ b/network/wallets/ios/resources.mdx @@ -0,0 +1,28 @@ +--- +title: Resources +--- + +Valuable assets for developers and users interested in integrating Wallet SDK into their applications. + +- [Awesome WalletConnect](https://github.com/WalletConnect/awesome-walletconnect) - Community-curated collection of WalletConnect-enabled wallets, libraries, and tools. +- [AppKit Laboratory](https://appkit-lab.reown.com/) - A place to test your wallet integrations against various setups of AppKit. +- [Wallet SDK Swift GitHub](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/web3wallet) - Wallet SDK Swift GitHub repository. + +### Wallet Resources + +To check more in details go and visit our [Wallet SDK Swift implementation app](https://github.com/reown-com/reown-swift/tree/main/Example/WalletApp). Sample Wallet and Dapp sample apps can be found under the Example directory in [Swift's V2 repository](https://github.com/reown-com/reown-swift/tree/main/Example) + +If you need to test your app's integration, you can use one of our following demo dapps. + +**Sign** + +- [React dApp (with standalone client) - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) ([Demo](https://react-app.walletconnect.com/)) + +### Dapp Resources + +Sample Dapp can be found under the Example directory in [Swift's V2 repository](https://github.com/reown-com/reown-swift/tree/main/Example) + +You can test your integration against Swift Sample Wallet that is included in the same repo or use the following JS React Wallet: + +- [React Wallet Ethers - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/wallets/react-wallet-v2) ([Demo](https://react-wallet.walletconnect.com/)) + diff --git a/network/wallets/ios/usage.mdx b/network/wallets/ios/usage.mdx new file mode 100644 index 0000000..5af6f24 --- /dev/null +++ b/network/wallets/ios/usage.mdx @@ -0,0 +1,442 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section. + +**[Initialization](#initialization)**: Creating a new WalletKit instance and initializing it with a projectId from [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +**Session**: Connection between a dapp and a wallet. + +- [Namespace Builder](#namespace-builder): + Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object +- [Session Approval](#session-approval): + Approving a session sent from a dapp +- [Session Rejection](#session-rejection): + Rejecting a session sent from a dapp +- [Responding to Session Requests](#responding-to-session-requests): + Responding to session requests sent from a dapp +- [Updating a Session](#updating-a-session): + Updating a session sent between a dapp and wallet +- [Extending a Session](#extending-a-session): + Extending a session between a dapp and wallet +- [Session Disconnect](#session-disconnect): + Disconnecting a session between a dapp and wallet +- [Register Device Token](#register-device-token) + Enabling Wallet Push Notifications by registering a device token. +- [Subscribe for WalletKit Publishers](#subscribe-for-walletkit-publishers) + Publishers available to subscribe to for WalletKit + + + +## Initialization + +Confirm you have configured the [Network Client](https://docs.reown.com/advanced/api/core/relay) first. + +Starting from WalletConnect SDK version 1.9.5, the `redirect` field in the `AppMetadata` object is mandatory. Ensure that the provided value matches your app's URL scheme to prevent redirection-related issues. + +Once you're done, in order to initialize a client just call a `configure` method from the WalletKit instance wrapper + +```swift +let telemetryEnabled = true; +let metadata = AppMetadata( + name: "Example Wallet", + description: "Wallet description", + url: "example.wallet", + icons: ["https://avatars.githubusercontent.com/u/37784886"], + redirect: AppMetadata.Redirect(native: "example://", universal: nil) +) + +WalletKit.configure( + metadata: metadata, + crypto: DefaultCryptoProvider(), + // Used for the Push: "echo.walletconnect.com" will be used by default if not provided + pushHost: "echo.walletconnect.com", + // Used for the Push: "APNSEnvironment.production" will be used by default if not provided + environment: .production, + telemetryEnabled: telemetryEnabled +) +``` + +In order to allow users to receive push notifications you have to communicate with Apple Push Notification service and receive unique device token. Register that token with following method: + +```swift +try await WalletKit.instance.register(deviceToken: deviceToken) +``` + +The telemetry feature aims to enhance the reliability and observability of connection flows between decentralized applications (dApps) and wallets. It focuses solely on collecting data related to code execution and error codes, without tracking any sensitive user information such as amounts, accounts, etc. + +It provides a comprehensive tracing system for three key use cases: + +- Subscribing to a Pairing Topic +- Approving a Session +- Approving an Authenticated Session + +Each execution trace consists of: + +- Trace Events: Collected to verify the proper execution of code. +- Error Events: Captured when errors occur during the trace, halting the execution trace. + +When an error event is encountered, it is stored locally within the SDK along with all preceding trace events. +These stored events are then transmitted to the server whenever the SDK is initialized. + +Error event tracing is enabled by default. + +**Telemetry Enabled (telemetryEnabled = true):** + +- The SDK stores events and sends them to the server. + +**Telemetry Disabled (telemetryEnabled = false):** + +- The SDK stops storing new events and deletes all unsent events from local storage upon the next initialization. + +Important Note: Since the SDK only stores abstract trace and error data, user identification is not possible. + +Example of the error events: + +```json +[ + { + "eventId": "69e53f11-fd4b-4efc-8d36-1f60a9ac8207", + "bundleId": "com.wallet.example", + "timestamp": 1689611327943, + "props": { + "event": "ERROR", + "type": "pairing_already_exists", + "properties": { + "topic": "topic1", + "trace": [ + "pairing_started", + "pairing_uri_validation_success", + "pairing_uri_not_expired", + "existing_pairing", + "pairing_not_expired", + "pairing_not_expired" + ] + } + } + }, + { + "eventId": "69e53f11-fd4b-4efc-8d36-2321312fds", + "bundleId": "com.wallet.example", + "timestamp": 16896113234323, + "props": { + "event": "ERROR", + "type": "session_approve_namespace_validation_failure", + "properties": { + "topic": "topic2", + "trace": ["session_approve_started", "proposal_not_expired"] + } + } + } +] +``` + +## Session + +A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires. + +### Namespace Builder + +`AutoNamespaces` is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns ready-to-use `SessionNamespace` object. + +```swift +public static func build( + sessionProposal: Session.Proposal, + chains: [Blockchain], + methods: [String], + events: [String], + accounts: [Account] +) throws -> [String: SessionNamespace] +``` + +Example usage + +```swift +do { + sessionNamespaces = try AutoNamespaces.build( + sessionProposal: proposal, + chains: [Blockchain("eip155:1")!, Blockchain("eip155:137")!], + methods: ["eth_sendTransaction", "personal_sign"], + events: ["accountsChanged", "chainChanged"], + accounts: [ + Account(blockchain: Blockchain("eip155:1")!, address: "0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")!, + Account(blockchain: Blockchain("eip155:137")!, address: "0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! + ] + ) +} catch let error as AutoNamespacesError { + // reject session proposal if AutoNamespace build function threw + try await reject(proposal: proposal, reason: RejectionReason(from: error)) + return +} +// approve session with sessionNamespaces +try await WalletKit.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + +``` + +### EVM methods & events + +In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events: + +```ts +{ + //... + methods: [ + "eth_accounts", + "eth_requestAccounts", + "eth_sendRawTransaction", + "eth_sign", + "eth_signTransaction", + "eth_signTypedData", + "eth_signTypedData_v3", + "eth_signTypedData_v4", + "eth_sendTransaction", + "personal_sign", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + "wallet_getPermissions", + "wallet_requestPermissions", + "wallet_registerOnboarding", + "wallet_watchAsset", + "wallet_scanQRCode", + "wallet_sendCalls", + "wallet_getCallsStatus", + "wallet_showCallsStatus", + "wallet_getCapabilities", + ], + events: [ + "chainChanged", + "accountsChanged", + "message", + "disconnect", + "connect", + ] +} +``` + +### Session Approval + +```swift + WalletKit.instance.approve( + proposalId: "proposal_id", + namespaces: sessionNamespaces +) +``` + +When session is successfully approved `sessionsPublishers` will publish a `Session` + +```swift +WalletKit.instance.sessionsPublishers + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + self?.reloadSessions() + }.store(in: &publishers) +``` + +`Session` object represents an active session connection with a dapp. It contains dapp’s metadata (that you may want to use for displaying an active session to the user), namespaces, and expiry date. There is also a topic property that you will use for linking requests with related sessions. + +You can always query settled sessions from the client later with: + +```swift +WalletKit.instance.getSessions() +``` + +#### Connect Clients + +Your Wallet should allow users to scan a QR code generated by dapps. You are responsible for implementing it on your own. +For testing, you can use our test dapp at: https://react-app.walletconnect.com/, which is v2 protocol compliant. +Once you derive a URI from the QR code call `pair` method: + +```swift +try await WalletKit.instance.pair(uri: uri) +``` + +if everything goes well, you should handle following event: + +```swift +WalletKit.instance.sessionProposalPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] session in + self?.verifyDapp(session.context) + self?.showSessionProposal(session.proposal) + }.store(in: &publishers) +``` + +Session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Handshake procedure is defined by [CAIP-25](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md). +`Session.Proposal` object conveys set of required and optional `ProposalNamespaces` that contains blockchains methods and events. Dapp requests with methods and wallet will emit events defined in namespaces. + +`VerifyContext` provides a domain verification information about `Session.Proposal` and `Request`. It consists of origin of a Dapp from where the request has been sent, validation enum that says whether origin is **unknown**, **valid** or **invalid** and verify URL server. + +To enable or disable verification find the **Verify SDK** toggle in your project [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +```swift +public struct VerifyContext: Equatable, Hashable { + public enum ValidationStatus { + case unknown + case valid + case invalid + } + + public let origin: String? + public let validation: ValidationStatus + public let verifyUrl: String +} +``` + +The user will either approve the session proposal (with session namespaces) or reject it. Session namespaces must at least contain requested methods, events and accounts associated with proposed blockchains. + +Accounts must be provided according to [CAIP10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) specification and be prefixed with a chain identifier. chain_id + : + account_address. You can find more on blockchain identifiers in [CAIP2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md). Our `Account` type meets the criteria. + +``` +let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! +``` + +Accounts sent in session approval must at least match all requested blockchains. + +Example proposal namespaces request: + +```json +{ + "eip155": { + "chains": ["eip155:137", "eip155:1"], + "methods": ["eth_sign"], + "events": ["accountsChanged"] + }, + "cosmos": { + "chains": ["cosmos:cosmoshub-4"], + "methods": ["cosmos_signDirect"], + "events": ["someCosmosEvent"] + } +} +``` + +Example session namespaces response: + +```json +{ + "eip155": { + "accounts": [ + "eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb", + "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb" + ], + "methods": ["eth_sign"], + "events": ["accountsChanged"] + }, + "cosmos": { + "accounts": [ + "cosmos:cosmoshub-4:cosmos1t2uflqwqe0fsj0shcfkrvpukewcw40yjj6hdc0" + ], + "methods": ["cosmos_signDirect", "personal_sign"], + "events": ["someCosmosEvent", "proofFinalized"] + } +} +``` + +#### Track Sessions + +When your `WalletKit` instance receives requests from a peer it will publish a related event. Set a subscription to handle them. + +To track sessions subscribe to `sessionsPublisher` publisher + +```swift +WalletKit.instance.sessionsPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] sessions in + // Reload UI + }.store(in: &publishers) +``` + +### Session Rejection + +```swift +try await WalletKit.instance.reject(requestId: request.id) +``` + +### Responding to Session requests + +After the session is established, a dapp will request your wallet's users to sign a transaction or a message. Requests will be delivered by the following publisher. + +```swift +WalletKit.instance.sessionRequestPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] session in + self?.verifyDapp(session.context) + self?.showSessionRequest(session.request) + }.store(in: &publishers) +``` + +When a wallet receives a session request, you probably want to show it to the user. It’s method will be in scope of session namespaces. And it’s params are represented by `AnyCodable` type. An expected object can be derived as follows: + +```swift +if sessionRequest.method == "personal_sign" { + let params = try! sessionRequest.params.get([String].self) +} else if method == "eth_signTypedData" { + let params = try! sessionRequest.params.get([String].self) +} else if method == "eth_sendTransaction" { + let params = try! sessionRequest.params.get([EthereumTransaction].self) +} +``` + +Now, your wallet (as it owns your user’s private keys) is responsible for signing the transaction. After doing it, you can send a response to a dapp. + +```swift +let response: AnyCodable = sign(request: sessionRequest) // Implement your signing method +try await WalletKit.instance.respond(topic: request.topic, requestId: request.id, response: .response(response)) +``` + +### Updating a Session + +If you want to update user session's chains, accounts, methods or events you can use session update method. + +```swift +try await WalletKit.instance.update(topic: session.topic, namespaces: newNamespaces) +``` + +### Extending a Session + +By default, session lifetime is set for 7 days and after that time user's session will expire. But if you consider that a session should be extended you can call: + +```swift +try await WalletKit.instance.extend(topic: session.topic) +``` + +Above method will extend a user's session to a week. + +### Session Disconnect + +For good user experience your wallet should allow users to disconnect unwanted sessions. In order to terminate a session use `disconnect` method. + +```swift +try await WalletKit.instance.disconnect(topic: session.topic) +``` + +### Subscribe for WalletKit Publishers + +The following publishers are available to subscribe: + +```swift +public var sessionProposalPublisher: AnyPublisher<(proposal: Session.Proposal, context: VerifyContext?), Never> +public var sessionRequestPublisher: AnyPublisher<(request: Request, context: VerifyContext?), Never> +public var authRequestPublisher: AnyPublisher<(request: AuthRequest, context: VerifyContext?), Never> +public var sessionPublisher: AnyPublisher<[Session], Never> +public var socketConnectionStatusPublisher: AnyPublisher +public var sessionSettlePublisher: AnyPublisher +public var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> +public var sessionResponsePublisher: AnyPublisher +``` + +### Register Device Token + +To register a wallet to receive WalletConnect push notifications, call `register` method and pass the device token received from the `didRegisterForRemoteNotificationsWithDeviceToken` method in the `AppDelegate`. + +```swift + +WalletKit.instance.register(deviceToken: deviceToken, enableEncrypted: true) + +``` diff --git a/network/wallets/ios/verify.mdx b/network/wallets/ios/verify.mdx new file mode 100644 index 0000000..672c8b7 --- /dev/null +++ b/network/wallets/ios/verify.mdx @@ -0,0 +1,50 @@ +--- +title: Verify API +--- + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. +Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect's domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +These are: + +![Verify Banner](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/verify-banner.png) + + +## Disclaimer + +Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + +## Domain risk detection + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +- Domain match: The domain linked to this request has been verified as this application's domain. + - This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +- Unverified: The domain sending the request cannot be verified. + - This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +- Mismatch: The application's domain doesn't match the sender of this request. + - This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +- Threat: This domain is flagged as malicious and potentially harmful. + - This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Implementation + +VerifyContext provides a domain verification information about Session.Proposal and Request and is relevant to the `verifyDapp` function. + +It consists of origin of an app from where the request has been sent, validation enum that says whether origin is unknown, valid or invalid and verify URL server. + +```swift +public struct VerifyContext: Equatable, Hashable { + public enum ValidationStatus { + case unknown + case valid + case invalid + } + + public let origin: String? + public let validation: ValidationStatus + public let verifyUrl: String +} +``` diff --git a/network/wallets/more/from-web3wallet-android.mdx b/network/wallets/more/from-web3wallet-android.mdx new file mode 100644 index 0000000..b81ef18 --- /dev/null +++ b/network/wallets/more/from-web3wallet-android.mdx @@ -0,0 +1,107 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for Android +sidebarTitle: WalletKit - Android +--- + +## Upgrade to WalletKit + +This upgrade guide helps developers transition from using the Web3Wallet library to the WalletKit within reown-kotlin. The guide involves updating imports, modifying class references and updating artefacts dependencies. Follow these steps to ensure a smooth migration. + +### Step 1. Update the Repository Dependencies + +The Web3Wallet library has been deprecated and moved to a new repository under the reown-com organization. Update your dependencies to use WalletKit: + +```swift +/* highlight-delete-start */ +- dependencies { +- implementation(platform("com.walletconnect:android-bom:{BOM version}")) +- implementation("com.walletconnect:android-core") +- implementation("com.walletconnect:web3wallet") +- } +/* highlight-delete-end */ +/* highlight-add-start */ ++ dependencies { ++ implementation(platform("com.reown:android-bom:{BOM version}")) ++ implementation("com.reown:android-core") ++ implementation("com.reown:walletkit") ++ } +/* highlight-add-end */ +``` + +### Step 2. Update Imports in Your Code + +All references to Web3Wallet in your import statements should be updated to use WalletKit. + +```swift +/* highlight-delete-start */ +- import com.walletconnect.android.* +- import com.walletconnect.web3.wallet.* +/* highlight-delete-end */ +/* highlight-add-start */ ++ import com.reown.android.* ++ import com.reown.walletkit.* +/* highlight-add-end */ +``` + + +### Step 3. Update Class Name + +The singleton instance for Web3Wallet has been replaced with WalletKit. Update all instances where Web3Wallet is used with WalletKit. + +```swift +/* highlight-delete-start */ +- Web3Wallet.initialize(Wallet.Params.Init(core = CoreClient), onSuccess, onError) +- Web3Wallet.approveSession(approveProposal, onSuccess, onError) +/* highlight-delete-end */ +/* highlight-add-start */ ++ WalletKit.initialize(Wallet.Params.Init(core = CoreClient), onSuccess, onError) ++ WalletKit.approveSession(approveProposal, onSuccess, onError) +/* highlight-add-end */ +``` + +### Step 4. Update ProGuard file rules + +If you have ProGuard rules defined remember to update + +```swift +/* highlight-delete-start */ +- -keep class com.walletconnect.web3.wallet.client.Wallet$Model { *; } +- -keep class com.walletconnect.web3.wallet.client.Wallet { *; } +/* highlight-delete-end */ +/* highlight-add-start */ ++ -keep class com.reown.walletkit.client.Wallet$Model { *; } ++ -keep class com.reown.walletkit.client.Wallet { *; } +/* highlight-add-end */ +``` + +### Step 5. Test Your Changes + +After updating all references to Web3Wallet to use WalletKit, thoroughly test your application to ensure that all functionalities work as expected. + +## Pairing Expiry + +Currently, Dapps create a new pairing whenever the user selects the **"Connect Wallet"** button, instead of reusing existing pairings. Although pairings were not intended to be reused, they were being persisted for 30 days, causing unnecessary resource usage for both Dapps and wallet clients, including redundant socket connections. + +This led to an accumulation of stale pairings in wallets, resulting in degraded efficiency and increased resource consumption. To address this issue, we have introduced changes to how pairings are managed to ensure more efficient connection handling. + +Pairings were never intended to be listed in the wallet, and wallets should only display active sessions to users. + +## WebSocket Connection Handling + +We've optimized the WebSocket connection management to improve performance and resource utilization. The SDK will now establish a WebSocket connection only when there's an explicit intention to send a request or subscribe to a topic. If none of these conditions are met, the WebSocket connection will remain closed by default. + +### What's Changed? +Previous Behavior: The SDK automatically initiated a WebSocket connection upon startup, regardless of active sessions or pending actions. + +New Behavior: The SDK delays establishing a WebSocket connection until it's necessary based on the app's activities. + +### Why This Change? +This adjustment reduces unnecessary network traffic and conserves device resources, leading to better performance and battery life, especially important for mobile applications. + +### Impact on Your Application +Disconnected State on Launch: Apps without active sessions at launch will start with the WebSocket in a disconnected state. +UI Elements Depending on WebSocket: Buttons or features that rely on an active WebSocket connection may not function until the connection is established. + +### Steps for Migration + +Wallets are no longer expected to handle pairing-related methods. If your wallet has been listing pairings, please replace this with listing active sessions instead. \ No newline at end of file diff --git a/network/wallets/more/from-web3wallet-flutter.mdx b/network/wallets/more/from-web3wallet-flutter.mdx new file mode 100644 index 0000000..e1f8331 --- /dev/null +++ b/network/wallets/more/from-web3wallet-flutter.mdx @@ -0,0 +1,79 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for Flutter +sidebarTitle: WalletKit - Flutter +--- + +## Upgrade to WalletKit + +This document outlines the steps to migrate from the old `walletconnect_flutter_v2` package to the new `reown_walletkit` packages in your Flutter project. + +### Step 1. Replace the corresponding dependency + +Remove `walletconnect_flutter_v2` dependency from pubspec.yaml and add `reown_walletkit`: + +```dart +/* highlight-delete-start */ +walletconnect_flutter_v2: ^X.Y.Z +/* highlight-delete-end */ +/* highlight-add-start */ +reown_walletkit: ^1.0.0 +/* highlight-add-end */ +``` + +Run `flutter clean && flutter pub get` after replacing the packages + +Then replace the imports... + +```dart +/* highlight-delete-start */ +import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +/* highlight-delete-end */ +/* highlight-add-start */ +import 'package:reown_walletkit/reown_walletkit.dart'; +/* highlight-add-end */ +``` + +### Step 2. Update main classes + + + +### Step 3. Update error definitions + +```tsx +/* highlight-delete-start */ +Errors.getSdkError(Errors.USER_REJECTED); +/* highlight-delete-end */ +/* highlight-add-start */ +Errors.getSdkError(Errors.USER_REJECTED).toSignError(); +/* highlight-add-end */ +``` + +### Step 5. Update any exception type + +
+ +### Final notes + +- Ensure that you have updated all relevant configurations and imports in your project to reflect the changes from Web3Wallet to WalletKit. +- Test your application thoroughly to ensure that the migration has been successful and that all functionality is working as expected. +- Check our [WalletKit example for Flutter](https://github.com/reown-com/reown_flutter/tree/master/packages/reown_walletkit/example/) to compare with your implementation in case you are having issues diff --git a/network/wallets/more/from-web3wallet-ios.mdx b/network/wallets/more/from-web3wallet-ios.mdx new file mode 100644 index 0000000..4bfaab1 --- /dev/null +++ b/network/wallets/more/from-web3wallet-ios.mdx @@ -0,0 +1,114 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for iOS +sidebarTitle: WalletKit - iOS +--- + + +## Upgrade to WalletKit + +This upgrade guide helps developers transition from using the Web3Wallet library to the WalletKit within reown-swift. The guide involves updating import statements, modifying instance references, changing configuration methods, and updating repository URLs for CocoaPods and Swift Package Manager (SPM). + +### Step 1. Update the Repository URL + +The Web3Wallet library has been moved to a new repository under the reown-com organization. If you are using Swift Package Manager (SPM) to manage dependencies, update your Package.swift file to point to the new repository: + +```swift +/* highlight-delete-start */ +- .package(url: "https://github.com/WalletConnect/WalletConnectSwiftV2", from: "1.0.0"), +/* highlight-delete-end */ +/* highlight-add-start */ ++ .package(url: "https://github.com/reown-com/reown-swift", from: "1.0.0"), +/* highlight-add-end */ +``` + +### Step 2. Update Imports in Your Code + +All references to Web3Wallet in your import statements should be updated to use WalletKit. + +```swift +/* highlight-delete-start */ +- import Web3Wallet +/* highlight-delete-end */ +/* highlight-add-start */ ++ import WalletKit +/* highlight-add-end */ +``` + +### Step 3. Update Instance Access and Method Calls + +The singleton instance access for Web3Wallet has been replaced with WalletKit. Update all instances where Web3Wallet.instance is used to WalletKit.instance. + +```swift +/* highlight-delete-start */ +- Web3Wallet.instance.authRequestPublisher.sink { (id, result) in +- // Your code here +- } +/* highlight-delete-end */ +/* highlight-add-start */ ++ WalletKit.instance.authRequestPublisher.sink { (id, result) in ++ // Your code here ++ } +/* highlight-add-end */ +``` + +### Step 4. Update Configuration Method + +The configure method has been updated to reflect the new branding. Replace calls to Web3Wallet.configure with WalletKit.configure. + +```swift +/* highlight-delete-start */ +- Web3Wallet.configure( +- ... +- ) +/* highlight-delete-end */ +/* highlight-add-start */ ++ WalletKit.configure( ++ ... ++ ) +/* highlight-add-end */ +``` + +### Step 5. Update CocoaPods Podspec + +If you are using CocoaPods to manage dependencies, update your Podfile to use the new library name. + +```swift +/* highlight-delete-start */ +- pod 'Web3Wallet', '~> 1.0' +/* highlight-delete-end */ +/* highlight-add-start */ ++ pod 'WalletKit', '~> 1.0' +/* highlight-add-end */ +``` + +### Step 6. Test Your Changes + +After updating all references to Web3Wallet to use WalletKit, thoroughly test your application to ensure that all functionalities work as expected. + +## Pairing Expiry + +Currently, Dapps create a new pairing whenever the user selects the **"Connect Wallet"** button, instead of reusing existing pairings. Although pairings were not intended to be reused, they were being persisted for 30 days, causing unnecessary resource usage for both Dapps and wallet clients, including redundant socket connections. + +This led to an accumulation of stale pairings in wallets, resulting in degraded efficiency and increased resource consumption. To address this issue, we have introduced changes to how pairings are managed to ensure more efficient connection handling. + +Pairings were never intended to be listed in the wallet, and wallets should only display active sessions to users. + +## WebSocket Connection Handling + +We've optimized the WebSocket connection management to improve performance and resource utilization. The SDK will now establish a WebSocket connection only when there's an explicit intention to send a request or subscribe to a topic. If none of these conditions are met, the WebSocket connection will remain closed by default. + +### What's Changed? +Previous Behavior: The SDK automatically initiated a WebSocket connection upon startup, regardless of active sessions or pending actions. + +New Behavior: The SDK delays establishing a WebSocket connection until it's necessary based on the app's activities. + +### Why This Change? +This adjustment reduces unnecessary network traffic and conserves device resources, leading to better performance and battery life, especially important for mobile applications. + +### Impact on Your Application +Disconnected State on Launch: Apps without active sessions at launch will start with the WebSocket in a disconnected state. +UI Elements Depending on WebSocket: Buttons or features that rely on an active WebSocket connection may not function until the connection is established. + +### Steps for Migration + +Wallets are no longer expected to handle pairing-related methods. If your wallet has been listing pairings, please replace this with listing active sessions instead. \ No newline at end of file diff --git a/network/wallets/more/from-web3wallet-react-native.mdx b/network/wallets/more/from-web3wallet-react-native.mdx new file mode 100644 index 0000000..7aa021b --- /dev/null +++ b/network/wallets/more/from-web3wallet-react-native.mdx @@ -0,0 +1,66 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for React Native +sidebarTitle: WalletKit - React Native +--- + + +## Upgrade to WalletKit + +This document outlines the steps to migrate from the old `@walletconnect/web3wallet` package to the new `@reown/walletkit` packages in your project. + +### Step 1. Update your package.json + +Replace your existing `@walletconnect/web3wallet` dependency with `@reown/walletkit`: + +```json +/* highlight-delete-start */ +"@walletconnect/web3wallet": "^x.y.z" +/* highlight-delete-end */ +/* highlight-add-start */ +"@reown/walletkit": "^1.0.0" +/* highlight-add-end */ +``` + +### Step 2. Install `@reown/walletkit` + +Run `npm install` (or your preferred package manager command) to install the new package. + +### Step 3. Update your imports + +Replace the imports in your project: + +```javascript +/* highlight-delete-start */ +import { Web3Wallet } from "@walletconnect/web3wallet"; +/* highlight-delete-end */ +/* highlight-add-start */ +import { WalletKit } from "@reown/walletkit"; +/* highlight-add-end */ +``` +and your initialization to use the new package: +```javascript +/* highlight-delete-start */ +await Web3Wallet.init() +/* highlight-delete-end */ +/* highlight-add-start */ +await WalletKit.init() +/* highlight-add-end */ +``` + + +If you're using additional imports from `@walletconnect/web3wallet`, you can replace them with their corresponding version from `@reown/walletkit` such as: +```javascript +/* highlight-delete-start */ +import { IWeb3Wallet } from "@walletconnect/web3wallet"; +/* highlight-delete-end */ +/* highlight-add-start */ +import { IWalletKit } from "@reown/walletkit"; +/* highlight-add-end */ +``` + + +## You're all set! + +### Final Notes ++ public API documentation can be found [here](/network/wallets/web/usage) ++ `auth_request` is deprecated in favor of `session_authenticate`. Docs can be found [here](/network/wallets/web/one-click-auth) diff --git a/network/wallets/more/from-web3wallet-to-reown.mdx b/network/wallets/more/from-web3wallet-to-reown.mdx new file mode 100644 index 0000000..2ab5f97 --- /dev/null +++ b/network/wallets/more/from-web3wallet-to-reown.mdx @@ -0,0 +1,32 @@ +--- +title: Upgrade from Web3Wallet to Reown WalletKit +sidebarTitle: Overview +--- + +## Upgrade Platform list + + + + Upgrade to WalletKit in Web. + + + + Upgrade to WalletKit in React Native. + + + + Upgrade to WalletKit in Flutter. + + + + Upgrade to WalletKit in Android. + + + + Migrate to WalletKit in iOS. + + + + Upgrade to WalletKit in .NET. + + diff --git a/network/wallets/more/from-web3wallet-unity.mdx b/network/wallets/more/from-web3wallet-unity.mdx new file mode 100644 index 0000000..6a1575d --- /dev/null +++ b/network/wallets/more/from-web3wallet-unity.mdx @@ -0,0 +1,98 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for .NET +sidebarTitle: WalletKit - Unity +--- + +## Upgrade to WalletKit + +This document outlines the steps to migrate from the old `WalletConnect.Web3Wallet` package to the new `Reown.WalletKit` package in your .NET project. + +### Step 1. Replace the corresponding dependency in your project file + +```xml + + + + + +/* highlight-delete-start */ + +/* highlight-delete-end */ +/* highlight-add-start */ + +/* highlight-add-end */ + + + +``` + +Alternatively, you can use the .NET CLI: + +```bash +# Remove the old package +dotnet remove package WalletConnect.Web3Wallet + +# Add the new package +dotnet add package Reown.WalletKit +``` + +### Step 2. Update references to the namespaces + +
+ +### Step 3. Update references to the classes + +
+ +### Final notes + +- Ensure that you have updated all relevant configurations and imports in your project to reflect the changes from Web3Wallet to WalletKit. +- Test your application thoroughly to ensure that the migration has been successful and that all functionality is working as expected. diff --git a/network/wallets/more/from-web3wallet-web.mdx b/network/wallets/more/from-web3wallet-web.mdx new file mode 100644 index 0000000..1916f34 --- /dev/null +++ b/network/wallets/more/from-web3wallet-web.mdx @@ -0,0 +1,65 @@ +--- +title: Upgrade from Web3Wallet to WalletKit for Web +sidebarTitle: WalletKit - Web +--- + +## Upgrade to WalletKit + +This document outlines the steps to migrate from the old `@walletconnect/web3wallet` package to the new `@reown/walletkit` packages in your project. + +### Step 1. Update your package.json + +Replace your existing `@walletconnect/web3wallet` dependency with `@reown/walletkit`: + +```json +/* highlight-delete-start */ +"@walletconnect/web3wallet": "^x.y.z" +/* highlight-delete-end */ +/* highlight-add-start */ +"@reown/walletkit": "^1.0.0" +/* highlight-add-end */ +``` + +### Step 2. Install `@reown/walletkit` + +Run `npm install` (or your preferred package manager command) to install the new package. + +### Step 3. Update your imports + +Replace the imports in your project: + +```javascript +/* highlight-delete-start */ +import { Web3Wallet } from "@walletconnect/web3wallet"; +/* highlight-delete-end */ +/* highlight-add-start */ +import { WalletKit } from "@reown/walletkit"; +/* highlight-add-end */ +``` +and your initialization to use the new package: +```javascript +/* highlight-delete-start */ +await Web3Wallet.init() +/* highlight-delete-end */ +/* highlight-add-start */ +await WalletKit.init() +/* highlight-add-end */ +``` + + +If you're using additional imports from `@walletconnect/web3wallet`, you can replace them with their corresponding version from `@reown/walletkit` such as: +```javascript +/* highlight-delete-start */ +import { IWeb3Wallet } from "@walletconnect/web3wallet"; +/* highlight-delete-end */ +/* highlight-add-start */ +import { IWalletKit } from "@reown/walletkit"; +/* highlight-add-end */ +``` + + +## You're all set! + +### Final Notes ++ public API documentation can be found [here](/network/wallets/web/usage) ++ `auth_request` is deprecated in favor of `session_authenticate`. Docs can be found [here](/network/wallets/web/one-click-auth) diff --git a/network/wallets/more/staying-up-to-date.mdx b/network/wallets/more/staying-up-to-date.mdx new file mode 100644 index 0000000..75a4bd5 --- /dev/null +++ b/network/wallets/more/staying-up-to-date.mdx @@ -0,0 +1,41 @@ +--- +title: Staying up to date +--- + +## Why Should You Keep WalletKit Updated? + +Keeping your WalletKit SDK updated to the latest version is crucial for maintaining optimal performance, security, and compatibility with the evolving Web3 ecosystem. Regular updates ensure: + +* **Security patches** - Protection against newly discovered vulnerabilities +* **Bug fixes** - Resolution of known issues and improved stability +* **New features** - Access to the latest WalletConnect protocol enhancements +* **Protocol compatibility** - Seamless interaction with updated dApps and wallets +* **Performance improvements** - Optimizations for better user experience + +## Latest Releases by Platform + +Stay current with the latest WalletKit releases for your development platform: + +### Kotlin (Android) + +Check the latest Kotlin releases for Android development: + +* [WalletConnect Kotlin Releases](https://github.com/reown-com/reown-kotlin/releases) + +### Swift (iOS) + +Stay updated with the latest Swift releases for iOS development: + +* [WalletConnect Swift Releases](https://github.com/reown-com/reown-swift/releases) + +### JavaScript / React Native + +Monitor JavaScript and React Native package updates: + +* [WalletConnect WalletKit JS Releases](https://github.com/reown-com/reown-walletkit-js/releases) + +### Flutter + +Check the latest Flutter releases for Flutter development: + +* [WalletConnect WalletKit Flutter Releases](https://pub.dev/packages/reown_walletkit) diff --git a/network/wallets/overview.mdx b/network/wallets/overview.mdx new file mode 100644 index 0000000..2d5e457 --- /dev/null +++ b/network/wallets/overview.mdx @@ -0,0 +1,63 @@ +--- +title: WalletConnect Wallet SDK +sidebarTitle: Overview +--- + +**Wallet SDK** is WalletConnect's modular SDK for integrating secure, multichain, policy-aligned wallet access directly into your infrastructure. Enable your wallets users to securely connect to any app, powered by the WalletConnect Network + +It’s designed for apps, institutions, and custodians that need full control over key management, signing, and access without compromising UX or compliance. + +## Quickstart + + + + Get started with Wallet SDK in Android. + + + + Get started with Wallet SDK in iOS. + + + + Get started with Wallet SDK in React Native. + + + + Get started with Wallet SDK in Flutter. + + + + Get started with Wallet SDK in Web. + + + + Get started with Wallet SDK in .NET. + + + +## Features + + + ![Wallet SDK banner](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/walletkit.png) + + +Some of the key features of Wallet SDK include: + +* **Sign API**: Allows dapps to request that the user sign a transaction or message. +* **Auth API**: Allows dapps to verify wallet address ownership through a single signature request, realizing login in one action. +* **Chain agnostic**: Wallet SDK is designed to work with any blockchain, so you can easily support multiple chains without having to write separate integration code. + +## Use Cases + +* Custom wallet infrastructure. +* Governance flows with onchain or offchain execution. +* Secure DeFi access from custody-controlled environments. +* Seamless cross-chain policy enforcement. +* In-app and in-wallet payments +* Secure in-app signature workflows. +* Access to 65,000+ onchain apps. +* Chain Agnostic by design. +* Fast, frictionless integration. +* Transparent and open source. +* Battle-tested and audit-proven security. +* No dropped connections, no interruptions. diff --git a/network/wallets/react-native/best-practices.mdx b/network/wallets/react-native/best-practices.mdx new file mode 100644 index 0000000..b6dcf62 --- /dev/null +++ b/network/wallets/react-native/best-practices.mdx @@ -0,0 +1,198 @@ +--- +title: Best Practices +--- + +The purpose of this guide is to show the best practices in regards of the WalletKit client usage. The goal is to provide the best user experience that just works in every circumstances. + + +In order to ensure the best user experience and flawless connection flow, please make sure that WalletKit is initialized immediately after your app launch, especially if launched via a WalletConnect Deep Link. It guarantees that websocket connection is opened immediately and all requests are received by your wallet + + +## Pairing + +A pairing is a connection between a wallet and a dapp that has fixed permissions to only allow a dapp to propose a session through it. Dapp can propose infinite number of sessions on one pairing. Wallet must use a pair method from the WalletKit client to pair with dapp. + +```typescript +const uri = 'xxx'; // pairing uri +try { + await walletKit.pair({ uri }); +} catch (error) { + // some error happens while pairing - check Expected errors section +} +``` + +### Pairing Expiry + +A pairing expiry event is triggered whenever a pairing is expired. The expiry for inactive pairing is 5 mins, whereas for active pairing is 30 days. A pairing becomes active when a session proposal is received and user successfully approves it. This event helps to know when given pairing expires and update UI accordingly. + +```typescript +core.pairing.events.on("pairing_expire", (event) => { + // pairing expired before user approved/rejected a session proposal + const { topic } = topic; +}); +``` +### Expected User flow + +### Pairing Flow + + + + + +### Pairing Error + + + + + +### Expected Errors + +While pairing the following errors might occur: + +- No Internet connection error or pairing timeout when scanning QR with no Internet connection + - User should pair again with Internet connection +- Pairing expired error when scanning a QR code with expired pairing + - User should refresh a QR code and scan again +- Pairing with existing pairing is not allowed + - User should refresh a QR code and scan again. I usually happens when user scans an already paired QR code. + +## Session Proposal + +A session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Whenever a user wants to establish a connection between a wallet and a dapp, one should approve a session proposal. + +### User Action Feedback + +Whenever user approves or rejects a session proposal, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +Approving session +```typescript + try { + await walletKit.approveSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` +Rejecting session +```typescript + try { + await walletKit.rejectSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` + +### Session Proposal Expiry + +A session proposal expiry is 5 mins. It means a given proposal is stored for 5 mins in the SDK storage and user has 5 mins for approval or rejection decision. After that time the below event is emitted and proposal modal should be removed from the app's UI. + +```typescript +walletKit.on("proposal_expire", (event) => { + // proposal expired and any modal displaying it should be removed + const { id } = event; +}); +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session proposal the following errors might occurs: + +- No Internet connection + - It happens when a user tries to approve or reject session proposal with no Internet connection +- Session proposal expired + - It happens when users tries to approve or reject expired session proposal +- Invalid namespaces + - It happens when a validation of session namespaces fails +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Session Request + +A session request represents the request sent by a dapp to a wallet. + +### User Action Feedback + +Whenever user approves or rejects a session request, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +```typescript + try { + await walletKit.respondSessionRequest(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` + +### Session Request Expiry + +A session request expiry is defined by a dapp. It's value must be between now() + 5mins and now() + 7 days. After the session request expires the below event is emitted and session request modal should be removed from the app's UI. + +```typescript +walletKit.on("session_request_expire", (event) => { + // request expired and any modal displaying it should be removed + const { id } = event; +}); +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session request the following error might occur: + +- Invalid session + - This error might happen when user approves or rejects a session request on expired session +- Session request expired + - This error might happen when user approves or rejects a session request that already expires +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Web Socket Connection State + +The Web Socket connection state tracks the connection with the relay server, event is emitted whenever a connection state changes. + +```typescript +core.relayer.on("relayer_connect", () => { + // connection to the relay server is established +}) + +core.relayer.on("relayer_disconnect", () => { +// connection to the relay server is lost +}) + +``` + +### Expected User flow + +### Connection State + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/connection_state.gif) + diff --git a/network/wallets/react-native/chain-abstraction.mdx b/network/wallets/react-native/chain-abstraction.mdx new file mode 100644 index 0000000..1687176 --- /dev/null +++ b/network/wallets/react-native/chain-abstraction.mdx @@ -0,0 +1,96 @@ +--- +title: Chain Abstraction +--- + +import HowItWorks from "/snippets/walletkit/shared/chain-abstraction/intro.mdx"; +import ErrorHandling from "/snippets/walletkit/shared/chain-abstraction/error-handling.mdx"; + + + +## Methods + +The following methods from Wallet SDK are used in implementing chain abstraction. + + +💡 Chain abstraction is currently in the early access phase. + +Make sure you are using canary version of `@reown/walletkit` and `@walletconnect/react-native-compat` + + +Following are the methods from WalletKit that you will use in implementing chain abstraction. + +### Prepare + +This method checks if a transaction requires additional bridging transactions beforehand. + +```typescript +public abstract prepare(params: { + transaction: ChainAbstractionTypes.PartialTransaction; +}): ChainAbstractionTypes.PrepareResponse; +``` + +### Execute + +Helper method used to broadcast the bridging and initial transactions and wait for them to be completed. + +```typescript +public abstract execute(params: { + orchestrationId: ChainAbstractionTypes.OrchestrationId; + bridgeSignedTransactions: ChainAbstractionTypes.SignedTransaction[]; + initialSignedTransaction: ChainAbstractionTypes.SignedTransaction; +}): ChainAbstractionTypes.ExecuteResult; +``` + +## Usage + +When sending a transaction, first check if chain abstraction is needed using the `prepare` method. +If it is needed, you must sign all the fulfillment transactions and use the `execute` method. +Here's a complete example: + +```typescript +// Check if chain abstraction is needed +const result = await walletKit.chainAbstraction.prepare({ + transaction: { + from: transaction.from as `0x${string}`, + to: transaction.to as `0x${string}`, + // @ts-ignore - cater for both input or data + input: transaction.input || (transaction.data as `0x${string}`), + chainId: chainId, + }, +}); + +// Handle the prepare result +if ('success' in result) { + if ('notRequired' in result.success) { + // No bridging required, proceed with normal transaction + console.log('no routing required'); + } else if ('available' in result.success) { + const available = result.success.available; + + // Sign all bridge transactions and initial transaction + const bridgeTxs = available.route.map(tx => tx.transactionHashToSign); + const signedBridgeTxs = bridgeTxs.map(tx => wallet.signAny(tx)); + const signedInitialTx = wallet.signAny(available.initial.transactionHashToSign); + + // Execute the chain abstraction + const result = await walletKit.chainAbstraction.execute({ + bridgeSignedTransactions: signedBridgeTxs, + initialSignedTransaction: signedInitialTx, + orchestrationId: available.routeResponse.orchestrationId, + }); + } +} +``` + +For example, check out implementation of chain abstraction in [sample wallet](https://github.com/reown-com/react-native-examples/tree/main/wallets/rn_cli_wallet) with React Native CLI. + + + +## Testing + +To test Chain Abstraction, you can use the [AppKit laboratory](https://appkit-lab.reown.com/library/wagmi/) and try sending any supported [tokens](/network/wallets/features/chain-abstraction#what-are-the-supported-tokens-and-networks%3F) with any chain abstraction supported wallet. +You can also use this [sample wallet](https://appdistribution.firebase.dev/i/076a3bc9669d3bee) for testing. + + diff --git a/network/wallets/react-native/cloud/analytics.mdx b/network/wallets/react-native/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/react-native/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/react-native/cloud/explorer-submission.mdx b/network/wallets/react-native/cloud/explorer-submission.mdx new file mode 100644 index 0000000..e5f11c8 --- /dev/null +++ b/network/wallets/react-native/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + diff --git a/network/wallets/react-native/cloud/relay.mdx b/network/wallets/react-native/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/react-native/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/react-native/eip5792.mdx b/network/wallets/react-native/eip5792.mdx new file mode 100644 index 0000000..4643606 --- /dev/null +++ b/network/wallets/react-native/eip5792.mdx @@ -0,0 +1,284 @@ +--- +title: Wallet Call API +--- + +WalletConnect supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. +Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities. + +- `wallet_sendCalls`: Requests that a wallet submits a batch of calls. +- `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet_sendCalls. +- `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet_sendCalls. +- `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication). + +## Usage + + + + ## Capabilities in CAIP-25 Connection Requests + +CAIP-25 defines how capabilities can be expressed in wallet-to-dapp connections. These capabilities control how methods like `wallet_sendCalls` behave. + +### Session Properties + +In a connection request, dapps can request capabilities via `sessionProperties`. These can be universal (across all chains) or chain-specific: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": [], + "strict": [], + "exoticThirdThing": [] + }, + "atomic": { + "status": "supported" + } +} +``` + +### Scoped Properties + +For chain-specific capabilities, dapps use `scopedProperties`: + +```json +"scopedProperties": { + "eip155:8453": { + "paymasterService": { + "supported": true + }, + "sessionKeys": { + "supported": true + } + }, + "eip155:84532": { + "auxiliaryFunds": { + "supported": true + } + } +} +``` + +### Wallet Response + +A wallet's response should indicate which capabilities it actually supports, following EIP-5792 and CAIP-25: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": ["halt", "continue"], + "strict": ["continue"] + }, + "atomic": { + "status": "ready" + } +}, +"scopedProperties": { + "eip155:1": { + "atomic": { + "status": "supported" + } + }, + "eip155:137": { + "atomic": { + "status": "unsupported" + } + }, + "eip155:84532": { + "eip155:83532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": { + "auxiliaryFunds": { + "supported": false + }, + "atomic": { + "status": "supported" + } + } + } +} +``` +- Capabilities shared across all address in a namespace can be expressed at top-level +- Address-specific capabilities can include exceptions to scope-wide capabilities + +### Atomic Capability + +According to EIP-5792, the `atomic` capability specifies how the wallet will execute batches of transactions. It has three possible values: + +- `supported` - The wallet will execute calls atomically and contiguously +- `ready` - The wallet can upgrade to support atomic execution pending user approval +- `unsupported` - The wallet provides no atomicity guarantees + +This capability is expressed per chain and is crucial for determining how `wallet_sendCalls` with `atomicRequired: true` will be handled. + + ### Example + The `wallet_getCapabilities` method is used to request information about what capabilities a wallet supports. Following EIP-5792, here's how it should be implemented: + + #### Request + ```json + { + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_getCapabilities", + "params": ["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]] + } + ``` + + #### Response + The wallet should return a response following EIP-5792, where capabilities are organized by chain ID: + + ```json + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "0x2105": { + "atomic": { + "status": "supported" + } + }, + "0x14A34": { + "atomic": { + "status": "unsupported" + } + } + } + } + ``` + + + + ### Implementation + When implementing `wallet_sendCalls`, wallets must follow these requirements: + + #### Connection Approval + - Only approve this method during the connection approval flow if your wallet can implement it correctly + - Define the `atomic` capability per chain/account in the CAIP-25 response + + #### Request Format + ```json + { + "id": 12345, + "version": "2.0", + "method": "wc_sessionRequest", + "params": { + "chainId": "caip-2-chain-id", + "request": { + "method": "wallet_sendCalls", + "params": { + "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "chainId": "0x01", + "atomicRequired": true, + "calls": [ + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x182183", + "data": "0xfbadbaf01" + } + ] + } + } + } + } + ``` + + #### Core Implementation Requirements + - Execute calls in the exact order specified in the request + - Do not wait for any calls to be finalized before completing the batch + - If the user rejects the request, do not send any calls + + #### Atomic Execution Behavior + When `atomicRequired` is `true`: + - Execute all calls atomically (either all succeed or none have any effect) + - Execute all calls contiguously (no other transactions between batch calls) + - If your wallet can upgrade from `ready` to `supported` atomicity, do so before executing + + When `atomicRequired` is `false`: + - You may execute calls sequentially without atomicity guarantees + - You may execute atomically if your wallet supports it + - You may upgrade to `supported` atomicity and execute atomically + + #### Response Enrichment + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + + + ### Example + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + To implement this functionality, the response for wallet_sendCalls should be enriched with capabilities: + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + Specify the `scopedProperties` when approving a session: + + ```json + "scopedProperties": { + "eip155": { + "walletService": [{ + "url": "", + "methods": ["wallet_getCallsStatus"] + }] + } + } + ``` + + ### Response Format + The response format for `wallet_getCallsStatus` varies based on the execution method: + + #### For Atomic Execution + ```json + { + "receipts": [/* single receipt or array of receipts */], + "atomic": true + } + ``` + + #### For Non-Atomic Execution + ```json + { + "receipts": [/* array of receipts for all transactions */], + "atomic": false + } + ``` + + + For non-atomic execution, include all transactions in the receipts array, even those that were included on-chain but eventually reverted. + + + + +## References +- EIP-5792: https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability +- CAIP-25 namespaces: https://github.com/ChainAgnostic/namespaces/blob/main/eip155/caip25.md diff --git a/network/wallets/react-native/installation.mdx b/network/wallets/react-native/installation.mdx new file mode 100644 index 0000000..a3d785d --- /dev/null +++ b/network/wallets/react-native/installation.mdx @@ -0,0 +1,31 @@ +--- +title: Installation +--- + +Install the WalletKit package. + +```sh +yarn add @reown/walletkit @walletconnect/react-native-compat +``` + +Additionally add these extra packages to help with async storage, polyfills and the instance of ethers. + +```sh +yarn add @react-native-async-storage/async-storage @react-native-community/netinfo react-native-get-random-values fast-text-encoding +``` + + +```sh +npx expo install expo-application +``` + + +For those using Typescript, we recommend adding these dev dependencies: + +```sh +yarn add @walletconnect/jsonrpc-types --dev +``` + +## Next Steps + +Now that you've installed Wallet SDK, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/react-native/link-mode.mdx b/network/wallets/react-native/link-mode.mdx new file mode 100644 index 0000000..7537ca8 --- /dev/null +++ b/network/wallets/react-native/link-mode.mdx @@ -0,0 +1,115 @@ +--- +title: Link Mode +--- + +Wallet SDK Link Mode is a low latency mechanism for transporting [One-Click Auth](/network/wallets/react-native/one-click-auth) requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection. + + +Make sure that [One-Click Auth](/network/wallets/react-native/one-click-auth) is implemented before enabling Link Mode. + + +### How to enable it: + +To support Link Mode add a universal link for your wallet in Cloud project configuration [dashboard](https://dashboard.walletconnect.com/sign-in), configure your Metadata with a valid universal link and set the `linkMode` property to `true`: + +```ts {10-11} +const walletKit = await WalletKit.init({ + core, + metadata: { + name: "Demo React Native Wallet", + description: "Demo RN Wallet to interface with Dapps", + url: "www.reown.com/walletkit", + icons: ["https://your_wallet_icon.png"], + redirect: { + native: "yourwalletscheme://", + universal: "https://example.com/example_wallet", + linkMode: true, + }, + }, +}); +``` + +### Platform specifics: + + + + +To enable universal links for your app, refer to [React Native Documentation](https://reactnative.dev/docs/linking?syntax=ios#enabling-deep-links).
+ +After following the steps provided in the official guide: + +1. Ensure that you handle incoming Universal Links in the your `AppDelegate.mm` file. + +```swift +#import + +// Enable deeplinks +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options +{ + return [RCTLinkingManager application:application openURL:url options:options]; +} + +// Enable Universal Links +- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity + restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler +{ + return [RCTLinkingManager application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; +} +``` + +2. Open your project in XCode and go to `Settings/Signing & Capabilities/Associated Domains` to add the new domain. After this, `your_project.entitlement` should look like this: + +```xml + + + + + com.apple.developer.associated-domains + + applinks:example.com + + + +``` + +3. Update/Create your domain's `.well-known/apple-app-site-association` file accordingly. + +For more information about supporting universal links, visit the [Supporting associated domains](https://developer.apple.com/documentation/xcode/supporting-associated-domains?language=objc) page + +For a debugging guide, visit the [Debugging Universal Links](https://developer.apple.com/documentation/technotes/tn3155-debugging-universal-links) page.
+ +
+ + +Android Studio provides a tool to configure Universal Links easily, you can read the guide in [Android Documentation](https://developer.android.com/studio/write/app-link-indexing) + +After following the steps provided in the guide: + +1. Ensure that your Universal Link is properly configured in your app's `AndroidManifest.xml` file with the `autoVerify` set to `true`. It should look similar to this: + +```xml + + + + + + + + + + +``` + +2. Update/Create your domains's `.well-known/assetlinks.json` file accordingly + +For more information on how to configure universal links for your app, refer to [Android Documentation](https://developer.android.com/studio/write/app-link-indexing).
+For testing the configured universal link to app content check [this](https://developer.android.com/training/app-links/deep-linking#testing-filters) documentation page.
+ +
+
+ +Once everything is properly configured, and the user interacts with a Link Mode-supporting dApp, your wallet will receive requests through it. diff --git a/network/wallets/react-native/mobile-linking.mdx b/network/wallets/react-native/mobile-linking.mdx new file mode 100644 index 0000000..6b9cb66 --- /dev/null +++ b/network/wallets/react-native/mobile-linking.mdx @@ -0,0 +1,115 @@ +--- +title: Mobile Linking +--- + +import HowToTest from "/snippets/walletkit/shared/mobile-linking.mdx"; + + + +This feature is only relevant to native platforms. + + + +## Usage + +Mobile Linking allows your wallet to automatically redirect back to the Dapp allowing for less user interactions and hence a better UX for your users. + +### Establishing Communication Between Mobile Wallets and Apps + +When integrating a wallet with a mobile application, it's essential to understand how they communicate. The process involves two main steps: + +1. **QR Code Handshake:** The mobile app (Dapp) generates a unique URI (Uniform Resource Identifier) and displays it as a QR code. This URI acts like a secret handshake. When the user scans the QR code using their wallet app, they establish a connection. It's like saying, "Hey, let's chat!" +2. **Deep Links and Universal Links:** The URI from the QR code allows the wallet app to create a [deep link](https://support.google.com/google-ads/answer/10023042?hl=en#:~:text=Deep%20links%20send%20mobile%20device,%2C%20Shopping%2C%20and%20Display%20campaigns.) or [universal link](https://developer.apple.com/ios/universal-links/). These links work on both Android and iOS. They enable seamless communication between the wallet and the app. + + + +**Developers should prefer Deep Linking over Universal Linking.** + +Universal Linking may redirect the user to a browser, which might not provide the intended user experience. Deep Linking ensures the user is taken directly to the app. + + + +### Key Behavior to Address + +In some scenarios, wallets use redirect metadata provided in session proposals to open applications. This can cause unintended behavior, such as: + +Redirecting to the wrong app when multiple apps share the same redirect metadata (e.g., a desktop and mobile version of the same Dapp). +Opening an unrelated application if a QR code is scanned on a different device than where the wallet is installed. + +#### Recommended Approach + +To avoid this behavior, wallets should: + +- **Restrict Redirect Metadata to Deep Link Use Cases**: Redirect metadata should only be used when the session proposal is initiated through a deep link. QR code scans should not trigger app redirects using session proposal metadata. + +The connection and sign request flows are similar across platforms. + +### Connection Flow + +- **Dapp Prompts User:** The Dapp asks the user to connect. +- **User Chooses Wallet:** The user selects a wallet from a list of compatible wallets. +- **Redirect to Wallet:** The user is redirected to their chosen wallet. +- **Wallet Approval:** The wallet prompts the user to approve or reject the session (similar to granting permission). +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reunites with Dapp:** After all the interactions, the user ends up back in the Dapp. + + + + Mobile Linking Connect Flow + Mobile Linking Connect Flow + + +### Sign Request Flow + +When the Dapp needs the user to sign something (like a transaction), a similar pattern occurs: + +- **Automatic Redirect:** The Dapp automatically sends the user to their previously chosen wallet. +- **Approval Prompt:** The wallet asks the user to approve or reject the request. +- **Return to Dapp:** + - **Manual Return:** The wallet asks the user to manually return to the Dapp. + - **Automatic Return:** Alternatively, the wallet automatically takes the user back to the Dapp. +- **User Reconnects:** Eventually, the user returns to the Dapp. + + + Mobile Linking Connect Flow + Mobile Linking Connect Flow + + +## Platform preparations + +Since React Native leverages on native APIs, you must follow iOS and Android steps for each native platform + +More information in official documentation: https://reactnative.dev/docs/linking?syntax=android#enabling-deep-links + + + +Dapps developers must do the same for their own custom schemes if they want the wallet to be able to navigate back after a session approval or a sign request response + + + + + +## Integration + +In order to redirect to the Dapp, you'll need to use `Linking` from `react-native` and call `openURL()` method with the Dapp scheme that comes in the proposal metadata. + +```js +import { Linking } from "react-native"; + +async function onApprove(proposal, namespaces) { + const session = await walletKit.approveSession({ + id: proposal.id, + namespaces, + }); + + const dappScheme = session.peer.metadata.redirect?.native; + + if (dappScheme) { + Linking.openURL(dappScheme); + } else { + // Inform the user to manually return to the DApp + } +} +``` diff --git a/network/wallets/react-native/notifications/notify/installation.mdx b/network/wallets/react-native/notifications/notify/installation.mdx new file mode 100644 index 0000000..a3ad2ad --- /dev/null +++ b/network/wallets/react-native/notifications/notify/installation.mdx @@ -0,0 +1,114 @@ +--- +title: Installation +--- + +Install the WalletConnect NotifyClient package. + +```sh +yarn add @walletconnect/notify-client @walletconnect/react-native-compat +``` + +You will need to polyfill crypto depending on your environment. See instructions below. + + + + +```sh +yarn add expo-crypto +``` + +1. Create a file called `expo-crypto-shim.js` at the root of your project +2. Go to `expo-crypto-shim.js`and paste the following snippet into it. + +```js +import { digest } from "expo-crypto"; + +// eslint-disable-next-line no-undef +const webCrypto = typeof crypto !== "undefined" ? crypto : new Crypto(); +webCrypto.subtle = { + digest: (algo, data) => { + const buf = Buffer.from(data); + return digest(algo, buf); + }, +}; +(() => { + if (typeof crypto === "undefined") { + Object.defineProperty(window, "crypto", { + configurable: true, + enumerable: true, + get: () => webCrypto, + }); + } +})(); +``` + +3. Then head over your `index.js` file at the root of your project and add the following imports. + +```js +import "@walletconnect/react-native-compat"; +import "./expo-crypto-shim.js"; +``` + + + + +```sh +yarn add react-native-quick-crypto react-native-quick-base64 stream-browserify @craftzdog/react-native-buffer babel-plugin-module-resolver +``` + +For iOS only + +```bash +cd ios && pod install +``` + +1. Go to your `index.js` file at the root of your project and add the following polyfill + +```js +import { AppRegistry } from "react-native"; +import App from "./App"; +import { name as appName } from "./app.json"; +import crypto from "react-native-quick-crypto"; + +const polyfillDigest = async (algorithm, data) => { + const algo = algorithm.replace("-", "").toLowerCase(); + const hash = crypto.createHash(algo); + hash.update(data); + return hash.digest(); +}; + +globalThis.crypto = crypto; +globalThis.crypto.subtle = { + digest: polyfillDigest, +}; + +AppRegistry.registerComponent(appName, () => App); +``` + +2. Update your `babel.config.js` with the following configuration + +```js +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + alias: { + 'crypto': 'react-native-quick-crypto', + 'stream': 'stream-browserify', + 'buffer': '@craftzdog/react-native-buffer', + }, + }, + ], + ... + ], +}; +``` + + + + +## Next Steps + +Now that you've installed WalletConnect Notify, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the Notify API. diff --git a/network/wallets/react-native/notifications/notify/overview.mdx b/network/wallets/react-native/notifications/notify/overview.mdx new file mode 100644 index 0000000..3c1bf27 --- /dev/null +++ b/network/wallets/react-native/notifications/notify/overview.mdx @@ -0,0 +1,26 @@ +--- +title: Overview +--- + + +For those integrating notifications related to wallet pairing and sign requests, please check [here](../push). + + +The WalletKit Notify API is designed to enhance the interaction between wallet users and dapps by offering a robust notification system. This API empowers wallet developers to implement a dynamic notification experience directly within their wallets. It provides the functionality for users to opt-in to notifications, ensuring they stay informed about critical events and interactions. + +The Notify API is versatile, with support for both iOS and Android platforms, making it an ideal choice for cross-platform wallet applications. + +Coupled with the AppKit Notifications, the Notify API forms part of a comprehensive toolkit that enables seamless integration of web3 communication and messaging features into dapps. This ensures a more connected and interactive experience for users in the decentralized ecosystem. + +## Features + +Some of the key features of the Notify API include: + +- **Push Notifications for Desktop and Native Platforms**: This feature enables dapps to directly send vital notifications to user wallets, ensuring timely and relevant communication. +- **Robust Spam Protection**: Users have complete authority over which dapps can send them notifications, effectively eliminating any unsolicited messages from unknown sources. Furthermore, users can fine-tune their preferences to only receive notifications types they are interested in, like new features or some important events occurrence. +- **Chain Agnostic Architecture**: The Notify API is built to be compatible with any blockchain, allowing seamless multi-chain support without the need for writing additional integration code. **As of November 2023, the Notify Server and Clients are equipped to support EVM chains. Plans to extend support to non-EVM chains are in progress and are a significant part of our upcoming development roadmap.** + +_Example integration_ + + + diff --git a/network/wallets/react-native/notifications/notify/spam-protection.mdx b/network/wallets/react-native/notifications/notify/spam-protection.mdx new file mode 100644 index 0000000..0e7bc21 --- /dev/null +++ b/network/wallets/react-native/notifications/notify/spam-protection.mdx @@ -0,0 +1,27 @@ +--- +title: Spam Protection +--- + +Users play a critical role in web3. That's why, with Web3Inbox, we’re committed to ensuring users can enjoy a safe, seamless, and reliable experience that puts them in the driver’s seat. As part of that pledge, Web3Inbox provides a number of user-first, anti-spam features and elements that ensure users are always in control of their web3 communications. + +## How are users protected from spam with Web3Inbox? + +### Becoming a WalletKit Notification customer + +When a wallet offers app notifications to their users via Web3Inbox, the feature will always be optional. If users decide they want to receive notifications from selected apps via their wallet, they’ll be able to ‘opt-in’ and subscribe to an app’s notifications by signing a message request. Similarly, when accessing notifications through the [Web3Inbox.com app](https://app.web3inbox.com), users will be met with the same request for each application they choose to subscribe to. This feature not only enables users to experience a customized, ‘app-by-app’ approach to staying connected in web3, but also ensures they only ever hear from the apps they choose to — no unsolicited notifications or spam from unknown senders. Its their curated inbox, connected with only those they choose. + +### Setting customized notification preferences + +Once users have subscribed to their chosen apps, they have the option to define and set which types of notifications they receive from those apps. For example, a user may wish to receive only information regarding changes to their portfolio from a DEX, or, they might want to receive notifications from an NFT marketplace — but only notifications regarding their own NFT collections. In these scenarios, they’ll have the ability to disable other notification types, like marketing updates, and ensure their feed is curated to show only information that’s meaningful to them. As apps set their own notification types, they have unlimited optionality to really build out a notification structure they know can support their users’ needs — no ‘one size fits all’ approach, but a personable, community-oriented structure that puts both app and user needs’ at the forefront of communication. + +### Rate limiting + +Apps are limited to a maximum number of notifications they’re able to send to their community. Specifically, apps may send accounts notifications twice an hour on average, but may exceed that average in bursts of up to 50 at a time. + +## Our continued pledge on spam protection + +We're constantly working on improving and growing our products, and we have a number of impactful anti-spam features and functions in the works set to increase the overall protection and user experience of WalletKit Notification users: + +### User reporting + +Users will have the ability to report applications that appear to be acting or engaging with their community in a malicious or suspicious manner. Projects that are flagged as malicious may be removed from the WalletKit Notification discover page and have notification functionality disabled. diff --git a/network/wallets/react-native/notifications/notify/usage.mdx b/network/wallets/react-native/notifications/notify/usage.mdx new file mode 100644 index 0000000..0bc1322 --- /dev/null +++ b/network/wallets/react-native/notifications/notify/usage.mdx @@ -0,0 +1,427 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +In this section, we showcase the aspects of using the Notify API. We'll guide you through the initial steps of initializing the Notify client and logging in a blockchain account. You'll also learn how to manage your subscriptions and messages. Additionally, we cover the process of setting up and displaying push notifications on your preferred platform. To ensure a good user experience, we include best practices for spam protection, helping you to enable the users to maintain control over the notifications wallet receives. + +## Content + +Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out Extra (Platform Specific) under this section. + +- [Initialization](#initialization): + Creating a new Notify Client instance and initializing it with a projectId from [[WalletConnect Dashboard](https://dashboard.walletconnect.com/). +- [Account login](#account-login): + A SIWE message must be signed by the user in order to authorize the client to use Notify API +- [Subscribing to a new dapp](#subscribing-to-a-new-dapp): + Opt-in to receive notifications from dapp +- [Fetching active subscriptions](#fetching-active-subscriptions): + Get active subscriptions +- [Fetching subscription’s notification](#fetching-subscriptions-notifications): + Get notifications of a subscription +- [Fetching available notification types](#fetching-available-notification-types): + Get latest notification types +- [Updating subscriptions notification settings](#updating-subscriptions-notification-settings): + Change allowed notification types sent by dapp +- [Unsubscribe from a dapp](#unsubscribe-from-a-dapp): + Opt-out from receiving notifications from a dapp +- [Account logout](#account-logout): + To stop receiving notifications to this client, accounts can logout of using Notify API +- [Push Notification Setup](#push-notification-setup): + Configuring app in order to decrypt notifications + +## Initialization + + + +#### Initialize the SDK clients + +```javascript +import { NotifyClient } from "@walletconnect/notify-client"; + +const notifyClient = await NotifyClient.init({ + projectId: "", +}); +``` + +## Add listeners for relevant events + +```javascript +// Handle response to a `notifyClient.subscribe(...)` call +notifyClient.on("notify_subscription", async ({ params }) => { + const { error } = params; + + if (error) { + // Setting up the subscription failed. + // Inform the user of the error and/or clean up app state. + console.error("Setting up subscription failed: ", error); + } else { + // New subscription was successfully created. + // Inform the user and/or update app state to reflect the new subscription. + console.log(`Subscribed successfully.`); + } +}); + +// Handle an incoming notification +notifyClient.on("notify_message", ({ params }) => { + const { message } = params; + // e.g. build a notification using the metadata from `message` and show to the user. +}); + +// Handle response to a `notifyClient.update(...)` call +notifyClient.on("notify_update", ({ params }) => { + const { error } = params; + + if (error) { + // Updating the subscription's scope failed. + // Inform the user of the error and/or clean up app state. + console.error("Setting up subscription failed: ", error); + } else { + // Subscription's scope was updated successfully. + // Inform the user and/or update app state to reflect the updated subscription. + console.log(`Successfully updated subscription scope.`); + } +}); + +// Handle a change in the existing subscriptions (e.g after a subscribe or update) +notifyClient.on("notify_subscriptions_changed", ({ params }) => { + const { subscriptions } = params; + // `subscriptions` will contain any *changed* subscriptions since the last time this event was emitted. + // To get a full list of subscriptions for a given account you can use `notifyClient.getActiveSubscriptions({ account: 'eip155:1:0x63Be...' })` +}); +``` + +## Account login + +In order to register account in Notify API to be able to subscribe to any dapp to start receiving notifications, account needs to sign SIWE message to prove ownership. Developers can check if an account is registered by calling **`isRegistered()`** function. If the account is not registered, developers should call **`prepareRegistration()`** and then **`register()`** function to register the account. + + +This is a one-time action per account. It does not need to be repeated after initial registration of the new account. + + +### Registering as a wallet + +```javascript +const account = `eip155:1:0x63Be2c680685d2A9620c11b0068291261aa62d76` +const domain = 'app.mydomain.com', // pass the domain (i.e. the hostname) where your dapp is hosted. +const allApps = true // The user will be prompted to authorize this wallet to send and receive messages on their behalf for ALL domains using their WalletConnect identity. + +// No need to register and sign message if already registered. +if (notifyClient.isRegistered({ account, domain, allApps })) return; + +const {registerParams, message} = notifyClient.prepareRegistration({ + account, + domain, + allApps +}); + +const signature = await ethersWallet.signMessage(message); + +await notifyClient.register({ + registerParams, + signature, +}) +``` + +## Subscribing to a new dapp + +To begin receiving notifications from a dapp, users must opt-in by subscribing. This subscription process grants permission for the dapp to send notifications to the user. These notifications can serve a variety of purposes, such as providing updates on the user's blockchain account activities or informing them about ongoing campaigns within the dapp. Upon initial subscription, clients will be automatically enrolled to receive all types of notifications as defined by the dapp at that moment. Users have the flexibility to modify their notification settings later, allowing them to tailor the types of alerts they receive according to their preferences. + + +To identify dapps that can be subscribed to via Notify, we can query the following Explorer API endpoint: + +https://explorer-api.walletconnect.com/v3/dapps?projectId=YOUR_PROJECT_ID&is_notify_enabled=true + + +```javascript +// Get the domain of the target dapp from the Explorer API response +const appDomain = new URL(fetchedExplorerDapp.platform_browser).hostname; + +// Subscribe to `fetchedExplorerDapp` by passing the account to be subscribed and the domain of the target dapp. +await notifyClient.subscribe({ + account, + appDomain, +}); + +// -> Success/Failure will be received via the `notify_update` event registered previously. +// -> New subscription will be emitted via the `notify_subscriptions_changed` watcher event. +``` + +## Fetching active subscriptions + +To fetch the current list of subscriptions an account has, call **`getActiveSubscriptions()`**. + +```javascript +// Will return all active subscriptions for the provided account, keyed by subscription topic. +const accountSubscriptions = notifyClient.getActiveSubscriptions({ + account: `eip155:1:0x63Be...`, +}); +``` + +## Fetching subscription's notifications + +To fetch subscription's notifications by calling **`getNotificationHistory()`**. + +```javascript +const notifications = notifyClient.getNotificationHistory(account); +``` + +## Fetching available notification types + +Developers can fetch latest notification types specified by dapp by calling **`getNotificationTypes()`** function. + +You can use the `scope` object of the subscription to get the available notification types. + +```typescript +// get notification types by accessing `scope` member of a dapp's subscription +const notificationTypes = notifyClient + .getActiveSubscriptions({ account }) + .filter((subscription) => subscription.topic === topic).scope; +``` + +## Updating subscriptions notification settings + +Users can alter their notification settings to filter out unwanted alerts from a dapp. During this process, they review and select the types of notifications they wish to receive, based on the latest options provided by the dapp. Available notification types fetching is shown in the [next section](#fetching-available-notification-types). + +```javascript +// `topic` - subscription topic of the subscription that should be updated. +// `scope` - an array of notification types that should be enabled going forward. The current scopes can be found under `subscription.scope`. +await notifyClient.update({ + topic, + scope: ["alerts"], +}); +``` + +## Unsubscribe from a dapp + +To opt-out of receiving notifications from a dap, a user can decide to unsubscribe from dapp. + +```javascript +notifyClient.deleteSubscription({ + topic: "subscription_topic_to_unsubscribe_from", +}); +``` + +## Account logout + +If an account is removed from the client or a user no longer wants to receive notifications for this account, you can logout the account from Notify API by calling **`unregister()`**. This will remove all subscriptions and messages for this account from the client’s storage. + +```javascript +const account = `eip155:1:0x63Be2c680685d2A9620c11b0068291261aa62d76`; + +await notifyClient.unregister({ + account, +}); +``` + +## Fetch notification history (Pagination) + +There might be different approaches to implement pagination in your app depending on your needs. You can see the following example implemented with `FlatList` which introduces infinite scroll functionality with a basic example: + +Please make sure you have better handling of the notify client instance which handles worst cases by checking initialization status, account status, for production ready apps. + +```javascript +export default function SubscriptionDetailsScreen() { + const {topic} = useRoute().params as {topic: string}; + const [notifications, setNotifications] = React.useState([]); + const [hasMore, setHasMore] = React.useState(false); + const [isLoading, setIsLoading] = React.useState(false); + + const lastItem = notifications?.[notifications.length - 1]?.id; + + async function getNotificationHistory(startingAfter?: string) { + setIsLoading(true); + + const notificationHistory = await notifyClient.getNotificationHistory({ + topic, + limit: 15, + startingAfter, + }); + + setNotifications( + prevNotifications => prevNotifications.concat(notificationHistory.notifications), + ); + setHasMore(notificationHistory.hasMore); + setIsLoading(false); + + return notificationHistory; + } + + React.useEffect(() => { + getNotificationHistory(); + }, [topic]); + + return ( + item.sentAt.toString()} + onEndReached={() => { + if (hasMore && lastItem) { + getNotificationHistory(lastItem) + } + }} + ListFooterComponent={() => { + if (!isLoading) return null + return + }} + renderItem={({item}) => ( + + )} + /> + ); +} +``` + +### Push Notification Setup + +Install [`@react-native-firebase/app`](https://www.npmjs.com/package/@react-native-firebase/app), [`@react-native-firebase/messaging`](https://www.npmjs.com/package/@react-native-firebase/messaging) and [`@notifee/react-native`](https://www.npmjs.com/package/@notifee/react-native) to handle Push Notifications. +Please refer to the respective package documentation to configure them properly. + +``` +yarn add @notifee/react-native @react-native-firebase/app @react-native-firebase/messaging +``` + +Update your `index.js` file to include the following logic. + +```js +import { AppRegistry } from "react-native"; +import { name as appName } from "./app.json"; +import crypto from "react-native-quick-crypto"; + +import messaging from "@react-native-firebase/messaging"; +import notifee, { + AndroidImportance, + AndroidVisibility, + EventType, +} from "@notifee/react-native"; +import { NotifyClient } from "@walletconnect/notify-client"; +import { decryptMessage } from "@walletconnect/notify-message-decrypter"; + +import App from "./src/App"; + +const polyfillDigest = async (algorithm, data) => { + const algo = algorithm.replace("-", "").toLowerCase(); + const hash = crypto.createHash(algo); + hash.update(data); + return hash.digest(); +}; + +globalThis.crypto = crypto; +globalThis.crypto.subtle = { + digest: polyfillDigest, +}; + +// Create notification channel (Android only feature) +notifee.createChannel({ + id: "default", + name: "Default Channel", + lights: false, + vibration: true, + importance: AndroidImportance.HIGH, + visibility: AndroidVisibility.PUBLIC, +}); + +let notifyClient; + +const projectId = process.env.ENV_PROJECT_ID; + +async function registerAppWithFCM() { + // This is expected to be automatically handled on iOS. See https://rnfirebase.io/reference/messaging#registerDeviceForRemoteMessages + if (Platform.OS === "android") { + await messaging().registerDeviceForRemoteMessages(); + } +} + +async function registerClient(deviceToken, clientId) { + const body = JSON.stringify({ + client_id: clientId, + token: deviceToken, + type: "fcm", + always_raw: true, + }); + + const requestOptions = { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, + }; + + return fetch( + `https://echo.walletconnect.com/${projectId}/clients`, + requestOptions + ) + .then((response) => response.json()) + .then((result) => console.log(">>> registered client", result)) + .catch((error) => console.log(">>> error while registering client", error)); +} + +async function handleGetToken(token) { + const status = await messaging().requestPermission(); + const enabled = + status === messaging.AuthorizationStatus.AUTHORIZED || + status === messaging.AuthorizationStatus.PROVISIONAL; + + if (enabled) { + notifyClient = await NotifyClient.init({ projectId }); + const clientId = await notifyClient.core.crypto.getClientId(); + return registerClient(token, clientId); + } +} + +messaging().getToken().then(handleGetToken); +messaging().onTokenRefresh(handleGetToken); + +async function onMessageReceived(remoteMessage) { + if (!remoteMessage.data?.blob || !remoteMessage.data?.topic) { + console.log("Missing blob or topic on notification message."); + return; + } + + const decryptedMessage = await decryptMessage({ + topic: remoteMessage.data?.topic, + encryptedMessage: remoteMessage.data?.blob, + }); + + return notifee.displayNotification({ + title: decryptedMessage.title, + body: decryptedMessage.body, + id: "default", + android: { + channelId: "default", + importance: AndroidImportance.HIGH, + visibility: AndroidVisibility.PUBLIC, + smallIcon: "ic_launcher", // optional, defaults to 'ic_launcher'. + // pressAction is needed if you want the notification to open the app when pressed. See https://notifee.app/react-native/docs/ios/interaction#press-action + pressAction: { + id: "default", + }, + }, + }); +} + +messaging().onMessage(onMessageReceived); +messaging().setBackgroundMessageHandler(onMessageReceived); + +notifee.onBackgroundEvent(async ({ type, detail }) => { + const { notification, pressAction } = detail; + + // Check if the user pressed the "Mark as read" action + if (type === EventType.ACTION_PRESS && pressAction.id === "mark-as-read") { + // Remove the notification + await notifee.cancelNotification(notification.id); + } +}); + +function HeadlessCheck({ isHeadless }) { + if (isHeadless) { + // App has been launched in the background by iOS, ignore + return null; + } + + // Render the app component on foreground launch + return ; +} + +AppRegistry.registerComponent(appName, () => HeadlessCheck); +``` diff --git a/network/wallets/react-native/notifications/push.mdx b/network/wallets/react-native/notifications/push.mdx new file mode 100644 index 0000000..2316249 --- /dev/null +++ b/network/wallets/react-native/notifications/push.mdx @@ -0,0 +1,115 @@ +--- +title: Push Notifications +--- + +WalletKit provides the functionality for wallets to receive push notifications through Firebase Cloud Messaging (FCM) and Apple Push Notification Service (APNs) via the Push Server. This feature ensures that wallets are promptly notified of incoming signature requests. Each push notification contains the encrypted details of the signature request. Upon receiving the notification, it can be decrypted and presented to the developer, allowing for customization of the message according to their requirements. + +## Server setup + +For the push notifications to be forwarded to FCM or APNs, the [Push Server](https://docs.reown.com/advanced/push-server) will need to be configured with your FCM or APNs server API credentials. + +## App setup + +### Register the device token + +To enable a device for push notifications, it's essential to register the device token using `walletKit.registerDeviceToken`. This token can be obtained from either FCM or APNS, depending on the platform used. + +To receive push notifications from WalletConnect's Push Server via Firebase Cloud Messaging, you will need to setup Firebase in your project. +You can follow their documentation - [Firebase documentation](https://rnfirebase.io/messaging/usage#installation). +Once you have Firebase configured, you can obtain the device token by calling `messaging().getToken()`. This unique token is used to identify each device. + +```ts +import messaging from '@react-native-firebase/messaging' + +const token = await messaging().getToken() +``` + +The device token will be used to register for WalletConnect push notifications by calling `walletKit.registerDeviceToken` and passing the token as an argument. +The `registerDeviceToken` should be called every time the client is initialized. + +```ts +walletKit.registerDeviceToken({ + token: await messaging().getToken(), // device token + clientId: await walletKit.core.crypto.getClientId(), //your instance clientId + notificationType: 'fcm', // notification type + enableEncrypted: true // flag that enabled detailed notifications +}) +``` + +With that the base setup is complete and you can start receiving push notifications from WalletConnect's Push Server for your sessions. + +Note, that from time to time, the device token is refreshed, so you must make sure to register it again. + +```ts +import messaging from '@react-native-firebase/messaging'; + +messaging().onTokenRefresh(async token => { + await walletKit.registerDeviceToken({ + token: await messaging().getToken(), // device token + clientId: await walletKit.core.crypto.getClientId(), //your instance clientId + notificationType: 'fcm', // notification type + enableEncrypted: true // flag that enabled detailed notifications + }); +}); +``` + +### Receiving push notifications + +After the device token is registered, the next step involves setting up the notification service specific to the platform being used. This service will decrypt the incoming requests and forward them to the developer for further processing and integration. + +To receive the actual push notifications, you will need to subscribe to firebase messaging events. + +```ts +import messaging from '@react-native-firebase/messaging'; + +// emitted when the app is open and a notification is received +messaging().onMessage(async notification => { + ... +}); + +// emitted when the app is in the background or closed and a notification is received +messaging().setBackgroundMessageHandler(async notification => { + ... +}); + +``` + +Now that we have the notifications listeners setup, we can start processing the incoming notifications. + +```ts +import { WalletKit } from '@reown/walletkit'; +import messaging from '@react-native-firebase/messaging'; + +messaging().onMessage(async notification => { + // get the topic, encrypted message & tag from the notification payload + const { topic, message, tag } = notification.data; + + // decrypt the message + // note this is static method and can be called without initializing the walletKit + const decryptedMessage = await WalletKit.notifications.decryptMessage({ + topic, + encryptedMessage: message, + }); + + /* + * `decryptedMessage` is JsonRpcRequest object, with the full payload of the incoming request such as method, params, id, etc. + * You can use it to emit local push notification with the request to the user and ask for their approval. + **/ + + /* + * the metadata contains name, description, icon and url of the dapp that initiated the request + * note that only notifications with tag `1108`(session requests) will have metadata, + **/ + let metadata + + if(tag == 1108) { + metadata = await WalletKit.notifications.getMetadata({ topic }); + } else { + // session proposals contain metadata in the request itself + metadata = decryptedMessage.params.proposer.metadata + } + + // with this information you can show a local push notification to the user + ... +}); +``` diff --git a/network/wallets/react-native/one-click-auth.mdx b/network/wallets/react-native/one-click-auth.mdx new file mode 100644 index 0000000..178d355 --- /dev/null +++ b/network/wallets/react-native/one-click-auth.mdx @@ -0,0 +1,137 @@ +--- +title: One-click Auth +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem. + + + Mobile Linking Connect Flow + Mobile Linking Connect Flow + + +## Handling Authentication Requests + +To handle incoming authentication requests, subscribe to the `session_authenticate` event. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```typescript +walletKit.on("session_authenticate", async (payload) => { + // Process the authentication request here. + // Steps include: + // 1. Populate the authentication payload with the supported chains and methods + // 2. Format the authentication message using the payload and the user's account + // 3. Present the authentication message to the user + // 4. Sign the authentication message(s) to create a verifiable authentication object(s) + // 5. Approve the authentication request with the authentication object(s) +}); +``` + +## Authentication Payload + +```typescript +import { populateAuthPayload } from "@walletconnect/utils"; + +// EVM chains that your wallet supports +const supportedChains = ["eip155:1", "eip155:2", 'eip155:137']; +// EVM methods that your wallet supports +const supportedMethods = ["personal_sign", "eth_sendTransaction", "eth_signTypedData"]; +// Populate the authentication payload with the supported chains and methods +const authPayload = populateAuthPayload({ + authPayload: payload.params.authPayload, + chains: supportedChains, + methods: supportedMethods, +}); +// Prepare the user's address in CAIP10(https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) format +const iss = `eip155:1:0x0Df6d2a56F90e8592B4FfEd587dB3D5F5ED9d6ef`; +// Now you can use the authPayload to format the authentication message +const message = walletKit.formatAuthMessage({ + request: authPayload, + iss +}); + +// Present the authentication message to the user +... +``` + +## Approving Authentication Requests + + + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + + +```typescript +// Approach 1 +// Sign the authentication message(s) to create a verifiable authentication object(s) +const signature = await cryptoWallet.signMessage(message, privateKey); +// Build the authentication object(s) +const auth = buildAuthObject( + authPayload, + { + t: "eip191", + s: signature, + }, + iss +); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths: [auth], +}); + +// Approach 2 +// Note that you can also sign multiple messages for every requested chain/address pair +const auths = []; +authPayload.chains.forEach(async (chain) => { + const message = walletKit.formatAuthMessage({ + request: authPayload, + iss: `${chain}:${cryptoWallet.address}`, + }); + const signature = await cryptoWallet.signMessage(message); + const auth = buildAuthObject( + authPayload, + { + t: "eip191", // signature type + s: signature, + }, + `${chain}:${cryptoWallet.address}` + ); + auths.push(auth); +}); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths, +}); +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method. + +```typescript +import { getSdkError } from "@walletconnect/utils"; + +await walletKit.rejectSessionAuthenticate({ + id: payload.id, + reason: getSdkError("USER_REJECTED"), // or choose a different reason if applicable +}); +``` + +## Testing One-click Auth + +You can use [AppKit Labs](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/react-native/resources.mdx b/network/wallets/react-native/resources.mdx new file mode 100644 index 0000000..9dd36f5 --- /dev/null +++ b/network/wallets/react-native/resources.mdx @@ -0,0 +1,31 @@ +--- +title: Resources +--- + +Valuable assets for developers and users interested in integrating Wallet SDK into their applications. + +- [Awesome WalletConnect](https://github.com/WalletConnect/awesome-walletconnect) - Community-curated collection of WalletConnect-enabled wallets, libraries, and tools. +- [AppKit Laboratory](https://appkit-lab.reown.com/) - A place to test your wallet integrations against various setups of AppKit. +- [Wallet SDK React Native GitHub](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/web3wallet) - Wallet SDK React Native GitHub repository. + +### Wallet Resources + +[Wallet SDK](https://medium.com/walletconnect/simplifying-integration-for-wallet-developers-with-the-new-web3wallet-sdk-8706b69e149c) simplifies the integration process for wallet developers by combining our Sign and Auth APIs. Please note that only V2 [WCURIs](https://specs.walletconnect.com/2.0/specs/clients/core/pairing/pairing-uri) will work with this SDK, as V1 is being deprecated by June 28th, 2023. + +#### Expo + +Experimental: For Expo, we have an unofficial npx starter command. `newWallet` represents the name of your project. + +```bash +npx create-wc-wallet-expo@latest newWallet +``` + +This downloads an Expo template with Wallet SDK installed. More information available in this [tutorial](https://medium.com/walletconnect/how-to-build-a-wallet-in-react-native-with-the-web3wallet-sdk-b6f57bf02f9a) + +### Dapp Resources + +If you need to test your app's integration, you can use one of our following demo wallets and/or dapps. + +**Sign** + +- [React dApp (with standalone client) - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) ([Demo](https://react-app.walletconnect.com/)) diff --git a/network/wallets/react-native/usage.mdx b/network/wallets/react-native/usage.mdx new file mode 100644 index 0000000..e47bfd6 --- /dev/null +++ b/network/wallets/react-native/usage.mdx @@ -0,0 +1,364 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface. + +## Cloud Configuration + +Create a new project on WalletConnect Dashboard at https://dashboard.walletconnect.com and obtain a new project ID. + + + +## Initialization + + + +`@walletconnect/react-native-compat` must be installed and imported before any `@reown/*` dependencies for proper React Native polyfills. + +```ts +import "@walletconnect/react-native-compat"; +// Other imports +``` + + + +Create a new instance from `Core` and initialize it with your `projectId`. Next, create a WalletKit instance by calling `init` on `WalletKit`. Passing in the options object containing metadata about the app. + +The `pair` function will help us pair between the dapp and wallet and will be used shortly. + +```javascript +import { Core } from "@walletconnect/core"; +import { WalletKit } from "@reown/walletkit"; + +const core = new Core({ + projectId: process.env.PROJECT_ID, +}); + +const walletKit = await WalletKit.init({ + core, // <- pass the shared `core` instance + metadata: { + name: "Demo React Native Wallet", + description: "Demo RN Wallet to interface with Dapps", + url: "www.walletconnect.com", + icons: ["https://your_wallet_icon.png"], + redirect: { + native: "yourwalletscheme://", + }, + }, +}); +``` + +### Core Instance Sharing + +Starting from newer versions of WalletKit, Core instances are shared globally by default to optimize resource usage. This means that multiple Core instances with the same configuration will reuse the same underlying Core. + +**For parallel testing scenarios** where you need isolated Core instances, you have two options: + +#### Option 1: Use customStoragePrefix + +```javascript +const core = new Core({ + projectId: process.env.PROJECT_ID, + customStoragePrefix: `test-${Date.now()}`, // Unique prefix for each test +}); +``` + + +Don't use randomly generated `customStoragePrefix` in production - this will cause the client to create new storage each time it is initialized. The client will not be able to persist/read existing data and all existing sessions will be lost after each reload. + + +#### Option 2: Disable global Core sharing + +```javascript +// Set environment variable before initializing Core +process.env.DISABLE_GLOBAL_CORE = "true"; + +const core = new Core({ + projectId: process.env.PROJECT_ID, +}); +``` + + +The global Core sharing behavior was introduced to prevent resource waste when multiple SDK instances are created. If you're running parallel tests and experiencing cross-test interference, use one of the solutions above to ensure proper test isolation. + + +## Session + +A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires. + +### Namespace Builder + +With WalletKit (and @walletconnect/utils) we've published a helper utility that greatly reduces the complexity of parsing the `required` and `optional` namespaces. It accepts as parameters a `session proposal` along with your user's `chains/methods/events/accounts` and returns ready-to-use `namespaces` object. + +```javascript +// util params +{ + proposal: ProposalTypes.Struct; // the proposal received by `.on("session_proposal")` + supportedNamespaces: Record< // your Wallet's supported namespaces + string, // the supported namespace key e.g. eip155 + { + chains: string[]; // your supported chains in CAIP-2 format e.g. ["eip155:1", "eip155:2", ...] + methods: string[]; // your supported methods e.g. ["personal_sign", "eth_sendTransaction"] + events: string[]; // your supported events e.g. ["chainChanged", "accountsChanged"] + accounts: string[] // your user's accounts in CAIP-10 format e.g. ["eip155:1:0x453d506b1543dcA64f57Ce6e7Bb048466e85e228"] + } + >; +}; +``` + +Example usage + +```javascript +// import the builder util +import { WalletKit, WalletKitTypes } from '@reown/walletkit' +import { buildApprovedNamespaces, getSdkError } from '@walletconnect/utils' + +async function onSessionProposal({ id, params }: WalletKitTypes.SessionProposal){ + try{ + // ------- namespaces builder util ------------ // + const approvedNamespaces = buildApprovedNamespaces({ + proposal: params, + supportedNamespaces: { + eip155: { + chains: ['eip155:1', 'eip155:137'], + methods: ['eth_sendTransaction', 'personal_sign'], + events: ['accountsChanged', 'chainChanged'], + accounts: [ + 'eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb', + 'eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb' + ] + } + } + }) + // ------- end namespaces builder util ------------ // + + const session = await walletKit.approveSession({ + id, + namespaces: approvedNamespaces + }) + }catch(error){ + // use the error.message to show toast/info-box letting the user know that the connection attempt was unsuccessful + .... + + await walletKit.rejectSession({ + id: proposal.id, + reason: getSdkError("USER_REJECTED") + }) + } +} + + +walletKit.on('session_proposal', onSessionProposal) +``` + +If your wallet supports multiple namespaces e.g. `eip155`,`cosmos` & `near` +Your `supportedNamespaces` should look like the following example. + +```javascript +// ------- namespaces builder util ------------ // +const approvedNamespaces = buildApprovedNamespaces({ + proposal: params, + supportedNamespaces: { + eip155: {...}, + cosmos: {...}, + near: {...} + }, +}); +// ------- end namespaces builder util ------------ // +``` + +### Get Active Sessions + +You can get the wallet active sessions using the `getActiveSessions` function. + +```js +const activeSessions = walletKit.getActiveSessions(); +``` + +### EVM methods & events + +In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events: + +```ts +{ + //... + methods: [ + "eth_accounts", + "eth_requestAccounts", + "eth_sendRawTransaction", + "eth_sign", + "eth_signTransaction", + "eth_signTypedData", + "eth_signTypedData_v3", + "eth_signTypedData_v4", + "eth_sendTransaction", + "personal_sign", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + "wallet_getPermissions", + "wallet_requestPermissions", + "wallet_registerOnboarding", + "wallet_watchAsset", + "wallet_scanQRCode", + "wallet_sendCalls", + "wallet_getCallsStatus", + "wallet_showCallsStatus", + "wallet_getCapabilities", + ], + events: [ + "chainChanged", + "accountsChanged", + "message", + "disconnect", + "connect", + ] +} +``` + +### Session Approval + +In order to connect with a dapp, you will need to receive a WalletConnect URI (WCURI) and this will talk to our protocol to facilitate a pairing session. Therefore, you will need a test dapp in order to communicate with the wallet. We recommend testing with our [React V2 Dapp](https://react-app.walletconnect.com/) as this is the most up-to-date development site. + +In order to capture the WCURI, recommend having some sort of state management you will pass through a `TextInput` or QRcode instance. + +The `session_proposal` event is emitted when a dapp initiates a new session with a user's wallet. The event will include a `proposal` object with information about the dapp and requested permissions. The wallet should display a prompt for the user to approve or reject the session. If approved, call `approveSession` and pass in the `proposal.id` and requested `namespaces`. + +The `pair` method initiates a WalletConnect pairing process with a dapp using the given `uri` (QR code from the dapps). To learn more about pairing, checkout out the [docs](https://specs.walletconnect.com/2.0/specs/clients/core/pairing/). + +```javascript +import { getSdkError } from "@walletconnect/utils"; + +// Approval: Using this listener for sessionProposal, you can accept the session +walletKit.on("session_proposal", async (proposal) => { + const session = await walletKit.approveSession({ + id: proposal.id, + namespaces, + }); +}); + +// Call this after WCURI is received +await walletKit.pair({ uri: wcuri }); +``` + +### Session Rejection + +You can use the `getSDKError` function, which is available in the `@walletconnect/utils` for the rejection function [library](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/utils). + +```javascript +import { getSdkError } from "@walletconnect/utils"; + +// Reject: Using this listener for sessionProposal, you can reject the session +walletKit.on("session_proposal", async (proposal) => { + await walletKit.rejectSession({ + id: proposal.id, + reason: getSdkError("USER_REJECTED_METHODS"), + }); +}); +``` + +### Responding to Session requests + + + + + +The `session_request` event is triggered by a dapp when it needs the wallet to perform a specific action, such as signing a transaction. The event contains a `topic` and a `request` object, which will vary depending on the action requested. + +To respond to the request, the wallet can access the `topic` and `request` object by destructuring them from the event payload. To see a list of possible `request` and `response` objects, refer to the relevant JSON-RPC Methods for [Ethereum](https://docs.reown.com/advanced/multichain/rpc-reference/ethereum-rpc), [Solana](https://docs.reown.com/advanced/multichain/rpc-reference/solana-rpc), [Cosmos](https://docs.reown.com/advanced/multichain/rpc-reference/cosmos-rpc), or [Stellar](https://docs.reown.com/advanced/multichain/rpc-reference/stellar-rpc). + +As an example, if the dapp requests a `personal_sign` method, the wallet can extract the `params` array from the `request` object. The first item in the array is the hex version of the message to be signed, which can be converted to UTF-8 and assigned to a `message` variable. The second item in `params` is the user's wallet address. + +To sign the message, the wallet can use the `wallet.signMessage` method and pass in the message. The signed message, along with the `id` from the event payload, can then be used to create a `response` object, which can be passed into `respondSessionRequest`. + +The wallet then signs the message. `signedMessage`, along with the `id` from the event payload, can then be used to create a `response` object, which can be passed into `respondSessionRequest`. + +```javascript +walletKit.on("session_request", async (event) => { + const { topic, params, id } = event; + const { request } = params; + const requestParamsMessage = request.params[0]; + + // convert `requestParamsMessage` by using a method like hexToUtf8 + const message = hexToUtf8(requestParamsMessage); + + // sign the message + const signedMessage = await wallet.signMessage(message); + + const response = { id, result: signedMessage, jsonrpc: "2.0" }; + + await walletKit.respondSessionRequest({ topic, response }); +}); +``` + +To reject a session request, the response should be similar to this. + +```javascript +const response = { + id, + jsonrpc: "2.0", + error: { + code: 5000, + message: "User rejected.", + }, +}; +``` + +### Updating a Session + +The `session_update` event is emitted from the wallet when the session is updated by calling `updateSession`. To update a session, pass in the [topic](https://docs.reown.com/advanced/glossary#topics) and the new namespace. + +```javascript +await walletKit.updateSession({ topic, namespaces: newNs }); +``` + +### Extending a Session + +To extend the session, call the `extendSession` method and pass in the new `topic`. The `session_update` event will be emitted from the wallet. + +```javascript +await walletKit.extendSession({ topic }); +``` + +### Session Disconnect + +When either the dapp or the wallet disconnects from a session, a `session_delete` event will be emitted. It's important to subscribe to this event so you could keep your state up-to-date. + +To initiate a session disconnect, call the `disconnectSession` method and pass in the `topic` and `reason`. You can use the `getSDKError` utility function, which is available in the `@walletconnect/utils` [library](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/utils). + +```javascript +await walletKit.disconnectSession({ + topic, + reason: getSdkError("USER_DISCONNECTED"), +}); +``` + +### Emitting Session Events + +To emit session events, call the `emitSessionEvent` and pass in the params. If you wish to switch to chain/account that is not approved (missing from `session.namespaces`) you will have to update the session first. In the following example, the wallet will emit `session_event` that will instruct the dapp to switch the active accounts. + +```javascript +await walletKit.emitSessionEvent({ + topic, + event: { + name: "accountsChanged", + data: ["0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb"], + }, + chainId: "eip155:1", +}); +``` + +In the following example, the wallet will emit `session_event` when the wallet switches chains. + +```javascript +await walletKit.emitSessionEvent({ + topic, + event: { + name: "chainChanged", + data: 1, + }, + chainId: "eip155:1", +}); +``` diff --git a/network/wallets/react-native/verify.mdx b/network/wallets/react-native/verify.mdx new file mode 100644 index 0000000..3fd7c16 --- /dev/null +++ b/network/wallets/react-native/verify.mdx @@ -0,0 +1,72 @@ +--- +title: Verify API +--- + +Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. +Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect's domain registry. + +When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious. + +These are: + + + + + +## Disclaimer + +Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof. + +## Domain risk detection + +The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`. + +- Domain match: The domain linked to this request has been verified as this application's domain. + - This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`. +- Unverified: The domain sending the request cannot be verified. + - This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`. +- Mismatch: The application's domain doesn't match the sender of this request. + - This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID` +- Threat: This domain is flagged as malicious and potentially harmful. + - This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`. + +### Implementation + +To check the Verify API validations and whether or not your user is interacting with potentially malicious app, you can do so by accessing the `verifyContext` included in the request payload. + +```javascript +... +walletKit.on("auth_request", async (authRequest) => { + const { verifyContext } = authRequest + const validation = verifyContext.verified.validation // can be VALID, INVALID or UNKNOWN + const origin = verifyContext.verified.origin // the actual verified origin of the request + const isScam = verifyContext.verified.isScam // true if the domain is flagged as malicious + + // if the domain is flagged as malicious, you should warn the user as they may lose their funds - check the `Threat` case for more info + if(isScam) { + // show a warning screen to the user + // and proceed only if the user accepts the risk + } + + switch(validation) { + case "VALID": + // proceed with the request - check the `Domain match` case for more info + break + case "INVALID": + // show a warning dialog to the user - check the `Mismatch` case for more info + // and proceed only if the user accepts the risk + break + case "UNKNOWN": + // show a warning dialog to the user - check the `Unverified` case for more info + // and proceed only if the user accepts the risk + break + } +}) +``` + +For live demo examples of the intended Verify API flows, check out our demo apps: + +- [Demo Web Wallet](https://react-wallet.walletconnect.com) +- [Demo React Native Wallet](https://github.com/WalletConnect/react-native-examples/tree/main/wallets/rn_cli_wallet) +- [Demo App](https://react-app.walletconnect.com/) - you can toggle between the verify states by clicking on the `gear` & selecting the decided Validation before connecting to the wallet +- [Demo Malicious App](https://malicious-app-verify-simulation.vercel.app/) - this app is flagged as malicious and will have the `isScam` parameter set to `true` in the `verifyContext` of the request diff --git a/network/wallets/walletguide/chain-list.mdx b/network/wallets/walletguide/chain-list.mdx new file mode 100644 index 0000000..d623181 --- /dev/null +++ b/network/wallets/walletguide/chain-list.mdx @@ -0,0 +1,17 @@ +--- +title: Supported Chains +--- + +import { ChainList } from "/snippets/chainlist.mdx" + +## Overview + +This page provides a list of chains on the [WalletGuide](https://walletguide.walletconnect.network/). WalletGuide is a tool that allows users to discover wallets and dapps that support their preferred blockchain. + +On this page, you can: + +- Filter chains by Mainnet / Testnet +- Search for chains by name +- Click on a chain to copy its Chain ID + + diff --git a/network/wallets/walletguide/explorer-submission.mdx b/network/wallets/walletguide/explorer-submission.mdx new file mode 100644 index 0000000..5ccde1e --- /dev/null +++ b/network/wallets/walletguide/explorer-submission.mdx @@ -0,0 +1,183 @@ +--- +title: WalletGuide Submission +--- + + + +Submitting a project to the WalletConnect Dashboard Explorer is recommended but optional. You can still use WalletConnect services without submitting your project. +However, doing so ensures that your project is listed under [WalletGuide](https://walletguide.walletconnect.network/?utm_source=walletconnect-docs&utm_medium=cloud&utm_campaign=github) and [Cloud Explorer API](./explorer.md). + + + +## Creating a New Project + +First, open the WalletConnect Dashboard by navigating to [dashboard.walletconnect.com](https://dashboard.walletconnect.com/?utm_source=blog&utm_medium=devrel&utm_campaign=conversion) and signing in. If you don’t have an account yet, please create one before proceeding. + +- Once you're logged in, navigate to your team view and click the **"+ Project"** button. + + + + + +- Select **"Wallet"**, enter a project name, and click **"Add"**. + + + + + + +## Project Details + +- From the project Dashboard, click on the **"WalletGuide"** tab in the top navigation. + + + + + +- Click **"Start submission"** to begin the submission wizard. + + + + + +## Project Submission + +The submission is a multi-step wizard. Follow each step to complete your listing: + +### Step 1 — Describe your project + +Fill in your wallet's basic details: + +- **Name** — This will appear in WalletGuide and other SDKs using the WalletConnect API +- **Link** — The homepage URL of your project +- **Description** — A short description of your wallet +- **Logo** — Upload your wallet's logo + +Click **"Continue"** to proceed. + + + + + +### Step 2 — Add wallet types + +Select the wallet types that apply to your project and provide the required links for each: + +- Mobile Wallet +- Desktop Wallet +- Web Wallet +- Browser Extension + +Click **"+ Add"** next to each applicable type to add its details. Click **"Continue"** when done. + + + + + + + + + +### Step 3 — Add chains + +Select all chains your project supports. You can search by name or browse by ecosystem (EVM, Solana, Cosmos, etc.). Toggle **"My wallet supports custom chains"** if applicable. + +Click **"Continue"** when done. + + + + + +### Step 4 — Submit your listing + +Add **Test instructions** to help the review team validate your WalletConnect integration. Clear test instructions help accelerate the review process. + +Click **"Submit"** to send your listing for review. + + + + + +## Review Timeline + +After submitting, your listing will go through a QA review to verify your WalletConnect integration is working correctly. + +- **Initial review** takes **7–10 business days** on average. You can track the status in the **WalletGuide** tab of your project — it will show as **"In Review"** while pending. +- **Once approved**, changes take approximately **24 hours** to go live on the production WalletGuide page. + +If your submission is not accepted, the reason will be noted in the WalletGuide tab and in the notification email. You can make the necessary changes and resubmit at any time. + +## How do we test wallets? + +In order to offer a great user experience in our APIs and SDKs every Cloud submission goes through a QA process to make sure that the integration of the WalletConnect protocol is working correctly. + +The following list details our QA flow and how to reproduce it: + +| Test Case | Steps | Expected Results | +|-----------------------------------------------|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------| +| **Set Up** | 1. Download the wallet
2. Install the wallet app
3. Sign up for an account
4. Create one or more accounts | 1. N/A
2. The app is installed
3. I have an account
4. I have one or more accounts | +| **Connect to dapp via web browser** | 1. Open the Reown connection page [appkit-lab.reown.com](https://appkit-lab.reown.com/) from a PC
2. Press "Connect Wallet" and select Reown.
3. Open the wallet app and scan QR code.
4. Accept the connection request. | 1. The app is set up correctly
2. A modal with wallet options appears
3. A QR code is shown and scanned
4. Connection established, wallet data displayed on site | +| **Connect to dapp via mobile browser (Deep-link)** | 1. Open [appkit-lab.reown.com](https://appkit-lab.reown.com/) on mobile.
2. Select a default option (e.g., Wagmi for EVM chains), click "Custom Wallet," enter wallet name and deep link, then add it. Press "Connect Wallet" and select the new wallet.
3. Accept connection request in the wallet app. | 1. N/A
2. A form appears to enter wallet data, new wallet option is visible.
3. User is redirected to the wallet app, sees a connection request, and successfully connects. On Android, user is redirected back to the website. | +| **Switch chains - dapp side** | 1. After connecting, click the modal button (top right of website).
2. Click the first button in the modal to switch chains.
3. Select a chain, close the modal, and press "Send Transaction." | 1. Modal with account info appears.
2. A new view with supported chains appears.
3. The transaction request in the wallet shows the correct chain. | +| **Switch Chains - wallet side (if supported)** | 1. Check if wallet supports chain switching. If so, switch to a different chain. | 1. The chain change is reflected on the website. The first card displays the current chain ID. | +| **Accounts Switching - wallet side** | 1. Switch accounts in the wallet app. | 1. The account switch is reflected in the modal’s account view on the website. | +| **Disconnect a wallet** | 1. Press "Disconnect" in the Wallet App (if available).
2. Alternatively, press "Disconnect" from the dApp. | 1. The session disappears from both the dApp and Wallet App.
2. The session disappears from both the dApp and Wallet App. | +| **Verify API** | 1. Open [malicious-app-verify-simulation.vercel.app](https://malicious-app-verify-simulation.vercel.app/).
2. Select a wallet-supported chain, press "Connect."
3. Scan the QR code with the wallet. | 1. N/A
2. A QR code modal appears.
3. The wallet flags the site as malicious. | + + +### Chain Specific + +The following test cases only apply for wallets supporting a particular set of chains. + + + + +| Test Case | Steps | Expected Results | +|-------------------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------| +| **Supporting personal_sign** | 1. Connect the wallet.
2. Press the “Sign Message” button.
3. Accept the signature request on the wallet. | 1. N/A
2. A modal should popup on the wallet app requesting a signature.
3. Once accepted and signed, the hash should show up on the website. | +| **Supporting eth_signTypedData_v4** | 1. Connect the wallet.
2. Press the “Sign Typed Data” button.
3. Accept the signature request on the wallet. | 1. N/A
2. A modal should popup on the wallet app requesting a signature.
3. Once accepted and signed, the hash should show up on the website. | +| **Supporting eth_sendTransaction** | 1. Connect the wallet.
2. Press the “Send Transaction” button. | 1. N/A
2. A modal should popup on the wallet app requesting a signature. | + + +
+ + + +| Test Case | Steps | Expected Results | +|-------------------------------------|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------| +| **Supporting solana_signMessage** | 1. Connect the wallet to [appkit-lab.reown.com/appkit/?name=solana](https://appkit-lab.reown.com/appkit/?name=solana).
2. Press the "Sign Message" button.
3. Accept the signature request on the wallet. | 1. N/A.
2. A modal should pop up on the wallet app requesting a signature.
3. Once accepted and signed, the hash should show up on the website. | +| **Supporting solana_signTransaction** | 1. Connect the wallet to [appkit-lab.reown.com/appkit/?name=solana](https://appkit-lab.reown.com/appkit/?name=solana).
2. Press the "Sign Transaction" button.
3. Accept the signature request on the wallet. | 1. N/A.
2. A modal should pop up on the wallet app requesting a signature.
3. Once accepted and signed, the hash should show up on the website. | +| **Supporting v0 Transactions** | 1. Connect the wallet to [appkit-lab.reown.com/appkit/?name=solana](https://appkit-lab.reown.com/appkit/?name=solana).
2. Press the "Sign Versioned Transaction" button.
3. Accept the signature request on the wallet. | 1. N/A.
2. A modal should pop up on the wallet app requesting a signature.
3. Once accepted and signed, the hash should show up on the website. | + + +
+
+ +## FAQ + + +You should set the EIP-6963 RDNS (Reverse Domain Name System) value of your wallet. +This value uniquely identifies your wallet and allows us to properly detect and discover it when it is installed in the user's browser. + + + +In the context of a browser extension, the reverse domain (RDNS): + +- Serves as a unique identifier for your wallet +- Enables wallet discovery via the EIP-6963 standard +- Allows our system to detect when your wallet extension is installed + +Without the correct RDNS value, your wallet may not be discoverable. + + +## What's Next? + +Now depending on whether or not your submission met all parameters, you will receive an email from the WalletConnect team with the status of your submission. The **WalletGuide** tab of your project will also reflect the current status. + + + + + +If your submission was not accepted, you can make the necessary changes and resubmit your project for review. The reason for rejection will be mentioned in the email and in the WalletGuide tab of your project. + +In case of any questions, feel free to ask on [Github Discussions](https://github.com/orgs/WalletConnect/discussions/categories/explorer-support) diff --git a/network/wallets/walletguide/explorer.mdx b/network/wallets/walletguide/explorer.mdx new file mode 100644 index 0000000..32036cc --- /dev/null +++ b/network/wallets/walletguide/explorer.mdx @@ -0,0 +1,113 @@ +--- +title: Explorer API +--- + +The Cloud Explorer API currently offers the following functionality: + +- [Listings](#listings) - Allows for fetching of wallets and dApps listed in the [WalletGuide](https://walletguide.walletconnect.network/). +- [Logos](#logos) - Provides logo assets in different sizes for a given Cloud explorer entry. + +### Listings + +By default listings endpoints return all data for provided type. You can use following query params to return paginated data or search for a specific listing by its name: + +| Param | Required? | Description | +| ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------ | +| projectId | Required | Your WalletConnect Dashboard Project ID (from [dashboard.walletconnect.com](https://dashboard.walletconnect.com/)) | +| entries | | Specifies how many entries will be returned (must be used together with page param) | +| page | | Specifies current page (must be used with entries param) | +| search | | Returns listings whose name matches provided search query | +| ids | | Returns listings whose id matches provided ids (e.g. `&ids=LISTING_ID1,LISTING_ID2`) | +| chains | | Returns listings that support at least one of the provided chains
(e.g. `?chains=eip155:1,eip155:137`) | +| platforms | | Returns listings that support at least one of the provided platforms
(e.g. `?platforms=ios,android,mac,injected`) | +| sdks | | Returns listings that support at least one of the provided Reown SDKs
(e.g. `?sdks=sign_v1,sign_v2,auth_v1`) | +| standards | | Returns listings that support at least one of the provided standards
(e.g. `?standards=eip-712,eip-3085`) | +| ~~version~~ | | Deprecated - replaced by `sdks` param. Specifies supported Sign version (1 or 2) | + +#### `GET /v3/wallets` + +Returns a JSON object containing all wallets listed in the cloud explorer. + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/wallets?projectId=YOUR_PROJECT_ID&entries=5&page=1` (will return the first 5 wallets from the first page) +- `GET https://explorer-api.walletconnect.com/v3/wallets?projectId=YOUR_PROJECT_ID&platforms=injected` (will only return injected wallets) + +#### `GET /v3/dapps` + +Returns a JSON object containing all dApps listed in the public cloud explorer. + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/dapps?projectId=YOUR_PROJECT_ID&entries=5&page=1` + +#### `GET /v3/hybrid` + +Returns a JSON object containing all hybrids listed in the public cloud explorer. + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/hybrid?projectId=YOUR_PROJECT_ID&entries=5&page=1` + +#### `GET /v3/all` + +Returns a JSON object containing all entries listed in the public cloud explorer. + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/all?projectId=YOUR_PROJECT_ID&entries=5&page=1` + +#### `GET /v3/all?projectId=YOUR_PROJECT_ID&ids=LISTING_ID1,LISTING_ID2` + +Returns a JSON object containing the entry listings by ID, which can be useful for allowlisting purposes.
+You can find and copy listing ids from our [WalletGuide](https://walletguide.walletconnect.network/) + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/all?projectId=YOUR_PROJECT_ID&ids=be49f0a78d6ea1beed3804c3a6b62ea71f568d58d9df8097f3d61c7c9baf273d,4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0` + +### Chains + +By default chains endpoint returns all chains registered under [CASA Namespace](https://github.com/ChainAgnostic/CASA) and that were approved by following our [Add Chain issue template](https://github.com/WalletConnect/walletconnect-monorepo/issues/new?assignees=&labels=type%3A+new+chain+request&template=new_chain_to_explorer.md&title=) + +#### Query Parameters + +You can use following query params to query chains by its namespace and exclude testnets: + +| Param | Description | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------- | +| testnets | Determines if testnets should be included in the response
(e.g. `?testnets=false`, defaults to `true` if not provided) | +| namespaces | Returns chains that belong to one of the provided namespaces
(e.g. `?namespaces=eip155,cosmos,solana`) | + +#### `GET /v3/chains` + +Returns all chains registered under [CASA Namespace](https://github.com/ChainAgnostic/CASA) and that were approved by following our [Add Chain issue template](https://github.com/WalletConnect/walletconnect-monorepo/issues/new?assignees=&labels=type%3A+new+chain+request&template=new_chain_to_explorer.md&title=) + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/chains?projectId=YOUR_PROJECT_ID` +- `GET https://explorer-api.walletconnect.com/v3/chains?projectId=YOUR_PROJECT_ID&testnets=false` +- `GET https://explorer-api.walletconnect.com/v3/chains?projectId=YOUR_PROJECT_ID&namespaces=eip155,cosmos` + +### Logos + +#### Path Parameters + +| Param | Description | +| ----- | ---------------------------------------------------------------------------------------- | +| size | Determines resolution of returned image can be one of: `sm`, `md` or `lg` | +| id | Corresponds to a Cloud Explorer entry's `image_id` field as returned by the Listings API | + +#### Query Parameters + +| Param | Required? | Description | +| --------- | --------- | ------------------------------------------------------------------------------------------------------ | +| projectId | Required | Your WalletConnect Dashboard Project ID (from [dashboard.walletconnect.com](https://dashboard.walletconnect.com/)) | + +#### `GET /v3/logo/:size/:image_id` + +Returns the image source of the logo for `image_id` sized according `size`. + +Examples: + +- `GET https://explorer-api.walletconnect.com/v3/logo/md/32a77b79-ffe8-42c3-61a7-3e02e019ca00?projectId=YOUR_PROJECT_ID` diff --git a/network/wallets/walletguide/overview.mdx b/network/wallets/walletguide/overview.mdx new file mode 100644 index 0000000..d59db11 --- /dev/null +++ b/network/wallets/walletguide/overview.mdx @@ -0,0 +1,47 @@ +--- +title: "Chain Onboarding" +--- + +The WalletConnect protocol is multi-chain by design. By using the [CAIP-25 standard](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md), WalletConnect aims to provide a standardized process for onboarding new chains into our ecosystem. To get started, follow the following steps. + +## Register Chain with the Explorer + + +**Registering a chain with the Explorer does not impact or improve the ability for wallets and dapps to support your chain.** It is simply a way for users to discover wallets and dapps that support your chain by: + +- Browsing the [Chains List](./chain-list) +- Filtering results programmatically via the [Explorer API](/network/wallets/walletguide/explorer) + +**It is still up to wallets and dapps to provide concrete support for your chain once it is listed as part of the Explorer.** + + +If you don't see your chain listed in this [list](./chain-list), then you will need to create an issue in GitHub to to get the process started. +You can do so by clicking [here](https://github.com/WalletConnect/walletconnect-monorepo/issues/new?assignees=&labels=type%3A+new+chain+request&template=new_chain_to_explorer.md&title=). Once your chain is added to this list, wallets & dapps will be able to indicate support for your chain via [WalletConnect Dashboard](https://dashboard.walletconnect.com). + +## CASA + +To register a chain, you must know both its native representation (the chainID used with that kind of blockchain) _and_ its Chain Agnostic Standards Alliance representation, which can be found reading the relevant CAIP-2 profiles on the [CASA Namespaces Project Docs](https://namespaces.chainagnostic.org/). If no such profile yet exists, you can collaborate with an expert in the respective chain's tooling and submit a [namespaces PR](https://github.com/ChainAgnostic/namespaces/?tab=readme-ov-file#namespaces) to add one. + +## Add RPC Methods + +Integrate RPC method support into the example wallets and dapp. + +**Example Wallet** + +- [Demo](https://react-wallet.walletconnect.com/) +- [GitHub](https://github.com/WalletConnect/web-examples/tree/main/advanced/wallets/react-walletkit) + +**Example Dapp** + +- [Demo](https://react-app.walletconnect.com/) +- [GitHub](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) + +## Promote + +For a chain to benefit users, its prominent wallets and dApps must be registered in the Explorer. Encourage them to join the API, allowing users to view the wallets as options when connecting to a dApp. + +## Wagmi & Viem + +If the chain you are registering is EVM compliant, we highly recommend you to integrate it with [Viem](https://viem.sh/docs/clients/chains.html), an ethereum library used by Wagmi and Reown. To accomplish this you will need to open a GitHub Pull Request in the Viem repository. + +- [Viem GitHub Repository](https://github.com/wagmi-dev/viem/tree/main/src/chains/definitions) diff --git a/network/wallets/walletguide/wallet-list.mdx b/network/wallets/walletguide/wallet-list.mdx new file mode 100644 index 0000000..80315b0 --- /dev/null +++ b/network/wallets/walletguide/wallet-list.mdx @@ -0,0 +1,16 @@ +--- +title: Wallets +--- + +import { WalletList } from "/snippets/walletlist.mdx" + +## Overview + +This page provides a list of wallets on the [WalletGuide](https://walletguide.walletconnect.network/). WalletGuide is a tool that allows users to discover wallets and all the information like WalletId, networks, supported devices, and official links. + +On this page, you can: + +- Search for wallets by name +- Click on a wallet to copy the WalletId + + \ No newline at end of file diff --git a/network/wallets/web/best-practices.mdx b/network/wallets/web/best-practices.mdx new file mode 100644 index 0000000..39500d6 --- /dev/null +++ b/network/wallets/web/best-practices.mdx @@ -0,0 +1,202 @@ +--- +title: Best Practices +--- + +The purpose of this guide is to show the best practices in regards of the WalletKit client usage. The goal is to provide the best user experience that just works in every circumstances. + + + In order to ensure the best user experience and flawless connection flow, please make sure that WalletKit is initialized immediately after your app launch, especially if launched via a WalletConnect Deep Link. It guarantees that websocket connection is opened immediately and all requests are received by your wallet + + +## Pairing + +A pairing is a connection between a wallet and a dapp that has fixed permissions to only allow a dapp to propose a session through it. Dapp can propose infinite number of sessions on one pairing. Wallet must use a pair method from WalletKit client to pair with dapp. + +```typescript +const uri = 'xxx'; // pairing uri +try { + await walletKit.pair({ uri }); +} catch (error) { + // some error happens while pairing - check Expected errors section +} +``` + +### Pairing Expiry + +A pairing expiry event is triggered whenever a pairing is expired. The expiry for inactive pairing is 5 mins, whereas for active pairing is 30 days. A pairing becomes active when a session proposal is received and user successfully approves it. This event helps to know when given pairing expires and update UI accordingly. + +```typescript +core.pairing.events.on("pairing_expire", (event) => { + // pairing expired before user approved/rejected a session proposal + const { topic } = topic; +}); +``` + +### Expected User flow + +### Pairing Flow + + + + + +### Pairing Error + + + + + +### Expected Errors + +While pairing the following errors might occur: + +- No Internet connection error or pairing timeout when scanning QR with no Internet connection + - User should pair again with Internet connection +- Pairing expired error when scanning a QR code with expired pairing + - User should refresh a QR code and scan again +- Pairing with existing pairing is not allowed + - User should refresh a QR code and scan again. I usually happens when user scans an already paired QR code. + +## Session Proposal + +A session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Whenever a user wants to establish a connection between a wallet and a dapp, one should approve a session proposal. + +### User Action Feedback + +Whenever user approves or rejects a session proposal, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +Approving session + +```typescript + try { + await walletKit.approveSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` + +Rejecting session + +```typescript + try { + await walletKit.rejectSession(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` + +### Session Proposal Expiry + +A session proposal expiry is 5 mins. It means a given proposal is stored for 5 mins in the SDK storage and user has 5 mins for approval or rejection decision. After that time the below event is emitted and proposal modal should be removed from the app's UI. + +```typescript +walletKit.on("proposal_expire", (event) => { + // proposal expired and any modal displaying it should be removed + const { id } = event; +}); +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session proposal the following errors might occurs: + +- No Internet connection + - It happens when a user tries to approve or reject session proposal with no Internet connection +- Session proposal expired + - It happens when users tries to approve or reject expired session proposal +- Invalid namespaces + - It happens when a validation of session namespaces fails +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Session Request + +A session request represents the request sent by a dapp to a wallet. + +### User Action Feedback + +Whenever user approves or rejects a session request, wallet should show loading indicators in a moment of the button press until Relay acknowledgement is received for any of this actions. + +```typescript + try { + await walletKit.respondSessionRequest(params); + // update UI -> remove the loader + } catch (error) { + // present error to the user + } +``` + +### Session Request Expiry + +A session request expiry is defined by a dapp. It's value must be between now() + 5mins and now() + 7 days. After the session request expires the below event is emitted and session request modal should be removed from the app's UI. + +```typescript +walletKit.on("session_request_expire", (event) => { + // request expired and any modal displaying it should be removed + const { id } = event; +}); +``` + +### Expected User flow + +### Approve or Reject Session Proposal + + + + + +### Error Handling + + + + + +### Expected Errors + +While approving or rejecting a session request the following error might occur: + +- Invalid session + - This error might happen when user approves or rejects a session request on expired session +- Session request expired + - This error might happen when user approves or rejects a session request that already expires +- Timeout + - It happens when Relay doesn't acknowledge session settle publish within 10s + +## Web Socket Connection State + +The Web Socket connection state tracks the connection with the relay server, event is emitted whenever a connection state changes. + +```typescript +core.relayer.on("relayer_connect", () => { + // connection to the relay server is established +}) + +core.relayer.on("relayer_disconnect", () => { +// connection to the relay server is lost +}) + +``` + +### Expected User flow + +### Connection State + + + ![](https://mintlify.s3.us-west-1.amazonaws.com/reown-5552f0bb/images/assets/connection_state.gif) + diff --git a/network/wallets/web/chain-abstraction.mdx b/network/wallets/web/chain-abstraction.mdx new file mode 100644 index 0000000..1fe0e8a --- /dev/null +++ b/network/wallets/web/chain-abstraction.mdx @@ -0,0 +1,92 @@ +--- +title: "Chain Abstraction" +--- + +import HowItWorks from "/snippets/walletkit/shared/chain-abstraction/intro.mdx"; +import ErrorHandling from "/snippets/walletkit/shared/chain-abstraction/error-handling.mdx"; + + + +## Methods + + +Make sure you are using canary version of `@reown/walletkit`. + + +Following are the methods from WalletKit that you will use in implementing chain abstraction. + +### Prepare + +This method checks if a transaction requires additional bridging transactions beforehand. + +```typescript +public abstract prepare(params: { + transaction: ChainAbstractionTypes.PartialTransaction; +}): ChainAbstractionTypes.PrepareResponse; +``` + +### Execute + +Helper method used to broadcast the bridging and initial transactions and wait for them to be completed. + +```typescript +public abstract execute(params: { + orchestrationId: ChainAbstractionTypes.OrchestrationId; + bridgeSignedTransactions: ChainAbstractionTypes.SignedTransaction[]; + initialSignedTransaction: ChainAbstractionTypes.SignedTransaction; +}): ChainAbstractionTypes.ExecuteResult; +``` + +## Usage + +When sending a transaction, first check if chain abstraction is needed using the `prepare` method. +If it is needed, you must sign all the fulfillment transactions and use the `execute` method. +Here's a complete example: + +```typescript +// Check if chain abstraction is needed +const result = await walletKit.chainAbstraction.prepare({ + transaction: { + from: transaction.from as `0x${string}`, + to: transaction.to as `0x${string}`, + // @ts-ignore - cater for both input or data + input: transaction.input || (transaction.data as `0x${string}`), + chainId: chainId, + }, +}); + +// Handle the prepare result +if ('success' in result) { + if ('notRequired' in result.success) { + // No bridging required, proceed with normal transaction + console.log('no routing required'); + } else if ('available' in result.success) { + const available = result.success.available; + + // Sign all bridge transactions and initial transaction + const bridgeTxs = available.route.map(tx => tx.transactionHashToSign); + const signedBridgeTxs = bridgeTxs.map(tx => wallet.signAny(tx)); + const signedInitialTx = wallet.signAny(available.initial.transactionHashToSign); + + // Execute the chain abstraction + const result = await walletKit.chainAbstraction.execute({ + bridgeSignedTransactions: signedBridgeTxs, + initialSignedTransaction: signedInitialTx, + orchestrationId: available.routeResponse.orchestrationId, + }); + } +} +``` + +For example, check out implementation of chain abstraction in [sample wallet](https://github.com/reown-com/web-examples/tree/main/advanced/wallets/react-wallet-v2) built with React. + + + +## Testing + +To test Chain Abstraction, you can use the [AppKit laboratory](https://appkit-lab.reown.com/library/wagmi/) and try sending [USDC/USDT](/network/wallets/features/chain-abstraction#what-are-the-supported-tokens-and-networks%3F) with any chain abstraction supported wallet. +You can also use this [sample wallet](https://react-wallet.walletconnect.com) for testing. + + \ No newline at end of file diff --git a/network/wallets/web/cloud/analytics.mdx b/network/wallets/web/cloud/analytics.mdx new file mode 100644 index 0000000..f78ba0b --- /dev/null +++ b/network/wallets/web/cloud/analytics.mdx @@ -0,0 +1,7 @@ +--- +title: Analytics +--- + +import Analytics from "/snippets/cloud/analytics.mdx"; + + diff --git a/network/wallets/web/cloud/explorer-submission.mdx b/network/wallets/web/cloud/explorer-submission.mdx new file mode 100644 index 0000000..e5f11c8 --- /dev/null +++ b/network/wallets/web/cloud/explorer-submission.mdx @@ -0,0 +1,7 @@ +--- +title: Explorer Submission +--- + +import ExplorerSubmission from "/snippets/cloud/explorer-submission.mdx"; + + diff --git a/network/wallets/web/cloud/relay.mdx b/network/wallets/web/cloud/relay.mdx new file mode 100644 index 0000000..5f9e1c0 --- /dev/null +++ b/network/wallets/web/cloud/relay.mdx @@ -0,0 +1,7 @@ +--- +title: Relay +--- + +import Relay from "/snippets/cloud/relay.mdx"; + + diff --git a/network/wallets/web/eip5792.mdx b/network/wallets/web/eip5792.mdx new file mode 100644 index 0000000..a09b8bf --- /dev/null +++ b/network/wallets/web/eip5792.mdx @@ -0,0 +1,284 @@ +--- +title: Wallet Call API +--- + +WalletConnect supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. +Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities. + +- `wallet_sendCalls`: Requests that a wallet submits a batch of calls. +- `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet_sendCalls. +- `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet_sendCalls. +- `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication). + +## Usage + + + + ## Capabilities in CAIP-25 Connection Requests + +CAIP-25 defines how capabilities can be expressed in wallet-to-dapp connections. These capabilities control how methods like `wallet_sendCalls` behave. + +### Session Properties + +In a connection request, dapps can request capabilities via `sessionProperties`. These can be universal (across all chains) or chain-specific: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": [], + "strict": [], + "exoticThirdThing": [] + }, + "atomic": { + "status": "supported" + } +} +``` + +### Scoped Properties + +For chain-specific capabilities, dapps use `scopedProperties`: + +```json +"scopedProperties": { + "eip155:8453": { + "paymasterService": { + "supported": true + }, + "sessionKeys": { + "supported": true + } + }, + "eip155:84532": { + "auxiliaryFunds": { + "supported": true + } + } +} +``` + +### Wallet Response + +A wallet's response should indicate which capabilities it actually supports, following EIP-5792 and CAIP-25: + +```json +"sessionProperties": { + "expiry": "2022-12-24T17:07:31+00:00", + "caip154": { + "supported": "true" + }, + "flow-control": { + "loose": ["halt", "continue"], + "strict": ["continue"] + }, + "atomic": { + "status": "ready" + } +}, +"scopedProperties": { + "eip155:1": { + "atomic": { + "status": "supported" + } + }, + "eip155:137": { + "atomic": { + "status": "unsupported" + } + }, + "eip155:84532": { + "eip155:83532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": { + "auxiliaryFunds": { + "supported": false + }, + "atomic": { + "status": "supported" + } + } + } +} +``` +- Capabilities shared across all address in a namespace can be expressed at top-level +- Address-specific capabilities can include exceptions to scope-wide capabilities + +### Atomic Capability + +According to EIP-5792, the `atomic` capability specifies how the wallet will execute batches of transactions. It has three possible values: + +- `supported` - The wallet will execute calls atomically and contiguously +- `ready` - The wallet can upgrade to support atomic execution pending user approval +- `unsupported` - The wallet provides no atomicity guarantees + +This capability is expressed per chain and is crucial for determining how `wallet_sendCalls` with `atomicRequired: true` will be handled. + + ### Example + The `wallet_getCapabilities` method is used to request information about what capabilities a wallet supports. Following EIP-5792, here's how it should be implemented: + + #### Request + ```json + { + "id": 1, + "jsonrpc": "2.0", + "method": "wallet_getCapabilities", + "params": ["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]] + } + ``` + + #### Response + The wallet should return a response following EIP-5792, where capabilities are organized by chain ID: + + ```json + { + "id": 1, + "jsonrpc": "2.0", + "result": { + "0x2105": { + "atomic": { + "status": "supported" + } + }, + "0x14A34": { + "atomic": { + "status": "unsupported" + } + } + } + } + ``` + + + + ### Implementation + When implementing `wallet_sendCalls`, wallets must follow these requirements: + + #### Connection Approval + - Only approve this method during the connection approval flow if your wallet can implement it correctly + - Define the `atomic` capability per chain/account in the CAIP-25 response + + #### Request Format + ```json + { + "id": 12345, + "version": "2.0", + "method": "wc_sessionRequest", + "params": { + "chainId": "caip-2-chain-id", + "request": { + "method": "wallet_sendCalls", + "params": { + "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "chainId": "0x01", + "atomicRequired": true, + "calls": [ + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + { + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "value": "0x182183", + "data": "0xfbadbaf01" + } + ] + } + } + } + } + ``` + + #### Core Implementation Requirements + - Execute calls in the exact order specified in the request + - Do not wait for any calls to be finalized before completing the batch + - If the user rejects the request, do not send any calls + + #### Atomic Execution Behavior + When `atomicRequired` is `true`: + - Execute all calls atomically (either all succeed or none have any effect) + - Execute all calls contiguously (no other transactions between batch calls) + - If your wallet can upgrade from `ready` to `supported` atomicity, do so before executing + + When `atomicRequired` is `false`: + - You may execute calls sequentially without atomicity guarantees + - You may execute atomically if your wallet supports it + - You may upgrade to `supported` atomicity and execute atomically + + #### Response Enrichment + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + + + ### Example + To enhance the user experience and eliminate the need for app switching, wallets can enrich the wallet_sendCalls response with caip2 id and transactionHash to let the Universal Provider resolve the transaction hash. + + To implement this functionality, the response for wallet_sendCalls should be enriched with capabilities: + + ```json + { + "id": "...", + "capabilities": { + "caip345": { + "caip2": "eip155:1", + "transactionHashes": ["..."], + } + } + } + ``` + + Specify the `scopedProperties` when approving a session: + + ```json + "scopedProperties": { + "eip155": { + "walletService": [{ + "url": "", + "methods": ["wallet_getCallsStatus"] + }] + } + } + ``` + + ### Response Format + The response format for `wallet_getCallsStatus` varies based on the execution method: + + #### For Atomic Execution + ```json + { + "receipts": [/* single receipt or array of receipts */], + "atomic": true + } + ``` + + #### For Non-Atomic Execution + ```json + { + "receipts": [/* array of receipts for all transactions */], + "atomic": false + } + ``` + + + For non-atomic execution, include all transactions in the receipts array, even those that were included on-chain but eventually reverted. + + + + +## References +- EIP-5792: https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability +- CAIP-25 namespaces: https://github.com/ChainAgnostic/namespaces/blob/main/eip155/caip25.md diff --git a/network/wallets/web/installation.mdx b/network/wallets/web/installation.mdx new file mode 100644 index 0000000..a0ee763 --- /dev/null +++ b/network/wallets/web/installation.mdx @@ -0,0 +1,23 @@ +--- +title: Installation +--- + +Install Wallet SDK using npm or yarn. + + +```bash npm +npm install @reown/walletkit @walletconnect/utils @walletconnect/core +``` +```bash Yarn +yarn add @reown/walletkit @walletconnect/utils @walletconnect/core +``` +```bash Bun +bun add @reown/walletkit @walletconnect/utils @walletconnect/core +``` +```bash pnpm +pnpm add @reown/walletkit @walletconnect/utils @walletconnect/core +``` + +## Next Steps + +Now that you've installed WalletKit, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK. diff --git a/network/wallets/web/one-click-auth-siws.mdx b/network/wallets/web/one-click-auth-siws.mdx new file mode 100644 index 0000000..bda6500 --- /dev/null +++ b/network/wallets/web/one-click-auth-siws.mdx @@ -0,0 +1,132 @@ +--- +title: One-click Auth / SIWS +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Solana](https://github.com/phantom/sign-in-with-solana) (SIWS) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWS messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWS messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Solana ecosystem. + +## Handling Authentication Requests + +To handle incoming authentication requests, subscribe to the `session_authenticate` event. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```typescript +walletKit.on("session_authenticate", async (payload) => { + // Process the authentication request here. + // Steps include: + // 1. Populate the authentication payload with the supported chains and methods + // 2. Format the authentication message using the payload and the user's account + // 3. Present the authentication message to the user + // 4. Sign the authentication message(s) to create a verifiable authentication object(s) + // 5. Approve the authentication request with the authentication object(s) +}); +``` + +## Authentication Objects/Payloads + +```typescript +import { populateAuthPayload } from "@walletconnect/utils"; + +// Solana chains that your wallet supports +const supportedChains = [ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ" ] +// Solana methods that your wallet supports +const supportedMethods = ["solana_signMessage", "solana_signTransaction"]; +// Populate the authentication payload with the supported chains and methods +const authPayload = populateAuthPayload({ + authPayload: payload.params.authPayload, + chains: supportedChains, + methods: supportedMethods, +}); +// Prepare the user's address in CAIP10(https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) format +const iss = `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:8nJ694gNrHx76L2eyJzQw7JBGRoW8Fdtrxf588pEqyYh`; +// Now you can use the authPayload to format the authentication message +const message = walletKit.formatAuthMessage({ + request: authPayload, + iss +}); + +// Present the authentication message to the user +... +``` + +## Approving Authentication Requests + + + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWS (Sign-In with Solana) message for each chain and account. However, at a minimum, one SIWS message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + + +```typescript +// Approach 1 +// Sign the authentication message(s) to create a verifiable authentication object(s) +const signature = await cryptoWallet.signMessage(message, privateKey); +// Build the authentication object(s) +const auth = buildAuthObject( + authPayload, + { + t: "caip122", + s: signature, + }, + iss +); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths: [auth], +}); + +// Approach 2 +// Note that you can also sign multiple messages for every requested chain/address pair +const auths = []; +authPayload.chains.forEach(async (chain) => { + const message = walletKit.formatAuthMessage({ + request: authPayload, + iss: `${chain}:${cryptoWallet.address}`, + }); + const signature = await cryptoWallet.signMessage(message); + const auth = buildAuthObject( + authPayload, + { + t: "caip122", // signature type + s: signature, + }, + `${chain}:${cryptoWallet.address}` + ); + auths.push(auth); +}); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths, +}); +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method. + +```typescript +import { getSdkError } from "@walletconnect/utils"; + +await walletKit.rejectSessionAuthenticate({ + id: payload.id, + reason: getSdkError("USER_REJECTED"), // or choose a different reason if applicable +}); +``` + +## Testing One-click Auth + +You can use [AppKit Labs](https://appkit-lab.reown.com/library/solana-siws/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/web/one-click-auth.mdx b/network/wallets/web/one-click-auth.mdx new file mode 100644 index 0000000..0dc6f91 --- /dev/null +++ b/network/wallets/web/one-click-auth.mdx @@ -0,0 +1,135 @@ +--- +title: One-click Auth +--- + +## Introduction + +This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities). + +This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form. + +By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem. + +![](/images/authenticatedSessions-light.png) + + +## Handling Authentication Requests + +To handle incoming authentication requests, subscribe to the `session_authenticate` event. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic. + +```typescript +walletKit.on("session_authenticate", async (payload) => { + // Process the authentication request here. + // Steps include: + // 1. Populate the authentication payload with the supported chains and methods + // 2. Format the authentication message using the payload and the user's account + // 3. Present the authentication message to the user + // 4. Sign the authentication message(s) to create a verifiable authentication object(s) + // 5. Approve the authentication request with the authentication object(s) +}); +``` + +## Authentication Objects/Payloads + +```typescript +import { populateAuthPayload } from "@walletconnect/utils"; + +// EVM chains that your wallet supports +const supportedChains = ["eip155:1", "eip155:2", 'eip155:137']; +// EVM methods that your wallet supports +const supportedMethods = ["personal_sign", "eth_sendTransaction", "eth_signTypedData"]; +// Populate the authentication payload with the supported chains and methods +const authPayload = populateAuthPayload({ + authPayload: payload.params.authPayload, + chains: supportedChains, + methods: supportedMethods, +}); +// Prepare the user's address in CAIP10(https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) format +const iss = `eip155:1:0x0Df6d2a56F90e8592B4FfEd587dB3D5F5ED9d6ef`; +// Now you can use the authPayload to format the authentication message +const message = walletKit.formatAuthMessage({ + request: authPayload, + iss +}); + +// Present the authentication message to the user +... +``` + +## Approving Authentication Requests + + +**Note** + +1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object. +2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session. + + +```typescript +// Approach 1 +// Sign the authentication message(s) to create a verifiable authentication object(s) +const signature = await cryptoWallet.signMessage(message, privateKey); +// Build the authentication object(s) +const auth = buildAuthObject( + authPayload, + { + t: "eip191", + s: signature, + }, + iss +); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths: [auth], +}); + +// Approach 2 +// Note that you can also sign multiple messages for every requested chain/address pair +const auths = []; +authPayload.chains.forEach(async (chain) => { + const message = walletKit.formatAuthMessage({ + request: authPayload, + iss: `${chain}:${cryptoWallet.address}`, + }); + const signature = await cryptoWallet.signMessage(message); + const auth = buildAuthObject( + authPayload, + { + t: "eip191", // signature type + s: signature, + }, + `${chain}:${cryptoWallet.address}` + ); + auths.push(auth); +}); + +// Approve +await walletKit.approveSessionAuthenticate({ + id: payload.id, + auths, +}); +``` + +## Rejecting Authentication Requests + +If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method. + +```typescript +import { getSdkError } from "@walletconnect/utils"; + +await walletKit.rejectSessionAuthenticate({ + id: payload.id, + reason: getSdkError("USER_REJECTED"), // or choose a different reason if applicable +}); +``` + +## Testing One-click Auth + +You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly. + + diff --git a/network/wallets/web/resources.mdx b/network/wallets/web/resources.mdx new file mode 100644 index 0000000..b5fe858 --- /dev/null +++ b/network/wallets/web/resources.mdx @@ -0,0 +1,31 @@ +--- +title: Resources +--- + +Valuable assets for developers and users interested in integrating Wallet SDK into their applications. + +- [Awesome WalletConnect](https://github.com/WalletConnect/awesome-walletconnect) - Community-curated collection of WalletConnect-enabled wallets, libraries, and tools. +- [AppKit Laboratory](https://appkit-lab.reown.com/) - A place to test your wallet integrations against various setups of AppKit. +- [Wallet SDK JavaScript GitHub](https://github.com/reown-com/reown-walletkit-js) - Wallet SDK JavaScript GitHub repository. + +### Wallet Resources + +We have a set of official examples in our [web-examples](https://github.com/WalletConnect/web-examples) repository to help you get started. + +**Wallet SDK** + +This wallet can be used with any dapp using Sign v2 or Auth. + +- [React Wallet SDK](https://github.com/reown-com/web-examples/tree/main/advanced/wallets/react-wallet-v2) ([Demo](https://react-wallet.walletconnect.com)) + +**Sign** + +- [React Wallet Ethers - v2](https://github.com/reown-com/web-examples/tree/main/advanced/wallets/react-wallet-auth) ([Demo](https://react-auth-wallet.walletconnect.com/)) + +### Dapp Resources + +If you need to test your app's integration, you can use one of our following demo wallets and/or dapps. + +**Sign** + +- [React dApp (with standalone client) - v2](https://github.com/WalletConnect/web-examples/tree/main/advanced/dapps/react-dapp-v2) ([Demo](https://react-app.reown.com/)) diff --git a/network/wallets/web/usage.mdx b/network/wallets/web/usage.mdx new file mode 100644 index 0000000..6a0ef26 --- /dev/null +++ b/network/wallets/web/usage.mdx @@ -0,0 +1,624 @@ +--- +title: Usage +--- + +import CloudBanner from "/snippets/cloud-banner.mdx"; + +## Overview + +WalletConnect makes distributing your Web wallet (such as Safe, Abstract Global Wallet, and many more) much faster. By integrating the Wallet SDK, your web wallet will be able to connect to any dApp that supports WalletConnect and will be available in the list of wallets on both WalletConnect, Reown AppKit, and others. + + + Web Wallet in Reown AppKit + + Web Wallet in WalletConnect + + +Additionally, you don't need to build SDKs in native languages such as Swift, Kotlin, Flutter, Unity, or React Native. This means your wallet can be available not just for web dApps, but also for native dApps, all from a single codebase. + +This section provides instructions on how to initialize the WalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dApps through a simple and intuitive interface. + +## User Experience + +### Default Integration + +This integration automatically opens a new web wallet tab when a user clicks "Connect" in a dApp. The wallet handles the WalletConnect URI automatically, meaning users don't need to manually copy and paste the URI. This provides a seamless, one-click connection experience. + + +