From 0ea522e8a0e715b2f9682c745808eaadf01ad609 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:55:03 +0000 Subject: [PATCH] docs: remove walletkit pages and add migration guide Co-Authored-By: Jem Conlon --- advanced/api/sign/wallet-usage.mdx | 1227 --------------------- advanced/walletconnect-deprecations.mdx | 132 --- advanced/walletconnectmodal/resources.mdx | 48 - advanced/walletconnectmodal/usage.mdx | 1039 ----------------- advanced/walletkit-migration.mdx | 17 + cloud/explorer-submission.mdx | 122 -- docs.json | 4 +- 7 files changed, 18 insertions(+), 2571 deletions(-) delete mode 100644 advanced/api/sign/wallet-usage.mdx delete mode 100644 advanced/walletconnect-deprecations.mdx delete mode 100644 advanced/walletconnectmodal/resources.mdx delete mode 100644 advanced/walletconnectmodal/usage.mdx create mode 100644 advanced/walletkit-migration.mdx delete mode 100644 cloud/explorer-submission.mdx diff --git a/advanced/api/sign/wallet-usage.mdx b/advanced/api/sign/wallet-usage.mdx deleted file mode 100644 index bcd284282..000000000 --- a/advanced/api/sign/wallet-usage.mdx +++ /dev/null @@ -1,1227 +0,0 @@ ---- -title: "Wallet Usage" ---- - -import CloudBanner from "/snippets/cloud-banner.mdx"; - -Sign API establishes a session between a wallet and a dapp in order to expose a set of blockchain accounts that can sign transactions or messages using a secure remote JSON-RPC transport with methods and events. - - - - - - - - This library is compatible with Node.js, browsers and React Native - applications (Node.js modules require polyfills for React Native). - - -#### Migrating from v1.x - -**We recommend you install v1 and v2 together for maximum compatibility.** If your wallet already uses `@walletconnect/client@1.x.x`, -you should be able to add `@walletconnect/sign-client@2.x.x` without any issues. - -If you experience dependency clashes or you require both `@walletconnect/types@1.x.x` and `@walletconnect/types@2.x.x` in parallel -in your wallet's top-level dependencies, please refer to the [`legacy` packages](https://github.com/WalletConnect/walletconnect-legacy/tree/main/packages) which were published explicitly for this purpose. - -In the above scenario, you would replace `@walletconnect/types@1.x.x` with `@walletconnect/legacy-types` and then install `@walletconnect/types@2.x.x`. - -#### Initializing the client - -Initialize client as a controller using [your Project ID](/cloud/relay). - -```js -const signClient = await SignClient.init({ - projectId: "", - // optional parameters - relayUrl: "", - metadata: { - name: "Wallet name", - description: "A short description for your wallet", - url: "", - icons: [""], - }, -}); -``` - -#### Setting up event listeners - -WalletConnect v2.0 emits events related to the current session. The listeners listed in the following code snippet represent typical -events in a session's lifecycle that you can listen for to synchronise your application accordingly. - -Example: when a `session_delete` event is emitted, it makes sense to change the UI from an active session state to -an inactive/disconnected state. - -**1. Add listeners for desired `SignClient` events.** - - - To listen to pairing-related events, please follow the guidance for [Pairing - API event listeners.](../core/pairing) - - -```ts -signClient.on("session_proposal", (event) => { - // Show session proposal data to the user i.e. in a modal with options to approve / reject it - - interface Event { - id: number; - params: { - id: number; - expiry: number; - relays: Array<{ - protocol: string; - data?: string; - }>; - proposer: { - publicKey: string; - metadata: { - name: string; - description: string; - url: string; - icons: string[]; - }; - }; - requiredNamespaces: Record< - string, - { - chains: string[]; - methods: string[]; - events: string[]; - } - >; - pairingTopic?: string; - }; - } -}); - -signClient.on("session_event", (event) => { - // Handle session events, such as "chainChanged", "accountsChanged", etc. - - interface Event { - id: number; - topic: string; - params: { - event: { - name: string; - data: any; - }; - chainId: string; - }; - } -}); - -signClient.on("session_request", (event) => { - // Handle session method requests, such as "eth_sign", "eth_sendTransaction", etc. - - interface Event { - id: number; - topic: string; - params: { - request: { - method: string; - params: any; - }; - chainId: string; - }; - } -}); - -signClient.on("session_ping", (event) => { - // React to session ping event - - interface Event { - id: number; - topic: string; - } -}); - -signClient.on("session_delete", (event) => { - // React to session delete event - - interface Event { - id: number; - topic: string; - } -}); -``` - -# Pairing and session permissions - -#### URI - -The pairing proposal between a wallet and a dapp is made using an [URI](https://specs.walletconnect.com/2.0/specs/clients/core/pairing/). In WalletConnect v2.0 the session and pairing are decoupled from each other. This means that a URI is shared to construct a pairing proposal, and only after settling the pairing the dapp can propose a session using that pairing. In simpler words, the dapp generates an URI that can be used by the wallet for pairing. - -#### Namespaces - -The `namespaces` parameter is used to specify the namespaces and chains that are intended to be used in the session. The following is an example: - -```js -namespaces: { - eip155: { - accounts: ["eip155:1:0x0000000000..., eip155:2:0x0000000000..."], - methods: ["personal_sign", "eth_sendTransaction"], - events: ["accountsChanged"] - }, -}; -``` - -#### Pairing with `uri` - -To create a pairing proposal, simply pass the `uri` received from the dapp into the `signClient.core.pairing.pair()` function. - - -As of 2.0.0 (stable), calling pairing-specific methods (such as `signClient.pair()`) directly on `signClient` will continue to work, but is considered deprecated and will be removed in a future major version. - -It is recommended to instead call these methods directly via the [Pairing API.](../core//pairing), e.g.: `signClient.core.pairing.pair()`. - - - -```js -// This will trigger the `session_proposal` event -await signClient.core.pairing.pair({ uri }); - -// Approve session proposal, use id from session proposal event and respond with namespace(s) that satisfy dapps request and contain approved accounts -const { topic, acknowledged } = await signClient.approve({ - id: 123, - namespaces: { - eip155: { - accounts: ["eip155:1:0x0000000000..."], - methods: ["personal_sign", "eth_sendTransaction"], - events: ["accountsChanged"], - }, - }, -}); - -// Optionally await acknowledgement from dapp -const session = await acknowledged(); - -// Or reject session proposal -await signClient.reject({ - id: 123, - reason: { - code: 1, - message: "rejected", - }, -}); -``` - -#### Pairing with QR Codes - -To facilitate better user experience, it is possible to pair wallets with dapps by scanning QR codes. This can be implemented by using any QR code scanning library (example, [react-qr-reader](https://www.npmjs.com/package/react-qr-reader)). After scanning the QR code, pass the obtained `uri` into the `signClient.pair()` function. A useful reference for implementing QR codes for pairing is the [react wallet example](https://github.com/WalletConnect/web-examples/blob/main/advanced/wallets/react-wallet-v2/). - -## Authenticated Session - -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 (SIWE) message, enhanced by ReCaps (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. - -#### 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) -}); -``` - -#### Populate 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 - - -**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 -}); -``` - - - - - -#### Configure Networking and Pair Clients - -Confirm you have configured the Network and Pair Client first - -- [Networking](/advanced/api/core/relay) -- [Pairing](/advanced/api/core/pairing) - -#### Configure Sign Client - -In order to initialize a client, call a `configure` method on the Sign instance - -```swift -Sign.configure(crypto: CryptoProvider) -``` - -#### Subscribe for Sign Publishers - -The following publishers are available to subscribe: - -```swift -public var sessionsPublisher: AnyPublisher<[Session], Never> -public var sessionProposalPublisher: AnyPublisher<(proposal: Session.Proposal, context: VerifyContext?), Never> -public var sessionRequestPublisher: AnyPublisher<(request: Request, context: VerifyContext?), Never> -public var socketConnectionStatusPublisher: AnyPublisher -public var sessionSettlePublisher: AnyPublisher -public var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> -public var sessionResponsePublisher: AnyPublisher -public var sessionRejectionPublisher: AnyPublisher<(Session.Proposal, Reason), Never> -public var sessionUpdatePublisher: AnyPublisher<(sessionTopic: String, namespaces: [String : SessionNamespace]), Never> -public var sessionEventPublisher: AnyPublisher<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never> -public var sessionUpdateExpiryPublisher: AnyPublisher<(sessionTopic: String, expiry: Date), Never> -``` - -#### 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 Pair.instance.pair(uri: uri) -``` - -if everything goes well, you should handle following event: - -```swift -Sign.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 `ProposalNamespaces` that contains required 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 [dashboard](https://dashboard.reown.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"] - } -} -``` - -#### 💡 AutoNamespaces Builder Utility - -`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 { - let 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")! - ] - ) - try await Sign.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces) -} catch { - print(error) -} -``` - -#### Approve Session - -```swift - Sign.instance.approve( - proposalId: "proposal_id", - namespaces: sessionNamespaces -) -``` - -#### Reject Session - -```swift -Sign.instance.reject( - proposalId: "proposal_id", - reason: .userRejected -) -``` - -When session is successfully approved `sessionSettlePublisher` will publish a `Session` - -```swift -Sign.instance.sessionSettlePublisher - .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 -Sign.instance.getSessions() -``` - -#### Track Sessions - -When your `Sign` 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 -Sign.instance.sessionsPublisher - .receive(on: DispatchQueue.main) - .sink { [self self] (sessions: [Session]) in - // Reload UI - }.store(in: &publishers) -``` - -#### Handle Requests from Dapp - -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 -Sign.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 Sign.instance.respond(topic: request.topic, requestId: request.id, response: .response(response)) -``` - -#### Update Session - -If you want to update user session's chains, accounts, methods or events you can use session update method. - -```swift -try await Sign.instance.update(topic: session.topic, namespaces: newNamespaces) -``` - -#### Extend 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 Sign.instance.extend(topic: session.topic) -``` - -above method will extend a user's session to a week. - -#### Disconnect Session - -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 Sign.instance.disconnect(topic: session.topic) -``` - -### Authenticated Session - -An authenticated session represents a secure connection established between a wallet and a dApp after successful authentication. - -#### 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 -Sign.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. -``` - -#### Building Authentication Objects - -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 Sign.instance.buildAuthPayload( - payload: request.payload, - supportedEVMChains: Array(commonChains), - supportedMethods: supportedMethods - ) - let formattedMessage = try Sign.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 Sign.instance.buildSignedAuthObject( - authPayload: supportedAuthPayload, - signature: signature, - account: accountForChain - ) - authObjects.append(authObject) - } - return authObjects -} - -``` - -#### Approving Authentication Requests - -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 Sign.instance.approveSessionAuthenticate(requestId: requestId, auths: authObjects) -``` - - -**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. - - - -#### 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 Sign.instance.rejectSession(requestId: requestId) -``` - -#### Where to go from here - -- Try our example wallet implementation [here](https://github.com/reown-com/reown-swift/tree/main/Example/WalletApp). - {/* */} -- Build API documentation in XCode: go to Product -> Build Documentation - - - - - -#### **Initialization** - -```kotlin -val projectId = "" // Get Project ID at https://dashboard.reown.com/ -val connectionType = ConnectionType.AUTOMATIC or ConnectionType.MANUAL -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) - -val init = Sign.Params.Init(core = CoreClient) - -SignClient.initialize(init) { error -> - // Error will be thrown if there's an issue during initialization -} -``` - -The wallet client will always be responsible for exposing accounts (CAPI10 compatible) to a Dapp and therefore is also in charge of signing. -To initialize the Sign client, create a `Sign.Params.Init` object in the Android Application class with the Core Client. The `Sign.Params.Init` object will then be passed to the `SignClient`initialize function. - -# **Wallet** - -#### **SignClient.WalletDelegate** - -```kotlin -val walletDelegate = object : SignClient.WalletDelegate { - override fun onSessionProposal(sessionProposal: Sign.Model.SessionProposal, verifyContext: Sign.Model.VerifyContext) { - // Triggered when wallet receives the session proposal sent by a Dapp - } - - val onSessionAuthenticate: ((Sign.Model.SessionAuthenticate, Sign.Model.VerifyContext) -> Unit)? get() = null - // Triggered when wallet receives the session authenticate sent by a Dapp - - override fun onSessionRequest(sessionRequest: Sign.Model.SessionRequest, verifyContext: Sign.Model.VerifyContext) { - // Triggered when a Dapp sends SessionRequest to sign a transaction or a message - } - - override fun onSessionDelete(deletedSession: Sign.Model.DeletedSession) { - // Triggered when the session is deleted by the peer - } - - override fun onSessionSettleResponse(settleSessionResponse: Sign.Model.SettledSessionResponse) { - // Triggered when wallet receives the session settlement response from Dapp - } - - override fun onSessionUpdateResponse(sessionUpdateResponse: Sign.Model.SessionUpdateResponse) { - // Triggered when wallet receives the session update response from Dapp - } - - override fun onConnectionStateChange(state: Sign.Model.ConnectionState) { - //Triggered whenever the connection state is changed - } - - override fun onError(error: Sign.Model.Error) { - // Triggered whenever there is an issue inside the SDK - } -} -SignClient.setWalletDelegate(walletDelegate) -``` - -`Sign.Model.VerifyContext` provides a domain verification information about SessionProposal and SessionRequest. 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 SignClient needs a `SignClient.WalletDelegate` passed to it for it to be able to expose asynchronous updates sent from the Dapp. - -# - -#### **Session Approval** - -NOTE: addresses provided in `accounts` array should follow [CAPI10](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, Sign.Model.Namespaces.Session(accounts, methods, events)) - -val approveParams: Sign.Params.Approve = Sign.Params.Approve(proposerPublicKey, namespaces) -SignClient.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 `SignClient.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: Sign.Params.Reject = Reject(proposerPublicKey, rejectionReason, rejectionCode) -SignClient.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 `SignClient.rejectSession` function. - -# - -#### **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 = Sign.Params.Disconnect(sessionTopic, disconnectionReason, disconnectionCode) - -SignClient.disconnect(disconnectParams) { error -> /*callback for error while disconnecting a session*/ } -``` - -To disconnect from a settled session, pass a disconnection reason with code and the Session topic to the `SignClient.disconnect` -function. - -# - -#### **Respond Request** - -```kotlin -val sessionTopic: String = /*Topic of Session*/ -val jsonRpcResponse: Sign.Model.JsonRpcResponse.JsonRpcResult = /*Settled Session Request ID along with request data*/ -val result = Sign.Params.Response(sessionTopic = sessionTopic, jsonRpcResponse = jsonRpcResponse) - -SignClient.respond(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 `Sign.Params.Response` with the session's topic and request -ID along with the respond data to the `SignClient.respond` function. - -#### **Reject Request** - -```kotlin -val sessionTopic: String = /*Topic of Session*/ -val jsonRpcResponseError: Sign.Model.JsonRpcResponse.JsonRpcError = /*Session Request ID along with error code and message*/ -val result = Sign.Params.Response(sessionTopic = sessionTopic, jsonRpcResponse = jsonRpcResponseError) - -SignClient.respond(result) { error -> /*callback for error while responding session request*/ } -``` - -To reject a JSON-RPC method that was sent from a Dapps for a session, submit a `Sign.Params.Response` with the settled session's topic and -request ID along with the rejection data to the `SignClient.respond` function. - -# - -#### **Session Update** - -NOTE: addresses provided in `accounts` array should follow [CAIP10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) -semantics and syntax. - -```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 authorized chains*/ -val methods: List = /*List of methods that wallet approves*/ -val events: List = /*List of events that wallet approves*/ -val namespaces: Map = mapOf(namespace, Sign.Model.Namespaces.Session(accounts, methods, events)) -val updateParams = Sign.Params.Update(sessionTopic, namespaces) - -SignClient.update(updateParams) { error -> /*callback for error while sending session update*/ } -``` - -To update a session with namespaces, use `SignClient.Update` to submit a `Sign.Params.Update` object with the session's topic and updated namespace objects (i.e. adding requesting new methods or events, new accounts on authorized chains, or authorizing new chainIds within a multi-chain namespace). - -# - -#### **Session Extend** - -```kotlin -val sessionTopic: String = /*Topic of Session*/ -val extendParams = Sign.Params.Extend(sessionTopic = sessionTopic) - -SignClient.extend(extendParams) { error -> /*callback for error while extending a session*/ } -``` - -To extend a session, create a `Sign.Params.Extend` object with the session's topic to update the session with to `Sign.Extend`. Session is -extended by 7 days. - -#### **Session Ping** - -```kotlin -val sessionTopic: String = /*Topic of Session*/ -val pingParams = Sign.Params.Ping(sessionTopic) -val listener = object : Sign.Listeners.SessionPing { - override fun onSuccess(pingSuccess: Model.Ping.Success) { - // Topic being pinged - } - - override fun onError(pingError: Model.Ping.Error) { - // Error - } -} - -SignClient.ping(pingParams, listener) -``` - -To ping a peer with a session, call `SignClient.ping` with the `Sign.Params.Ping` with a session's topic. If ping is successful, topic is -echo'd in listener. - -# - -#### **Authenticated Session** - -An authenticated session represents a secure connection established between a wallet and a dApp after successful authentication. - -### Authentication Requests - -To handle incoming authentication requests, set up SignClient.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 -} -``` - -### Responding Authentication Request - -To interact with authentication requests, build authentication objects (Sign.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 = - 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 = formatAuthMessage(Sign.Params.FormatMessage(authPayloadParams, issuer)) - - val signature = signMessage(message: formattedMessage, privateKey: privateKey) //Note: Assume `signMessage` is a function you've implemented to sign messages. - val auth = generateAuthObject(authPayloadParams, issuer, signature) - auths.add(auth) - } -} -``` - -### Approving Authentication Requests - -To approve an authentication request, construct Sign.Model.Cacao instances for each supported chain, sign the authentication messages, build AuthObjects and call approveAuthenticate with the request ID and the authentication objects. - -```kotlin - val approveAuthenticate = Sign.Params.ApproveAuthenticate(id = sessionAuthenticate.id, auths = auths) -SignClient.approveAuthenticate(approveProposal, - onSuccess = { - //Redirect back to the dapp if redirect is set: sessionAuthenticate.participant.metadata?.redirect - }, - onError = { error -> - //Handle error - } -) -``` - - -**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. - - - -### Rejecting Authentication Requests - -If the authentication request cannot be approved or if the user chooses to reject it, use the rejectAuthenticate method. - -```kotlin -val rejectParams = Sign.Params.RejectAuthenticate( - id = sessionAuthenticate.id, - reason = "Reason" -) - -SignClient.rejectAuthenticate(rejectParams, - onSuccess = { - //Success - }, - onError = { error -> - //Handle error - } -) -``` - - - - - -#### Setup - -First you must setup `SignClientOptions` which stores both the `ProjectId` and `Metadata`. You may also optionally specify the storage module to use. By default, the `FileSystemStorage` module is used if none is specified. - -```csharp -var walletOptions = new SignClientOptions() -{ - ProjectId = "39f3dc0a2c604ec9885799f9fc5feb7c", - Metadata = new Metadata() - { - Description = "An example wallet to showcase WalletConnectSharpv2", - Icons = new[] { "https://walletconnect.com/meta/favicon.ico" }, - Name = "WalletConnectSharpv2 Wallet Example", - Url = "https://walletconnect.com" - }, - // Uncomment to disable persistent storage - // Storage = new InMemoryStorage() -}; -``` - -Once you have the options defined, you can initialize the SDK. - -```csharp -var walletClient = await WalletConnectSignClient.Init(walletOptions); -``` - -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 -ProposalStruct proposal = await walletClient.Pair(connectData.Uri); -``` - -The wallet can then approve or reject the proposal using either of the following: - -```csharp -string addressToConnect = ...; -var approveData = await walletClient.Approve(proposal, addressToConnect); -await approveData.Acknowledged(); -``` - -```csharp -string[] addressesToConnect = ...; -var approveData = await walletClient.Approve(proposal, addressesToConnect); -await approveData.Acknowledged(); -``` - -```csharp -await walletClient.Reject(proposal, "User rejected"); -``` - -#### WalletConnect Methods - -All sign methods require 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 user. - -```csharp -var sessionTopic = sessionData.Topic; -``` - -##### Update 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(); -``` - -##### Extend Session - -Extend a session's expiry time so the session remains open - -```csharp -var request = await walletClient.Extend(sessionTopic); -await request.Acknowledged(); -``` - -##### Ping - -Send a ping to the session - -```csharp -var request = await walletClient.Ping(sessionTopic); -await request.Acknowledged(); -``` - -#### 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 statically typed language, so these types must be given whenever you do a session request (or do any querying for session requests). - -Currently, **WalletConnectSharp 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) - { - } -} -``` - -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; -} -``` - -#### Disconnecting - -To disconnect a session, use the `Disconnect` function. You may optional provide a reason for the disconnect - -```csharp -await walletClient.Disconnect(sessionTopic); - -// or - -await walletClient.Disconnect(sessionTopic, Error.FromErrorType(ErrorType.USER_DISCONNECTED)); -``` - - - - diff --git a/advanced/walletconnect-deprecations.mdx b/advanced/walletconnect-deprecations.mdx deleted file mode 100644 index fdd44d067..000000000 --- a/advanced/walletconnect-deprecations.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: Deprecated WalletConnect SDKs ---- - -WalletConnect Inc is now Reown. As part of this transition, we are deprecating a number of repositories/packages -across our supported platforms, and the transition to their equivalents published under the Reown organization. -This page outlines the deprecation schedule and provides important information for users of affected repositories/packages. - -## Deprecation Schedule - -### 1. Limited Support Phase (September 17, 2024 - February 17, 2025) - -- Only critical bug fixes and security updates will be provided for the deprecated packages/repositories. -- No new features or non-critical bug fixes will be implemented. - -### 2. End-of-Life Phase (February 18, 2025 onwards) - -- All updates and support for the deprecated packages/repositories packages will cease. -- Users are strongly encouraged to complete migration to packages published under Reown before this date. - -## Affected Packages and Repositories - -The following packages and repositories are affected by this deprecation notice: - -### Web - -**Packages** - -- `@walletconnect/web3wallet` deprecated in favor of `@reown/walletkit` - - For guidance on how to update your existing `@walletconnect/web3wallet` implementation, please see the [WalletKit migration guide](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-web). - - For guidance on how to update your existing `@web3modal/*` implementation, please see the [AppKit migration guide](/appkit/upgrade/to-reown-appkit-web). - -### React Native - -**Packages** - -- `@web3modal/*-react-native` packages deprecated in favor of `@reown/appkit-*-react-native` packages - -For guidance on how to update your implementation, please see [React Native AppKit migration guide](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-react-native) - -### Swift - -- **Packages** - - `Web3Wallet` deprecated in favor of `ReownWalletKit` - - `Web3Modal` deprecated in favor of `ReownAppKit` - - `WalletConnectRouter` deprecated in favor of`ReownRouter` - -**Repositories** - -- https://github.com/WalletConnect/WalletConnectSwiftV2 in favor of https://github.com/reown-com/reown-swift - -For guidance on how to update your Swift implementation, please see: - -- [Swift Migration from Web3Modal to AppKit](/appkit/upgrade/from-web3modal-ios) -- [Swift Migration from Web3Wallet to WalletKit](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-ios) - -### Kotlin - -**Packages** - -- `com.walletconnect:android-bom` in favor of `com.reown:android-bom` -- `com.walletconnect:android-core` in favor of `com.reown:android-core` -- `com.walletconnect:web3wallet` in favor of `com.reown:walletkit` -- `com.walletconnect:web3modal` in favor of `com.reown:appkit` -- `com.walletconnect:sign` in favor of `com.reown:sign` -- `com.walletconnect:notify` in favor of `com.reown:notify` - -**Repositories** - -- https://github.com/WalletConnect/WalletConnectKotlinV2 in favor of https://github.com/reown-com/reown-kotlin - -For guidance on how to update your Kotlin packages, please see: - -- [Migration from Web3Modal to AppKit](/appkit/upgrade/from-web3modal-android) -- [Migration from Web3Wallet to WalletKit](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-android) - -### Unity - -**Packages** - -- `com.walletconnect.web3modal` in favor of `com.reown.appkit.unity` -- `com.walletconnect.nethereum` in favor of `com.reown.nethereum.unity` -- `com.walletconnect.core` in favor of `com.reown.sign.unity` and `com.reown.appkit.unity` -- `com.walletconnect.modal` deprecated, migrate to `com.reown.appkit.unity` - -**Repositories** - -- https://github.com/walletconnect/web3modalunity in favor of https://github.com/reown-com/reown-dotnet -- https://github.com/walletconnect/walletconnectunity in favor of https://github.com/reown-com/reown-dotnet - -For guidance on how to update your Unity packages, please see the [Web3Modal to AppKit migration guide](/appkit/upgrade/from-web3modal-unity) - -### .NET - -**Packages** - -- `WalletConnect.Sign` in favor of `Reown.Sign` -- `WalletConnect.Web3Wallet` in favor of `Reown.WalletKit` - -**Repositories** - -- https://github.com/WalletConnect/WalletConnectSharp in favor of https://github.com/reown-com/reown-dotnet - -For guidance on how to update your NuGet packages, please see the [Web3Wallet to WalletKit migration guide](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-unity) - -### Flutter - -**Packages** - -- [walletconnect_flutter_v2](https://pub.dev/packages/walletconnect_flutter_v2) in favor of [reown_walletkit](https://pub.dev/packages/reown_walletkit) -- [web3modal_flutter](https://pub.dev/packages/walletconnect_flutter_v2) in favor of [reown_appkit](https://pub.dev/packages/reown_appkit) - -**Repositories** - -- https://github.com/WalletConnect/WalletConnectFlutterV2 in favor of https://github.com/reown-com/reown_flutter -- https://github.com/WalletConnect/Web3ModalFlutter in favor of https://github.com/reown-com/reown_flutter - -For guidance on how to update your Flutter packages, please see: - -- [Migration from Web3Modal to AppKit](/appkit/upgrade/from-web3modal-flutter) -- [Migration from Web3Wallet to WalletKit](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-flutter) - -## Action Required - -1. Identify the platforms and packages you are currently using from the list above. -2. Review the corresponding migration guide for your platform(s) using the links provided. -3. Plan your migration to packages published under Reown as soon as possible. -4. Complete the migration before February 17th 2025, to ensure continued support and access to the latest features and security updates. - -## Support and Resources - -- If you encounter any issues during migration, please open an issue in the respective [Reown Github repository](https://github.com/reown-com). diff --git a/advanced/walletconnectmodal/resources.mdx b/advanced/walletconnectmodal/resources.mdx deleted file mode 100644 index a7242aa66..000000000 --- a/advanced/walletconnectmodal/resources.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Resources ---- - -Valuable assets for developers and users interested in integrating WalletKit 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. -- [Web3Wallet GitHub](https://github.com/WalletConnect/walletconnect-monorepo/tree/v2.0/packages/web3wallet) - Web3Wallet GitHub repository. - -## Implementation Examples - - - - -To check more in detail go and visit our [WalletConnect Modal Web implementation app](https://github.com/WalletConnect/web3modal-examples) - - - - -To check more in detail go and visit our [WalletConnect Modal Swift implementation app](https://github.com/reown-com/reown-swift/tree/main/Example/WalletApp) - - - - -To check more in detail go and visit our [WalletConnect Modal Kotlin implementation app](https://github.com/WalletConnect/WalletConnectKotlinV2/tree/develop/sample) - - - - -- Check our implementation of [Modal + Viem](https://github.com/WalletConnect/react-native-examples/tree/main/dapps/ModalViem) -- Check our implementation of [Modal + Ethers](https://github.com/WalletConnect/react-native-examples/tree/main/dapps/ModalEthers) -- Check our implementation of [Modal + Universal Provider](https://github.com/WalletConnect/react-native-examples/tree/main/dapps/ModalUProvider) -- To check more in details go and visit our [WalletConnect Modal React Native implementation app](https://github.com/WalletConnect/modal-react-native/tree/main/example) - - - - -To check more in detail go and visit our [WalletConnect Modal Flutter implementation app](https://github.com/WalletConnect/WalletConnectModalFlutter/tree/master/example/sign) - - - - -To check more in detail go and visit our [WalletConnect Modal Unity implementation sample](https://github.com/WalletConnect/WalletConnectUnity/tree/main/Packages/com.walletconnect.modal/Samples~/Modal%20Sample) - - - - diff --git a/advanced/walletconnectmodal/usage.mdx b/advanced/walletconnectmodal/usage.mdx deleted file mode 100644 index 9452c04db..000000000 --- a/advanced/walletconnectmodal/usage.mdx +++ /dev/null @@ -1,1039 +0,0 @@ ---- -title: Usage ---- - -This section provides instructions on how to use WalletConnectModal in your project. - -## Implementation - - - - -Start by importing `WalletConnectModal` and initializing it. - -```js -import { WalletConnectModal } from "@walletconnect/modal"; - -const modal = new WalletConnectModal({ - projectId: "YOUR_PROJECT_ID", - chains: ["eip155:1"], -}); -``` - -#### Trigger the modal - -Once you have obtained your connection uri, you can open or close the modal. - -From here on, use `provider` as you normally would, WalletConnectModal will be shown and hidden automatically i.e. - -```js -await modal.openModal({ - uri: "YOUR_CONNECTION_URI", -}); - -// Do some work... - -modal.closeModal(); -``` - - - - -#### Configure Networking and Pair clients - -Make sure that you properly configure Networking and Pair Clients first. - -- [Networking](/advanced/api/core/relay) - -#### Initialize WalletConnectModal Client - -In order to initialize a client just call a `configure` method from the WalletKit instance wrapper - -```swift -let metadata = AppMetadata( - name: "Example Wallet", - description: "Wallet description", - url: "example.wallet", - icons: ["https://avatars.githubusercontent.com/u/37784886"], - // Used for the Verify: to opt-out verification ignore this parameter - verifyUrl: "verify.walletconnect.com" -) - -WalletConnectModal.configure( - projectId: PROJECT_ID, - metadata: metadata -) -``` - -This example will default to using following namespaces. - -```swift -let methods: Set = ["eth_sendTransaction", "personal_sign", "eth_signTypedData"] -let events: Set = ["chainChanged", "accountsChanged"] -let blockchains: Set = [Blockchain("eip155:1")!] -let namespaces: [String: ProposalNamespace] = [ - "eip155": ProposalNamespace( - chains: blockchains, - methods: methods, - events: events - ) -] - -let defaultSessionParams = SessionParams( - requiredNamespaces: namespaces, - optionalNamespaces: nil, - sessionProperties: nil - ) -``` - -If you want to change that you can call configure and define your own session parameters like this. - -```swift -let metadata = AppMetadata(...) - -let sessionParams = SessionParams(...) - -WalletConnectModal.configure( - projectId: PROJECT_ID, - metadata: metadata, - sessionParams: sessionParams -) -``` - -or you can change them later by calling `WalletConnectModal.set(sessionParams: SessionParams(...))` - - - - -`WalletConnectModal` is a singleton that interacts with the WalletConnectModal SDK. - -#### Initialize - -```kotlin -val connectionType = ConnectionType.AUTOMATIC or ConnectionType.MANUAL -val projectId = "" // Get Project ID at https://dashboard.reown.com/ -val appMetaData = Core.Model.AppMetaData( - name = "Kotlin.WalletConnectModal", - description = "Kotlin WalletConnectModal Implementation", - url = "kotlin.walletconnect.com", - icons = listOf("https://raw.githubusercontent.com/WalletConnect/walletconnect-assets/master/Icon/Gradient/Icon.png"), - redirect = "kotlin-modal://request" -) - -CoreClient.initialize(projectId = projectId, connectionType = connectionType, application = this, metaData = appMetaData) - -WalletConnectModal.initialize( - init = Modal.Params.Init(CoreClient), - onSuccess = { - // Callback will be called if initialization is successful - }, - onError = { error -> - // Error will be thrown if there's an issue during initialization - } -) -``` - -#### SessionParams - -This example will default to using following namespaces. -You can define your own session parameters like this. - -```kotlin -val methods: List = listOf("eth_sendTransaction", "personal_sign", "eth_sign", "eth_signTypedData") -val events: List = listOf("chainChanged", "accountsChanged") -val chains: List = listOf("eip155:1") -val namespaces = mapOf( - "eip155" to Modal.Model.Namespace.Proposal( - chains = chains, - methods = methods, - events = events - ) -) - -val sessionParams = Modal.Params.SessionParams( - requiredNamespaces = namespaces, - optionalNamespaces = null, - properties = null -) - -WalletConnectModal.setSessionParams(sessionParams) -``` - -**IMPORTANT**: `SessionParams` must be set before opening the modal. - - - - -Create your `WalletConnectModalService` which is your primary class for opening, closing, disconnecting, etc. - -Be sure to update the project ID and metadata with your own. - -```javascript -WalletConnectModalService service = WalletConnectModalService( - projectId: 'YOUR_PROJECT_ID', - metadata: const PairingMetadata( - name: 'Flutter WalletConnect', - description: 'Flutter WalletConnectModal Sign Example', - url: 'https://walletconnect.com/', - icons: ['https://walletconnect.com/walletconnect-logo.png'], - redirect: Redirect( - native: 'flutterdapp://', - universal: 'https://www.walletconnect.com', - ), - ), -); -await service.init(); -``` - -The service must be initialized before it can be used. - -With the `WalletConnectModalService` created and ready, you can call `_service.open()` to open the modal. - -To make things easy, you can use the WalletConnectModalConnect widget to open the modal. -This is a button that changes its state based on the modal and connection. -This widget requires the WalletConnectModalService to be passed in. - -```javascript -WalletConnectModalConnect( - walletConnectModalService: _service, -), -``` - -#### iOS Setup - -For each app you would like to be able to deep link to, you must add that app's link into the `ios/Runner/Info.plist` file like so: - -```xml -LSApplicationQueriesSchemes - - metamask - rainbow - trust - -``` - -To handle deep linking to your app, you will also need to add the following to the plist file: - -```xml -CFBundleURLTypes - - - CFBundleURLSchemes - - flutterdapp - - CFBundleURLName - com.walletconnect.flutterdapp - - -``` - -#### Android Setup - -On android 11+ you must specify that use can use the internet, along with the different packages you would like to be able to deep link to in the `android/app/src/main/AndroidManifest.xml` file like so: - -```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ... - -``` - -For other packages, see the [example project](https://github.com/WalletConnect/Web3ModalFlutter/blob/2981053456ecd3511ca2e3a7f0def7c75e22af62/example/sign/android/app/src/main/AndroidManifest.xml#L2) - -For some reason, multiple wallets have the `metamask` intent, and will launch metamask as a result. -This is a bug in the wallets, not this package. - - - - - -Start by importing `@walletconnect/react-native-compat` at the top of your app. Then import the WalletConnect Modal package, replace `YOUR_PROJECT_ID` with your [Reown Dashboard](https://dashboard.reown.com/sign-in) Project ID and add your Project's info in `providerMetadata` - -```tsx -import "@walletconnect/react-native-compat"; -import { WalletConnectModal } from "@walletconnect/modal-react-native"; - -const projectId = "YOUR_PROJECT_ID"; - -const providerMetadata = { - name: "YOUR_PROJECT_NAME", - description: "YOUR_PROJECT_DESCRIPTION", - url: "https://your-project-website.com/", - icons: ["https://your-project-logo.com/"], - redirect: { - native: "YOUR_APP_SCHEME://", - universal: "YOUR_APP_UNIVERSAL_LINK.com", - }, -}; - -function App() { - return ( - <> - - - ); -} -``` - - - - - -1. Fill in the Project ID and Metadata fields in the `Assets/WalletConnectUnity/Resources/WalletConnectProjectConfig` asset. - - If you don't have a Project ID, you can create one at [Reown Dashboard](https://dashboard.reown.com).). - - The `Redirect` fields are optional. They are used to redirect the user back to your app after they approve or reject the session. -2. Add `WalletConnectModal` prefab from `WalletConnectUnity Modal` package to the first scene in your game. - - - - -## Usage - - - - - -#### openModal - -Action to open the modal. Returns promise that resolves once modal is visible. - -#### Example - -```js -await modal.openModal({ - uri: "YOUR_CONNECTION_URI", -}); -``` - -#### Reference - -```ts -openModal: (options?: OpenOptions) => Promise; -``` - -```ts -interface OpenOptions { - // Uri that will be used to generate qrcode and mobile links, required - uri: string; - // CAIP-2 compliant chain ids to override initial chains defined when creating the modal - // Learn about CAIP-10: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md - chains?: string[]; -} -``` - -#### closeModal - -Action to close the modal. - -#### Example - -```js -modal.closeModal(); -``` - -#### Reference - -```ts -closeModal: () => void -``` - -#### subscribeModal - -Action to subscribe to modal state changes. - -#### Example - -```js -modal.subscribeModal((state) => console.log(state)); -``` - -#### Reference - -```ts -subscribeModal: (callback: (state: ModalState) => void) => void -``` - -```ts -interface ModalState { - open: boolean; -} -``` - - - - -To actually present the modal you can simply call. - -```swift -WalletConnectModal.present() -``` - -It will traverse the view hierarchy and try to present from top most controller. This is meant more towards SwiftUI. - -Otherwise you can specify the viewController to present from. - -```swift -WalletConnectModal.present(from: viewController) -``` - -#### Subscribe for WalletConnectModal Publishers - -The following publishers are available to subscribe: - -```swift -public var sessionPublisher: AnyPublisher<[Session], Never> -public var sessionSettlePublisher: AnyPublisher -public var sessionRejectionPublisher: AnyPublisher<(Session.Proposal, Reason), Never> -public var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> -public var sessionResponsePublisher: AnyPublisher -public var socketConnectionStatusPublisher: AnyPublisher -``` - -#### Sign methods - -WalletConnectModal is internally using Sign SDK and most of its method are being exposed through WalletConnectModal interface. - -#### Where to go from here - -Check the WalletConnectModal usage in our Example Showcase app that is part of WalletConnectSwiftV2 repository. -Build API documentation in Xcode by going to `Product -> Build Documentation` - - - - - -#### Android Compose - -```kotlin -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.ModalBottomSheetState -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController -import com.google.accompanist.navigation.material.BottomSheetNavigator -import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi -import com.google.accompanist.navigation.material.ModalBottomSheetLayout -import com.google.accompanist.navigation.material.bottomSheet -import com.walletconnect.wcmodal.ui.walletConnectModalGraph - -setContent { - val modalSheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden, skipHalfExpanded = true) - val bottomSheetNavigator = BottomSheetNavigator(modalSheetState) - val navController = rememberNavController(bottomSheetNavigator) - - ModalBottomSheetLayout(bottomSheetNavigator = bottomSheetNavigator) { - NavHost( - navController = navController, - startDestination = "home" - ) { - composable("home") { - HomeScreen() - } - walletConnectModalGraph(navController) - } - } -} -``` - -**IMPORTANT**: WalletConnectModal uses accompanist navigation material inside. `ModalBottomSheetLayout` should be imported from [Accompanist Navigation Material](https://google.github.io/accompanist/navigation-material/) - -```kotlin -import com.walletconnect.wcmodal.ui.openWalletConnectModal - -navController.openWalletConnectModal() -``` - -#### Android View - -#### Navigation Component - -```xml - - - - - - - - -``` - -```kotlin -import androidx.navigation.fragment.findNavController -import com.walletconnect.wcmodal.ui.openWalletConnectModal - -findNavController().openWalletConnectModal(id = R.id.action_to_bottomSheet) -``` - -#### Kotlin DSL - -```kotlin -import androidx.navigation.createGraph -import androidx.navigation.fragment.fragment -import com.walletconnect.wcmodal.ui.walletConnectModal - -navController.graph = navController.createGraph("Home") { - fragment("Home") - walletConnectModal() -} -``` - -```kotlin -import androidx.navigation.fragment.findNavController -import com.walletconnect.wcmodal.ui.openWalletConnectModal - -findNavController().openWalletConnectModal() -``` - -#### WalletConnectModal.ModalDelegate - -```kotlin -val walletConnectModalDelegate = object : WalletConnectModal.ModalDelegate { - override fun onSessionApproved(approvedSession: Modal.Model.ApprovedSession) { - // Triggered when receives the session approval from wallet - } - - override fun onSessionRejected(rejectedSession: Modal.Model.RejectedSession) { - // Triggered when receives the session rejection from wallet - } - - override fun onSessionUpdate(updatedSession: Modal.Model.UpdatedSession) { - // Triggered when receives the session update from wallet - } - - override fun onSessionExtend(session: Modal.Model.Session) { - // Triggered when receives the session extend from wallet - } - - override fun onSessionEvent(sessionEvent: Modal.Model.SessionEvent) { - // Triggered when the peer emits events that match the list of events agreed upon session settlement - } - - override fun onSessionDelete(deletedSession: Modal.Model.DeletedSession) { - // Triggered when receives the session delete from wallet - } - - override fun onSessionRequestResponse(response: Modal.Model.SessionRequestResponse) { - // Triggered when receives the session request response from wallet - } - - override fun onProposalExpired(proposal: Modal.Model.ExpiredProposal) { - // Triggered when a proposal becomes expired - } - - override fun onRequestExpired(request: Modal.Model.ExpiredRequest) { - // Triggered when a request becomes expired - } - - override fun onConnectionStateChange(state: Modal.Model.ConnectionState) { - //Triggered whenever the connection state is changed - } - - override fun onError(error: Modal.Model.Error) { - // Triggered whenever there is an issue inside the SDK - } -} -``` - -The WalletConnectModal needs a `WalletConnectModal.ModalDelegate` passed to it for it to be able to expose asynchronously updates sent from the Wallet. It can only be called after successful `WalletConnectModal` initialization - -#### Connect - -```kotlin -val namespace: String = /*Namespace identifier, see for reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md#syntax*/ -val chains: List = /*List of chains that wallet will be requested for*/ -val methods: List = /*List of methods that wallet will be requested for*/ -val events: List = /*List of events that wallet will be requested for*/ -val requiredNamespaces: Map = mapOf(namespace, Modal.Model.Namespaces.Proposal(accounts, methods, events)) /*Required namespaces to setup a session*/ -val optionalNamespaces: Map = mapOf(namespace, Modal.Model.Namespaces.Proposal(accounts, methods, events)) /*Optional namespaces to setup a session*/ -val pairing: Core.Model.Pairing = /*Either an active or inactive pairing*/ -val connectParams = Modal.Params.Connect(requiredNamespaces, optionalNamespaces, pairing) - -WalletConnectModal.connect( - connect = connectParams, - onSuccess = { - /* callback that letting you know that you have successfully initiated connecting */ - }, - onError = { error => - /* callback for error while trying to initiate a connection with a peer */ - } -) -``` - -More about optional and required namespaces can be found [here](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md) - -#### Disconnect - -```kotlin -val disconnectParams = WalletConnectModal.Params.Disconnect(topic) - -WalletConnectModal.disconnect( - disconnect = disconnectParams, - onSuccess = { - /* callback that letting you know that you have successfully disconnected */ - }, - onError = { error -> - /* callback for error while trying to disconnection with a peer */ - } -) -``` - -#### Request - -```kotlin -val requestParams = Modal.Params.Request( - sessionTopic = sessionTopic, - method = /* Selected method */, - params = /* Method params */, - chainId = /* Chain id */ -) - -WalletConnectModal.request( - request = requestParams, - onSuccess = { - /* callback that letting you know that you have successful request */ - }, - onError = { error -> - /* callback for error */ - } -) -``` - -#### Get List of Active Sessions - -```kotlin -WalletConnectModal.getListOfActiveSessions() -``` - -To get a list of active sessions, call `WalletConnectModal.getListOfActiveSessions()` which will return a list of type `Modal.Model.Session`. - -#### Get list of pending session requests for a topic - -```kotlin -WalletConnectModal.getActiveSessionByTopic(topic) -``` - -To get an active session for a topic, call `WalletConnectModal.getActiveSessionByTopic()` and pass a topic which will return -a `Modal.Model.Session` object containing requestId, method, chainIs and params for pending request. - - - - - -You can launch the currently connected wallet by calling `service.launchCurrentWallet()`. - - - - - -#### useWalletConnectModal - -Hook to programmatically control the modal. Useful when you want to use your own UI elements and subscribe to modals state. - -\*Note: A new session is created automatically when the modal is opened, so avoid calling `provider.connect` by yourself. - -```tsx -import { useWalletConnectModal } from "@walletconnect/modal-react-native"; - -const { isOpen, open, close, provider, isConnected, address } = useWalletConnectModal(); - -// Modal's open state -isOpen; - -// Open modal -interface Options { - route?: 'ConnectWallet' | 'Qrcode' | 'WalletExplorer'; -} -await open(options?: Options); - -// Close modal -close(); - -// Initialized provider -provider; - -// Wallet connection state -isConnected; - -// Connected account's address -address; - -``` - -#### Example - -```tsx -import { Pressable, Text } from "react-native"; -import "@walletconnect/react-native-compat"; -import { - WalletConnectModal, - useWalletConnectModal, -} from "@walletconnect/modal-react-native"; - -const projectId = "YOUR_PROJECT_ID"; - -const providerMetadata = { - name: "YOUR_PROJECT_NAME", - description: "YOUR_PROJECT_DESCRIPTION", - url: "https://your-project-website.com/", - icons: ["https://your-project-logo.com/"], - redirect: { - native: "YOUR_APP_SCHEME://", - universal: "YOUR_APP_UNIVERSAL_LINK.com", - }, -}; - -function App() { - const { open, isConnected, provider } = useWalletConnectModal(); - - const onPress = () => { - if (isConnected) { - provider.disconnect(); - } else { - open(); - } - }; - - return ( - <> - - {isConnected ? "Disconnect" : "Connect"} - - - - ); -} -``` - - - - -#### Connection and Events - -- WalletConnect Modal is a singleton that can be accessed from any scene. -- By default Modal will initialize itself asynchronously on Awake. During initialization it will also try to connect - to the last - session. -- After initialization, Modal invokes `WalletConnectModal.Ready` static event. -- If `Ready` argument's `SessionResumed` is `true`, it means that Modal has successfully connected to the last - session. In this case you don't need to open the modal. Otherwise, open the modal with `WalletConnectModal.Open()` - static method. - -```csharp -private void Start() -{ - WalletConnectModal.Ready += (sender, args) => - { - if (args.SessionResumed) - { - // Session has been resumed, proceed to the game - } - else - { - // Session hasn't been resumed - - // Define required namespaces for new session - var requiredNamespaces = new RequiredNamespaces - { - { - "eip155", new ProposedNamespace - { - Methods = new[] - { - "eth_sendTransaction", - "personal_sign", - "eth_signTypedData" - }, - Chains = new[] - { - "eip155:1" - }, - Events = new[] - { - "chainChanged", - "accountsChanged" - } - } - } - }; - - var connectOptions = new ConnectOptions - { - RequiredNamespaces = requiredNamespaces - }; - - // Open the modal - WalletConnectModal.Open(new WalletConnectModalOptions - { - ConnectOptions = connectOptions - }); - } - }; -} -``` - -Subscribe to `ActiveSessionChanged` and `SessionDeleted` events. It's recommended to do it in `Ready` event handler. - -```csharp -WalletConnectModal.Ready += (sender, args) => -{ - // .... - - // Invoked after wallet connected - WalletConnect.Instance.ActiveSessionChanged += (_, sessionStruct) => - { - // Session connected/updated, proceed to the game if sessionStruct.topic is not null/empty - }; - - // Invoked after wallet disconnected - WalletConnect.Instance.SessionDisconnected += (_, _) => - { - // Session deleted, show sign in screen - }; -}; -``` - -#### Disconnection - -To disconnect from the current session, call `WalletConnectModal.Disconnect()` static method. - -### Interaction with RPC - -The WalletConnect Modal is responsible for facilitating communication between the game and the wallet. -Some methods do not require the user to interact with the wallet. For example, `eth_getBalance` is used to get the address balance, -and `eth_call` is used to read data from a smart contract without modifying its state, hence no signature is required. - -To call these methods, you can use the [Nethereum.Web3](https://www.nuget.org/packages/nethereum.web3) package. - -```csharp -private static async Task GetAccountBalance() -{ - var session = WalletConnect.Instance.ActiveSession; - - // Because one session can have multiple namespaces, we need to select one. - // In most cases, especially in games, dapp will use only one namespace. - var @namespace = session.Namespaces.First(); - var address = session.CurrentAddress(@namespace.Key).Address; - - var config = ProjectConfiguration.Load(); - - // Using WalletConnect Blockchain API: https://docs.walletconnect.com/cloud/blockchain-api - var url = $"https://rpc.walletconnect.com/v1?chainId={@namespace.Value.Chains[0]}&projectId={config.Id}"; - - var web3 = new Nethereum.Web3.Web3(url); - var balance = await web3.Eth.GetBalance.SendRequestAsync(address); - Debug.Log($"Balance of {address} in Wei: {balance.Value}"); - - var etherAmount = Nethereum.Web3.Web3.Convert.FromWei(balance.Value); - Debug.Log($"Balance of {address} in Ether: {etherAmount}"); -} -``` - -#### Interaction with Smart Contracts - -To query smart contracts, you can use [Nethereum.Web3](https://www.nuget.org/packages/nethereum.web3) package -to make `eth_call` requests directly to the RPC endpoint. -However, to call methods that modify the state of the smart contract, you need user to sign the transaction in the wallet. - -There are two ways to interact with smart contracts: - -- **With Interceptor**: using Nethereum's `RequestInterceptor` (recommended) -- **Manual**: using Nethereum's tools to encode data and make requests directly with WalletConnect - - - - - - WalletConnect provides a Nethereum interceptor utility that will route requests that require user signature to the wallet. - With this approach, you don't need to manually encode data and make requests. Use convenient Nethereum's methods to interact with smart contracts, and interceptor - will automatically route requests to the wallet. - - [WalletConnectUnity Nethereum source code](https://github.com/WalletConnect/WalletConnectUnity/tree/main/Packages/con.walletconnect.nethereum) - -#### Install interceptor - - ```bash - openupm add com.walletconnect.nethereum - ``` - - #### Use interceptor - - This example shows how to call `transfer` method of ERC20 smart contract using interceptor. - - ```csharp - // Nethereum's Web3 instance - var web3 = new Web3(); - - // Instance of WalletConnect singleton - var walletConnect = WalletConnect.Instance; - - // Interceptor that will route requests requiring signing to the wallet connected with WalletConnect - var walletConnectUnityInterceptor = new WalletConnectUnityInterceptor(walletConnect); - - // Assign the interceptor to the Web3 instance - web3.Client.OverridingRequestInterceptor = walletConnectUnityInterceptor; - - const string contractAddress = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"; - const string recipientAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; - const BigInteger amount = 1; - - // Get ERC20 contract service - var contractService = Web3Modal.Web3.Eth.ERC20.GetContractService(contractAddress); - - // Call transfer method of ERC20 contract - await contractService.TransferRequestAsync(recipientAddress, amount); - ``` - - Nethereum allows to deploy and interact with custom smart contracts as well. - Refer to the [Nethereum documentation](https://docs.nethereum.com/en/latest/nethereum-smartcontrats-gettingstarted/) for more information. - - - - - - The example below shows how to call `approve` method of WETH9 (Wrapped Ether) smart contract. It encodes data with Nethereum and makes request with WalletConnect. - - ```csharp - public async Task ContractTransaction() - { - var session = WalletConnect.Instance.ActiveSession; - - // Because one session can have multiple namespaces, we need to select one. - // In most cases, especially in games, dapp will use only one namespace. - var @namespace = session.Namespaces.First(); - var myAddress = session.CurrentAddress(@namespace.Key).Address; - - // Define contract and function details - var contractAddress = "0x4200000000000000000000000000000000000006"; - var toAddress = myAddress; // Use sender's address for the sake of example - var amount = new BigInteger(12345); - - // Define the parameters for the approve function - var parameters = new Parameter[] { - new("address", "guy"), - new("uint256", "wad") - }; - - var functionCallEncoder = new FunctionCallEncoder(); - var sha3Signature = new Sha3Keccack().CalculateHash("approve(address,uint256)"); - - // Encode the parameters - var encodedParameters = functionCallEncoder - .EncodeParameters(parameters, toAddress, amount) - .ToHex(); - - // Combine signature and parameters - var data = "0x" + sha3Signature[..8] + encodedParameters; - - // Create transaction - var ethSendTransaction = new EthSendTransaction(new Transaction - { - From = myAddress, - To = contractAddress, - Value = "0", - Data = data - }); - - try - { - var result = await WalletConnect.Instance.RequestAsync(ethSendTransaction); - Debug.Log($"Transaction success! TxHash: {result}", this); - } - catch (Exception e) - { - Debug.LogError(e, this); - } - } - - public class Transaction - { - [JsonProperty("from")] public string From { get; set; } - - [JsonProperty("to")] public string To { get; set; } - - [JsonProperty("gas", NullValueHandling = NullValueHandling.Ignore)] - public string Gas { get; set; } - - [JsonProperty("gasPrice", NullValueHandling = NullValueHandling.Ignore)] - public string GasPrice { get; set; } - - [JsonProperty("value")] public string Value { get; set; } - - [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)] - public string Data { get; set; } = "0x"; - } - - [RpcMethod("eth_sendTransaction"), RpcRequestOptions(Clock.ONE_MINUTE, 99997)] - public class EthSendTransaction : List - { - public EthSendTransaction(params Transaction[] transactions) : base(transactions) - { - } - - [Preserve] - public EthSendTransaction() - { - } - } - ``` - - Please refer to [Nethereum](https://nethereum.com/) documentation for more details. Nethereum provides tools to simplify encoding and decoding. - These tools hadn't been used in the example above to better illustrate the process. - - - - - -#### Subscribe to session events - -```csharp -var signClient = WalletConnect.Instance.SignClient; -signClient.SubscribeToSessionEvent("chainChanged", OnChainChanged); -``` - - - diff --git a/advanced/walletkit-migration.mdx b/advanced/walletkit-migration.mdx new file mode 100644 index 000000000..a9252b020 --- /dev/null +++ b/advanced/walletkit-migration.mdx @@ -0,0 +1,17 @@ +--- +title: "WalletKit Migration" +description: "WalletKit documentation has moved to the WalletConnect Docs. Find links to the new locations for all migrated pages." +sidebarTitle: "WalletKit Migration" +--- + +The following WalletKit-related pages have been migrated from Reown Docs to the [WalletConnect Docs](https://docs.walletconnect.network). Use the links below to find the updated content. + +## Migrated Pages + +| Former Reown Docs Page | New WalletConnect Docs Location | +| --- | --- | +| WalletGuide Submission | [WalletGuide Submission](https://docs.walletconnect.network/walletguide/explorer-submission) | +| Deprecated WalletConnect SDKs | [Upgrade from Web3Wallet to Wallet SDK](https://docs.walletconnect.network/wallet-sdk/upgrade/from-web3wallet-to-reown) | +| Sign API - Wallet Usage | [Wallet SDK Web - One-click Auth](https://docs.walletconnect.network/wallet-sdk/web/one-click-auth) and platform-specific Usage pages ([Web](https://docs.walletconnect.network/wallet-sdk/web/usage), [iOS](https://docs.walletconnect.network/wallet-sdk/ios/usage), [React Native](https://docs.walletconnect.network/wallet-sdk/react-native/usage)) | +| WalletConnectModal Usage | [App SDK Overview](https://docs.walletconnect.network/app-sdk/overview) | +| WalletConnectModal Resources | [Wallet SDK Web - Resources](https://docs.walletconnect.network/wallet-sdk/web/resources) and [Wallet SDK React Native - Resources](https://docs.walletconnect.network/wallet-sdk/react-native/resources) | diff --git a/cloud/explorer-submission.mdx b/cloud/explorer-submission.mdx deleted file mode 100644 index fa1e67d06..000000000 --- a/cloud/explorer-submission.mdx +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: WalletGuide Submission ---- - - - -Submitting a project to the Reown Dashboard Explorer is recommended but optional. You can still use Reown 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 Reown Dashboard by navigating to [dashboard.reown.com](https://dashboard.reown.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, go to the "**Projects**" section under **Cloud** and click on "**+ Project**". - - - - - -- Give a suitable name for your project, select Wallet (WalletKit) and click the "Create" button. You can change the name for your project later. - - - - - - -## Project Details - -- Click on “WalletGuide” to proceed to fill in the details of your wallet. - - - - - -- You will now see an option to publish your wallet to WalletGuide. Click "Publish" to proceed. - - - - - -- You will now see a form to fill in the details of your wallet as shown below. - -| Field | Description | Required | -|------------------------------|-----------------------------------------------------------------------------|----------| -| Name | The name to display in the explorer | yes | -| Description | A short description explaining your project (dapp/wallet) | yes | -| Type | Whether your project is a dapp or a wallet | yes | -| Category | Appropriate category for your project. This field is dependent on the type of your project | yes | -| Homepage | The URL of your project | yes | -| Web App | The URL of your web app. This field is only applicable for dapps | yes | -| Chains | Chains supported by your project | yes | -| Logo | The logo of your project. Further requirements are provided in the explorer submission form | yes | -| Testing Instructions | Instructions on how to test your Reown Integration | yes | -| Download Links | Links to download your project (if applicable) | no | -| Mobile Linking | Required for mobile wallets targeting AppKit. Deep Link is recommended over Universal Link | no | -| Desktop Linking | Required for desktop wallets targeting AppKit. | no | -| Injected Wallet Identifiers | Required for injected wallets targeting AppKit. RDNS (from EIP-6963 metadata) is recommended over Provider Flags(Legacy) | no | -| Metadata | User-facing UI metadata for your project. Only Short Name is required. | no | - - -## Project Submission - -- Once you've filled the applicable fields, click the "Submit" button to submit your project for review. Alternatively, you can save your changes and submit later. Additional information will be visible in the modal that appears after clicking the "Submit" button. - - - - - -## 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. |e. | -| **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. |e. | -| **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. |e. | - - -
-
- -## What's Next? - -Now depending on whether or not your submission met all parameters, you will receive an email from the Reown team with the status of your submission. This change will also be reflected with more directions in the "Explorer" tab of your project. -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 "Explorer" 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/docs.json b/docs.json index b0de9cfca..715882eff 100644 --- a/docs.json +++ b/docs.json @@ -661,7 +661,6 @@ { "group": "WalletGuide", "pages": [ - "cloud/explorer-submission", { "group": "WalletGuide Chains", "pages": ["cloud/chains/overview", "cloud/chains/chain-list"] @@ -748,7 +747,6 @@ "pages": [ "advanced/api/sign/overview", "advanced/api/sign/dapp-usage", - "advanced/api/sign/wallet-usage", "advanced/api/sign/smart-contract-wallet-usage" ] } @@ -762,7 +760,7 @@ ] }, "advanced/push-server", - "advanced/walletconnect-deprecations" + "advanced/walletkit-migration" ] }, {