Wallet Connect SDK made in ❤️ with dart.
To configure your app use latest version of wallet_connect_dart_v2
, see pub.dev
Note: In order to use wallet_connect_dart_v2 alongside the legacy v1 sdk, see wallet_connect.
For detailed implementation of dapp usage, see example-dapp.
For detailed implementation of wallet usage, see example-wallet.
- Initialization
- Pairing via QR
- Pairing Via URI
- Responding to Session Proposal
- Responding to Dapp Requests
- Responding to Dapp Events
- Responding to Ping
- Responding to Session Delete
- Sending Requests to Dapp
import 'package:wallet_connect_dart_v2/wallet_connect_dart_v2.dart';
final signClient = await SignClient.init(
projectId: "PROJECY_ID",
relayUrl: "RELAY_URL", // or leaving it empty, uses default "wss://relay.walletconnect.com"
metadata: const AppMetadata(
name: "Demo app",
description: "Demo Client as Wallet/Peer",
url: "www.walletconnect.com",
icons: [],
),
database: 'DB_NAME', // optional, if empty all session data will be stored in memory
);
We have used ScanView for this you can use any other package as well.
Scan the QR code to get pairing URI.
ScanView(
controller: ScanController(),
onCapture: (data) {
if (Uri.tryParse(value) != null) {
signClient.pair(value);
}
},
);
Directly use pair
functionality from SignClient
instance
await signClient.pair(value);
The SignClientEvent.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.
You can listen for this event while initializing client:
signClient.on(SignClientEvent.SESSION_PROPOSAL.value, (data) {
final eventData = data as SignClientEventParams<RequestSessionPropose>;
// Show session proposal data to the user i.e. in a popup with options to approve / reject it
const approve = true;
// On Approve Session Proposal
if(approve) {
//
final SessionNamespaces namespaces = {
// Provide the namespaces and chains (e.g. `eip155` for EVM-based chains) being requested by dapp.
"eip155": SessionNamespace(
// `accounts` addresses need to be passed from the wallet side int the specified format as per the number of chains being requested by dapp
accounts: ["eip155:1:0x0000000000..., eip155:10:0x0000000000..."],
// `methods and `events` Can be accessed at `eventData.params!.requiredNamespaces`
methods: [
"eth_sendTransaction",
"eth_signTransaction",
"eth_sign",
"personal_sign",
"eth_signTypedData",
],
events: ["chainChanged", "accountsChanged"],
)
};
final params = SessionApproveParams(
id: eventData.id!,
namespaces: namespaces,
);
signClient.approve(params);
}
// Or Reject Session Proposal
else {
final params = SessionRejectParams(
id: eventData.id!,
reason: formatErrorMessage(
error: getSdkError(SdkErrorKey.USER_DISCONNECTED),
),
);
signClient.reject(params);
}
});
The SignClientEvent.SESSION_REQUEST
event is triggered when a dapp sends a request to the wallet for a specific action, such as signing a transaction. This event is emitted by the dapp and received by the wallet. To respond to the request, wallets should call the specific required sign function and pass in details from the request. You can then approve or reject the request based on the response.
signClient.on(SignClientEvent.SESSION_REQUEST.value, (data) async {
final eventData = data as SignClientEventParams<RequestSessionRequest>;
final String method = eventData.params!.request.method;
// Example handling some methods from EVM-based chains
if (method == "personal_sign") {
final requestParams = eventData.params!.request.params[0];
final dataToSign = requestParams["data"];
final address = requestParams["to"];
// Handle request params to generate necessary result and send back the response to dapp.
final signedDataHex = personalSign(dataToSign, address);
// Approve the request
signClient!.respond(
SessionRespondParams(
topic: eventData.topic!,
response: JsonRpcResult<String>(
id: eventData.id!,
result: signedDataHex,
),
),
);
// Or Reject the request with error
_signClient!.respond(SessionRespondParams(
topic: eventData.topic!,
response: JsonRpcError(id: eventData.id!),
));
} else if (method == "eth_sign") {
// Handle `eth_sign`
} else if (method == "eth_signTypedData") {
// Handle `eth_signTypedData`
} else if (method == "eth_sendTransaction") {
final requestParams = eventData.params!.request.params[0];
// Handle `eth_sendTransaction`
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Send transaction'),
actions: <Widget>[
TextButton(
onPressed: () {
// You can use web3dart package to excecute transaction
// then pass it in params to respond
final txhash = _web3client.sendTransaction();
signClient.respond(
SessionRespondParams(
topic: eventData.topic!,
response: JsonRpcResult<String>(
id: eventData.id!,
result: txhash,
),
),
);
Navigator.of(context).pop();
},
child: Text('Accept'),
),
TextButton(
onPressed: () {
signClient.respond(SessionRespondParams(
topic: eventData.topic!,
response: JsonRpcError(id: eventData.id!),
));
Navigator.of(context).pop();
},
child: Text('Cancel'),
),
],
);
},
);
} else if (method == "eth_signTransaction") {
// Handle `eth_signTransaction`
}
});
signClient!.on(SignClientEvent.SESSION_EVENT.value, (data) {
final eventData = data as SignClientEventParams<RequestSessionEvent>;
// Handle events request
});
signClient!.on(SignClientEvent.SESSION_PING.value, (data) {
final eventData = data as SignClientEventParams<void>;
// Handle Ping request
});
signClient!.on(SignClientEvent.SESSION_DELETE.value, (data) {
final eventData = data as SignClientEventParams<void>;
// Handle Session Delete request
});
If either the dapp or the wallet decides to disconnect the session, the SignClientEvent.SESSION_DELETE
event will be emitted. The wallet should listen for this event in order to update the UI.
To disconnect a session from the wallet, call the disconnect
function and pass in the topic and reason. You can optionally send the reason for disconnect to dapp.
await signClient.disconnect(topic: "TOPIC");
To extend the session, call the extend
method and pass in the new topic. The SignClientEvent.SESSION_UPDATE
event will be emitted from the wallet.
await signClient.extend("TOPIC");
The SignClientEvent.SESSION_UPDATE
event is emitted from the wallet when the session is updated by calling update
.
To update a session, pass in the new SessionUpdateParams
await signClient.update(params);
To emit sesssion events, call the emit
and pass in the params. It takes SessionEmitParams
as a parameter.
final SessionEmitParams params = SessionEmitParams(
topic: "TOPIC",
event: SessionEmitEvent(
name: "NAME",
data: ["DATA_1"],
),
chainId: "CHAIN_ID");
await signClient.emit(params);