Skip to main content

Usage

This section provides instructions on how to initialize the Web3Wallet client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface.

Don't have a project ID?

Head over to WalletConnect Cloud and create a New Project now!

Get startedcloud illustration

Initializationโ€‹

Create a new instance from Core and initialize it with a projectId created from installation. Next, create web3Wallet instance by calling init on Web3Wallet. Passing in the options object containing metadata about the app and an optional relay URL.

import { Core } from '@walletconnect/core'
import { Web3Wallet } from '@walletconnect/web3wallet'

const core = new Core({
projectId: process.env.PROJECT_ID
})

const web3wallet = await Web3Wallet.init({
core, // <- pass the shared `core` instance
metadata: {
name: 'Demo app',
description: 'Demo Client as Wallet/Peer',
url: 'www.walletconnect.com',
icons: []
}
})

Sessionโ€‹

A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires.

Namespace Builderโ€‹

With Web3Wallet v1.5.1 (and @walletconnect/utils v2.6.1) we've published a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns ready-to-use namespaces object.

// util params
{
proposal: ProposalTypes.Struct; // the proposal received by `.on("session_proposal")`
supportedNamespaces: Record< // your Wallet's supported namespaces
string, // the supported namespace key e.g. eip155
{
chains: string[]; // your supported chains in CAIP-2 format e.g. ["eip155:1", "eip155:2", ...]
methods: string[]; // your supported methods e.g. ["personal_sign", "eth_sendTransaction"]
events: string[]; // your supported events e.g. ["chainChanged", "accountsChanged"]
accounts: string[] // your user's accounts in CAIP-10 format e.g. ["eip155:1:0x453d506b1543dcA64f57Ce6e7Bb048466e85e228"]
}
>;
};

Example usage

// import the builder util
import { buildApprovedNamespaces } from '@walletconnect/utils'

web3wallet.on('session_proposal', async sessionProposal => {
const { id, params } = sessionProposal

// ------- namespaces builder util ------------ //
const approvedNamespaces = buildApprovedNamespaces({
proposal: params,
supportedNamespaces: {
eip155: {
chains: ['eip155:1', 'eip155:137'],
methods: ['eth_sendTransaction', 'personal_sign'],
events: ['accountsChanged', 'chainChanged'],
accounts: [
'eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb',
'eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb'
]
}
}
})
// ------- end namespaces builder util ------------ //

const session = await web3wallet.approveSession({
id,
namespaces: approvedNamespaces
})
})

If your wallet supports multiple namespaces e.g. eip155,cosmos & near Your supportedNamespaces should look like the following example.

// ------- namespaces builder util ------------ //
const approvedNamespaces = buildApprovedNamespaces({
proposal: params,
supportedNamespaces: {
eip155: {...},
cosmos: {...},
near: {...}
},
});
// ------- end namespaces builder util ------------ //

Session Approvalโ€‹

The session_proposal event is emitted when a dapp initiates a new session with a user's wallet. The event will include a proposal object with information about the dapp and requested permissions. The wallet should display a prompt for the user to approve or reject the session. If approved, call approveSession and pass in the proposal.id and requested namespaces.

The pair method initiates a WalletConnect pairing process with a dapp using the given uri (QR code from the dapps). To learn more about pairing, checkout out the docs.

web3wallet.on('session_proposal', async proposal => {
const session = await web3wallet.approveSession({
id: proposal.id,
namespaces
})
})
await web3wallet.pair({ uri })

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

  • No matching key. proposal id doesn't exist: 1

This rejection means the SDK can't find a record with the given proposal.id - in this example 1. This can happen when the proposal has expired (by default 5 minutes) or if you attempt to respond to a proposal that has already been approved/rejected. If you are seeing this error, please make sure that you are calling approveSession with the correct proposal.id that is available whithin the proposal payload.

  • Error: Missing or invalid. approve(), namespaces should be an object with data

This error means that the namespaces parameter passed to approveSession is either missing or invalid. Please check that you are passing a valid namespaces object that satisfies all required properties.

  • Non conforming namespaces. approve() namespaces <property> don't satisfy required namespaces.

This error indicates that some value(s) in your namespaces object do not satisfy the required namespaces requested by the dapp. To provide additional guidance, the message might include info about the exact property that is missing or invalid e.g. Required: eip155:1 Approved: eip155:137. Please check CAIP-25 to familiarize yourself with the standard and it's nuanses. Additonaly, we highly recommend you to use our namespace builder utility that would greatly simplify the process of parsing & building a valid namespaces object.

Session Rejectionโ€‹

