> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletconnect.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage

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

## Content

Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section.

**[Initialization](#initialization)**: Creating a new ReownWalletKit instance and initializing it with a projectId from [WalletConnect Dashboard](https://dashboard.walletconnect.com).

**Session**: Connection between a dapp and a wallet.

* [Namespace Builder](#namespace-builder):
  Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object
* [Session Approval](#session-approval):
  Approving a session sent from a dapp
* [Session Rejection](#session-rejection):
  Rejecting a session sent from a dapp
* [Responding to Session Requests](#responding-to-session-requests):
  Responding to session requests sent from a dapp
* [Updating a Session](#updating-a-session):
  Updating a session sent between a dapp and wallet
* [Extending a Session](#extending-a-session):
  Extending a session between a dapp and wallet
* [Session Disconnect](#session-disconnect):
  Disconnecting a session between a dapp and wallet
* [Formatted Errors](#formatted-errors):
  A list of useful error objects to be used

<Info>
  **Don't have a project ID?**

  Head over to WalletConnect Dashboard and create a new project now!

  <Card title="Get started" href="https://dashboard.walletconnect.com/?utm_source=cloud_banner&utm_medium=docs&utm_campaign=backlinks" />
</Info>

## Initialization

To create an instance of ReownWalletKit, you need to pass in the `core` and `metadata` parameters.

```javascript theme={null}
final _walletKit = ReownWalletKit(
  core: ReownCore(
    projectId: '{YOUR_PROJECT_ID}',
  ),
  metadata: PairingMetadata(
    name: 'Example Wallet',
    description: 'Example wallet description',
    url: 'https://example.com/',
    icons: ['https://example.com/logo.png'],
    redirect: Redirect(
      native: 'examplewallet://',
      universal: 'https://reown.com/examplewallet',
    ),
  ),
);
```

## Session

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

### Namespace Builder

On flutter you don't need to worry about Namespace Builder as Flutter SDK would handle that for you and generate a namespace object with the supported ones for you to approve.

All you have to do is make sure you register...

1. **wallet's accounts** with `_walletKit.registerAccount()` for accounts you want events and methods to be enabled on. This is essential if you want to properly form a session object between your wallet and the requester dapp.
2. **request handlers** with `_walletKit.registerRequestHandler()` for methods you want to support on your wallet. Optional but **highly recommended** if you want to seamlessly create a session object, as we will see in the coming section.
3. **events emitters** with `_walletKit.registerEventEmitter()` for events you want to support on your wallet. Optional but recommended if you plan to send events such as `chainChanged` and `accountsChanged`.

And you'll have to do this **for every chain** you want to support on your wallet.

```dart theme={null}
// Quick example:

List<String> supportedChains = ['eip155:1', 'eip155:10', ...];
List<String> walletAddresses = ['0x1234......'];
List<String> supportedEvents = ['chainChanged', 'accountsChanged', ...];

Map<String, dynamic Function(String, dynamic)> get _methodHandlers => {
  'personal_sign': personalSignHandler,
  'eth_sendTransaction': ethSendTransactionHandler,
};

for (final chainId in supportedChains) {
  for (var address in walletAddresses) {
    _walletKit!.registerAccount(
      chainId: chainId, // CAIP-2 format chain id
      accountAddress: address, // 0x.... address
    );
  }

  for (var handler in _methodHandlers.entries) {
    _walletKit.registerRequestHandler(
      chainId: chainId,
      method: handler.key,
      handler: handler.value,
    );
  }

  for (final event in supportedEvents) {
    _walletKit.registerEventEmitter(
      chainId: chainId,
      event: event,
    );
  }
}
```

When a dApp propose a session, with declared namespaces, your wallet will be able to approve an **already generated set of namespaces** based on your registered accounts, methods and events.

You can access this object in **SessionProposalEvent** during `onSessionProposal` event by querying `event.params.generatedNamespaces`. (See [Session Approval](#session-approval) below)

<Note>
  You can choose **not to use** `registerRequestHandler` to configure your supported methods and rather define them during session approval (See [Session Approval](#session-approval) below)

  By not using `registerRequestHandler` your methods requests are going to be sent through `onSessionRequest` event subscription.

  If you do choose to use `registerRequestHandler` **(highly recommended)** then `onSessionRequest` event subscription is not going to be called.
</Note>

Flutter SDK provides a handy `MethodsConstants` and `EventsConstants` for already defined set of required and optional values.

### EVM methods & events

In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events:

```ts theme={null}
{
  //...
  methods: [
    "eth_accounts",
    "eth_requestAccounts",
    "eth_sendRawTransaction",
    "eth_sign",
    "eth_signTransaction",
    "eth_signTypedData",
    "eth_signTypedData_v3",
    "eth_signTypedData_v4",
    "eth_sendTransaction",
    "personal_sign",
    "wallet_switchEthereumChain",
    "wallet_addEthereumChain",
    "wallet_getPermissions",
    "wallet_requestPermissions",
    "wallet_registerOnboarding",
    "wallet_watchAsset",
    "wallet_scanQRCode",
    "wallet_sendCalls",
    "wallet_getCallsStatus",
    "wallet_showCallsStatus",
    "wallet_getCapabilities",
  ],
  events: [
    "chainChanged",
    "accountsChanged",
    "message",
    "disconnect",
    "connect",
  ]
}
```

### Session Approval

As mentioned before, the `SessionProposalEvent` is emitted when a dapp initiates a new session with your wallet. The event object will include the information about the dapp and requested namespaces. The wallet should display a prompt for the user to approve or reject the session.

To approve a session, subscribe to `onSessionProposal` event and call `approveSession()` passing in the `event.id` and the namespaces object.

```javascript theme={null}
_walletKit.onSessionProposal.subscribe((SessionProposalEvent? event) {
  // display a prompt for the user to approve or reject the session
  // ....
  // If approved
  _walletKit.approveSession(
    id: event.id,
    namespaces: event.params.generatedNamespaces ?? {},
  );
});
```

<Note>
  As mentioned before, `namespaces:` should be either `event.params.generatedNamespaces!` if you decided to use `registerRequestHandler` method to configure your supported methods or a `Map<String, Namespace>` object defined by yourself if you decided **not** to use `registerRequestHandler` method
</Note>

#### Pairing

The `pair` method initiates a pairing process with a dapp using the given `uri` (QR code from the dapps). To learn more about pairing, checkout out the [docs](https://specs.walletconnect.com/2.0/specs/clients/core/pairing/).

Scan the QR code and parse the URI, and pair with the dapp.\
Upon the first pairing, you will immediately receive `onSessionProposal` and `onAuthRequest` events.

```javascript theme={null}
Uri uri = Uri.parse(scannedUriString);
await _walletKit.pair(uri: uri);
```

### Session Rejection

To reject the request, pass in an error code and reason according to [protocol specs](https://specs.walletconnect.com/2.0/specs/clients/sign/error-codes). See also [Formatted Errors](#formatted-errors) section.

To reject a session:

```javascript theme={null}
_walletKit.onSessionProposal.subscribe((SessionProposalEvent? event) async {
  // display a prompt for the user to approve or reject the session
  // ....
  // If rejected
  await _walletKit.rejectSession(
    id: event.id,
    reason: Errors.getSdkError(Errors.USER_REJECTED).toSignError(),
  );
});
```

### Responding to Session requests

To handle a session request, such as `personal_sign`, you have two ways as explained before, and they are mutually exclusive, so, either you use onSessionRequest event subscription or your methods handlers configured with `registerRequestHandler`.

1. The **recommended one** is to register a request handler for the methods and chains you want to support. So let's say your wallet supports `eip155:1` and `eip155:137`. This would translate to:

```javascript theme={null}
final supportedChains = ['eip155:1', 'eip155:137'];
Map<String, dynamic Function(String, dynamic)> supportedMethods = {
  'personal_sign': _personalSignHandler,
  'eth_sendTransaction': _ethSendTransactionHandler,
};
// Register your handlers as stated in Namespace Builder section
for (var chainId in supportedChains) {
  for (var method in supportedMethods.entries) {
    _walletKit.registerRequestHandler(
      chainId: chainId,
      method: method.key,
      handler: method.value,
    );
  }
}

Future<void> _personalSignHandler(String topic, dynamic params) async {
  final SessionRequest pendingRequest = _walletKit.pendingRequests.getAll().last;
  final int requestId = pendingRequest.id;

  // message should arrive encoded
  final decoded = hex.decode(params.first.substring(2));
  final message = utf8.decode(decoded);

  // display a prompt for the user to approve or reject the request
  // if approved
  if (approved) {
    // Your code to sign the message here
    final signature = await signMessage(message);

    return _walletKit.respondSessionRequest(
      topic: topic,
      response: JsonRpcResponse(
        id: requestId,
        jsonrpc: '2.0',
        result: signature,
      ),
    );
  }

  // if rejected
  return _walletKit.respondSessionRequest(
    topic: topic,
    response: JsonRpcResponse(
      id: id,
      jsonrpc: '2.0',
      error: const JsonRpcError(code: 5001, message: 'User rejected method'),
    ),
  );
}

Future<void> _ethSendTransactionHandler(String topic, dynamic params) async {
  final SessionRequest pendingRequest = _walletKit.pendingRequests.getAll().last;
  final int requestId = pendingRequest.id;
  final String chainId = pendingRequest.chainId;

  final transaction = (params as List<dynamic>).first as Map<String, dynamic>;

  // display a prompt for the user to approve or reject the request
  // if approved
  if (approved) {
    final signedTx = await sendTransaction(transaction, int.parse(chainId));
    // respond to requester
    await _walletKit.respondSessionRequest(
      topic: topic,
      response: JsonRpcResponse(
        id: requestId, 
        jsonrpc: '2.0', 
        result: signedTx,
      ),
    );
  }

  // if rejected
  return _walletKit.respondSessionRequest(
    topic: topic,
    response: JsonRpcResponse(
      id: id,
      jsonrpc: '2.0',
      error: const JsonRpcError(code: 5001, message: 'User rejected method'),
    ),
  );
}
```

2. The other way is subscribing to `onSessionRequest` events (if you didn't use `generatedNamespaces` object) and handle the request based on the method that is firing the event.

```javascript theme={null}
_walletKit.onSessionRequest.subscribe(_onSessionRequest);

void _onSessionRequest(SessionRequestEvent? event) async {
  if (event != null) {
    final id = event.id;
    final topic = event.topic;
    final method = event.method;
    final chainId = event.chainId;
    final params = event.params as List;

    // message should arrive encoded
    final decoded = hex.decode(params.first.substring(2));
    final message = utf8.decode(decoded);

    // display a prompt for the user to approve or reject the request
    // if approved
    if (approved) {
      // Your code to sign the message here
      final signature = ...

      return _walletKit.respondSessionRequest(
        topic: topic,
        response: JsonRpcResponse(
          id: id,
          jsonrpc: '2.0',
          result: signature,
        ),
      );
    }
    // if rejected
    return _walletKit.respondSessionRequest(
      topic: topic,
      response: JsonRpcResponse(
        id: id,
        jsonrpc: '2.0',
        error: const JsonRpcError(code: 5001, message: 'User rejected method'),
      ),
    );
  }
}
```

<Info>
  Remember that if you have handlers registered these are going to be triggered **instead of** the `onSessionRequest` event.
</Info>

### Updating a Session

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

After you update the session, the dapp connected to your wallet will receive a `SessionUpdate` event.

```javascript theme={null}
await _walletKit.updateSession(topic: 'topic', namespaces: '{}')
```

### Extending a Session

To extend the session, call the `extendSession` method and pass in the new `topic`. The `SessionUpdate` event will be emitted from the wallet.

```javascript theme={null}
await _walletKit.extendSession(topic: 'topic')
```

### Session Disconnect

To initiate a session disconnect, call the `disconnectSession` method and pass in the `topic` and a `reason`.

When either the dapp or the wallet disconnects from a session, a `SessionDelete` event will be emitted. It's important to subscribe to this event so you could keep your state up-to-date.

```javascript theme={null}
await _walletKit.disconnectSession(
  topic: session.topic,
  reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
);
```

Using `disconnectSession()` alone will make the pairing topic persist, i.e, it can be re-used until it expires. If you want to disconnect (remove) the pairing topic as well you would have add another call as follows:

```javascript theme={null}
await _walletKit.core.pairing.disconnect(
  topic: pairing.topic,
);
```

#### Supporting session events

In order to support session events, such as `chainChanged` or `accountChanged`, you would have to register an event emitter for such events, for every chain you want to emit an event for (similar to request handlers).

```javascript theme={null}
final supportedChains = ['eip155:1', 'eip155:137'];
const supportedEvents = ['chainChanged', 'accountChanged'];
for (var chainId in supportedChains) {
  for (var event in supportedEvents) {
    _walletKit.registerEventEmitter(
      chainId: chainId,
      event: event,
    );
  }
}
```

And to emit an event, call `emitSessionEvent()` as follows:

```javascript theme={null}
await _walletKit.emitSessionEvent(
  topic: session.topic,
  chainId: 'eip155:1',
  event: SessionEventParams(
    name: 'chainChanged',
    data: 1,
  ),
);
```

For a better understanding please check out the [example wallet](https://github.com/reown-com/reown_flutter/tree/master/packages/reown_walletkit/example/lib) and, in particular, the [EVMService](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_walletkit/example/lib/dependencies/chain_services/evm_service.dart) inside of it.

### Formatted Errors

Our SDK exports a variety of ready-made error objects for you to use in the different situations. Most commonly used are...

```javascript theme={null}
// When user rejects session proposal or method request.
final userRejectedError = Errors.getSdkError(Errors.USER_REJECTED).toSignError();

// When the request coming to your wallet can not be unparsed
final malformedRequest = Errors.getSdkError(Errors.MALFORMED_REQUEST_PARAMS).toSignError();

// When user disconnects the session
final userDisconnected = Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError();

// When dapp request an unsupported method to your wallet
final unsupportedMethods = Errors.getSdkError(Errors.UNSUPPORTED_METHODS).toSignError();
```

But you can check the full list of [available errors here](https://github.com/reown-com/reown_flutter/blob/master/packages/reown_core/lib/utils/errors.dart)