In the event you want to reject the session proposal, call the rejectSession method. The getSDKError function comes from the @walletconnect/utils library.

web3wallet.on('session_proposal', async proposal => {
const session = await web3wallet.rejectSession({
id: proposal.id,
reason: getSdkError('USER_REJECTED_METHODS')
})
})

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

  • No matching key. proposal id doesn't exist: 1

This rejection means the SDK can't find a record with the given proposal.id - in this example 1. This can happen when the proposal has expired (by default 5 minutes) or if you attempt to respond to a proposal that has already been approved/rejected. If you are seeing this error, please make sure that you are calling rejectSession with the correct proposal.id that is available whithin the proposal payload.

  • Error: Missing or invalid. reject() reason:

This rejection means the reason parameter passed to rejectSession is either missing or invalid. We recommend using the getSDKError function from the @walletconnect/utils library that will populate & format the parameter for you.

Responding to Session requestsโ€‹

The session_request event is emitted when the SDK received a request from the peer and it needs the wallet to perform a specific action, such as signing a transaction. The event contains a topic and a request object, which will vary depending on the action requested.

To respond to the request, you can access the topic and request object by destructuring them from the event payload. To see a list of possible request and response objects, refer to the relevant JSON-RPC Methods for Ethereum, Solana, Cosmos, or Stellar.

As an example, if the dapp requests a personal_sign method, you can extract the params array from the request object. The first item in the array is the hex version of the message to be signed, which can be converted to UTF-8 and assigned to a message variable. The second item in params is the user's wallet address.

To sign the message, you can use your wallet's signMessage method and pass in the message. The signed message, along with the id from the event payload, can then be used to create a response object, which can be passed into respondSessionRequest.

web3wallet.on('session_request', async event => {
const { topic, params, id } = event
const { request } = params
const requestParamsMessage = request.params[0]

// convert `requestParamsMessage` by using a method like hexToUtf8
const message = hexToUtf8(requestParamsMessage)

// sign the message
const signedMessage = await wallet.signMessage(message)

const response = { id, result: signedMessage, jsonrpc: '2.0' }

await web3wallet.respondSessionRequest({ topic, response })
})

To reject a session request, the response should be similar to this.

const response = {
id,
jsonrpc: '2.0',
error: {
code: 5000,
message: 'User rejected.'
}
}

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

  • Error: No matching key. session topic doesn't exist: 'xyz...'

This rejection means the SDK can't find a session with the given topic - in this example xyz.... This can happen when the session has been disconnected by either the wallet or the dapp while the session request was being processed or if a session with such topic doesn't exist. If you are seeing this error, please make sure that you are using a correct topic that is available whithin the request payload.

  • Error: Missing or invalid. respond() response:

This rejection means the response parameter passed to respondSessionRequest is either missing or invalid. The response should be a valid JSON-RPC 2.0 response object. We recommend you to use our formatJsonRpcResult utility from "@walletconnect/jsonrpc-utils" that will format the response for you.

Example usage: id argument being the request id from the request payload.

import { formatJsonRpcResult } from '@walletconnect/jsonrpc-utils'

const signature = await cryptoWallet.signTransaction(signTransaction)
const response = await web3wallet.respondSessionRequest({
topic: session.topic,
response: formatJsonRpcResult(id, signature)
})

Updating a Sessionโ€‹

If you wish to include new accounts or chains or methods in an existing session, `updateSession` allows you to do so. You need pass in the `topic` and a new `Namespaces` object that contains all of the existing namespaces as well as the new data you wish to include. After you update the session, the other peer will receive a `session_update` event.

An example adding a new account to an existing session:

const namespaces = session.namespaces
const acounts = [
'eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb',
'eip155:1:0x1234567890123456789012345678901234567890'
]
const updatedNamespaces = {
...namespaces,
eip155: {
...namespaces.eip155,
accounts
}
}
await web3wallet.updateSession({ topic: session.topic, namespaces: updatedNamespaces })

An example adding a new chain to an existing session:

const namespaces = session.namespaces
const chains = ['eip155:1', 'eip155:137']
const acounts = [
'eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb',
'eip155:137:0x1234567890123456789012345678901234567890'
]
const updatedNamespaces = {
...namespaces,
eip155: {
...namespaces.eip155,
accounts,
chains
}
}
await web3wallet.updateSession({ topic: session.topic, namespaces: updatedNamespaces })

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

Note that all namespaces validation applies and you still have to satisfy the required namespaces requested by the dapp.

  • Error: No matching key. session topic doesn't exist: 'xyz...'

This rejection means the SDK can't find a session with the given topic - in this example xyz.... This can happen when the session you're trying to update has already been disconnected by either the wallet or the dapp or if a session with such topic doesn't exist. If you are seeing this error, please make sure that you are using a correct topic of an active session.

  • Error: Missing or invalid. update(), namespaces should be an object with data

This error means that the namespaces parameter passed to updateSession is either missing or invalid. Please check that you are passing a valid namespaces object that satisfies all required properties.

  • Non conforming namespaces. update() namespaces <property> don't satisfy required namespaces.

This error indicates that some value(s) in your namespaces object do not satisfy the required namespaces requested by the dapp. To provide additional guidance, the message might include info about the exact property that is missing or invalid e.g. Required: eip155:1 Approved: eip155:137. Please check CAIP-25 to familiarize yourself with the standard and it's nuanses. Additonaly, we highly recommend you to use our namespace builder utility that would greatly simplify the process of parsing & building a valid namespaces object.

Extending a Sessionโ€‹

Sessions have a default expiry of 7 days. To extend a session by an additional 7 days, call .extendSession method and pass in the topic of the session you wish to extend.

await web3wallet.extendSession({ topic })

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

  • Error: No matching key. session topic doesn't exist: 'xyz...'

This rejection means the SDK can't find a session with the given topic - in this example xyz.... This can happen when the session you're trying to update has already been disconnected by either the wallet or the dapp or if a session with such topic doesn't exist. If you are seeing this error, please make sure that you are using a correct topic of an active session.

Session Disconnectโ€‹

To initiate disconnnect from a session(think session delete), call .disconnectSession by passing a topic & reason for the disconnect. The other peer will receive a session_delete and be notified that the session has been disconnected.

Note

It's important that you're subscribed to the session_delete event as well, to be notified when the other peer initiates a disconnect.

Tip

We recommend using the getSDKError utility function, that will provide ready-to-use reason payloads and is available in the @walletconnect/utils library.

await web3wallet.disconnectSession({
topic,
reason: getSdkError('USER_DISCONNECTED')
})

๐Ÿ› ๏ธ Usage examplesโ€‹

โš ๏ธ Expected Errorsโ€‹

  • Error: No matching key. session topic doesn't exist: 'xyz...'

This rejection means the SDK can't find a session with the given topic - in this example xyz.... This can happen when the session you're trying to update has already been disconnected by either the wallet or the dapp or if a session with such topic doesn't exist. If you are seeing this error, please make sure that you are using a correct topic of an active session.

Auth Requestsโ€‹

Auth requests are used to authenticate a user with a dapp. The dapp will send a request to the wallet, which will then prompt the user to sign a message. The signed message will be sent back to the dapp, which will verify the signature and authenticate the user.

Note

Auth requests are only supported on iOS, Android, Flutter & C#

Setup Auth Requests Handlingโ€‹

When your Auth instance receives requests or responses from a peer client, it will publish a related event. So you should set a subscription to handle them.

Web3Wallet.instance.authRequestPublisher
.receive(on: DispatchQueue.main)
.sink { [self self] auth in
self?.verifyDapp(auth.context)
self?.showAuthRequest(auth.request)
}.store(in: &publishers)

VerifyContext provides a domain verification information about AuthRequest. 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 cloud.

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
}

Approve Auth Requestsโ€‹

Authorization request will be published by authRequestPublisher. When a wallet receives a request, you want to present it to the user and request a signature. After the user signs the authentication message, the wallet should respond to a dapp.

Type parameter represent signature validation method which will be used on dapp side. Supported signature validation methods: EIP191, EIP1271. In both cases message will be signed with EIP191 standard.

let signer = MessageSignerFactory.create()
let signature = try signer.sign(message: request.message, privateKey: privateKey, type: .eip191)
try await Web3WalletClient.respond(requestId: request.id, signature: signature, from: account)

Reject Auth Requestsโ€‹

In case user rejects an authentication request, call:

try await Web3WalletClient.reject(requestId: request.id)

Extra (Platform Specific)โ€‹

Emitting Session Eventsโ€‹

To emit session events, call the emitSessionEvent and pass in the params. If you wish to switch to chain/account that is not approved (missing from session.namespaces) you will have to update the session first. In the following example, the wallet will emit session_event that will instruct the dapp to switch the active accounts.

await web3wallet.emitSessionEvent({
topic,
event: {
name: 'accountsChanged',
data: ['0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb']
},
chainId: 'eip155:1'
})

In the following example, the wallet will emit session_event when the wallet switches chains.

await web3wallet.emitSessionEvent({
topic,
event: {
name: 'chainChanged',
data: 1
},
chainId: 'eip155:1'
})