Wallet Connect
IMPORTANT
WalletConnect V1 has been sunset on 28th June 2023 and the bridge servers has been taken offline. This means that this package won't work anymore without unofficial V1 bridge server.
Please read more about V1 sunset here.
WalletConnect is an open-source protocol for connecting decentralised applications to mobile wallets with QR code scanning or deep linking. A user can interact securely with any Dapp from their mobile phone, making WalletConnect wallets a safer choice compared to desktop or browser extension wallets.
Introduction
This package provides UX for dApp to seamlessly connect to a wallet app. On iOS list of wallet apps is provided for the user to select from, on Android there is one click connect. QR code option is also provided.
The package uses walletconnect-dart package for underlying WalletConnect communication.
Usage
Once installed, you can simply connect your application to a wallet.
Initiate connection - show QR code modal
// Create a connector
final qrCodeModal = WalletConnectQrCodeModal(
connector: WalletConnect(
bridge: 'https://bridge.walletconnect.org',
clientMeta: const PeerMeta( // <-- Meta data of your app appearing in the wallet when connecting
name: 'QRCodeModalExampleApp',
description: 'WalletConnect Developer App',
url: 'https://walletconnect.org',
icons: [
'https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media'
],
),
),
);
// Try to initiate connection
final session = await qrCodeModal.connect(context).catchError((error) {
print('Error: $error');
return null;
});
// Subscribe to events
qrCodeModal.registerListeners(
onConnect: (session) => print('Connected: $session'),
onSessionUpdate: (response) => print('Session updated: $response'),
onDisconnect: () => print('Disconnected'),
);
// Create QR code modal and connect to a wallet, connector returns WalletConnect
// session which can be saved and restored.
final session = await qrCodeModal.connect(context, chainId: 2)
// Errors can also be caught from connector, eg. session cancelled
.catchError((error) {
// Handle error here
debugPrint(error);
return null;
});
Send transaction
Example of Ethereum transaction:
final provider = EthereumWalletConnectProvider(connector);
final ethereum = Web3Client('https://goerli.infura.io/', Client());
final sender = EthereumAddress.fromHex(session.accounts[0]);
final transaction = Transaction(
to: sender,
from: sender,
gasPrice: EtherAmount.inWei(BigInt.one),
maxGas: 100000,
value: EtherAmount.fromUnitAndValue(EtherUnit.finney, 1),
);
final credentials = WalletConnectEthereumCredentials(provider: provider);
// Send the transaction
final txBytes = await ethereum.sendTransaction(credentials, transaction);
Kill session
await qrCodeModal.killSession();
Customizations
The library UI is completely customizable through its modalBuilder
builder. It lets you either customize existing UI elements or replace them with your own.
Each builder needs to return a Widget
to be used by the package. For convenience defaultWidget
is always provided in the builder to either be customised using its copyWith
method or replaced completely with another widget.
For example, if you want to change the card color of the modal:
WalletConnectQrCodeModal(
connector: WalletConnect(
...
),
modalBuilder: (context, uri, callback, defaultModalWidget) {
return defaultModalWidget.copyWith(
cardColor: Colors.pink,
);
});
You could also return your custom widget in the builder rather than the defaultModalWidget
if the level of customization is not sufficient. All the necessary data to build your own widget are either passed in through the builder arguments or can be obtained from the default...Widget
.
For example, the main modalBuilder
passes through the uri
which is the WalletConnect URI and walletCallback
which should be called when the Wallet
is selected.
Various UI elements are accessible through different builders which allows you to mix and match which bits you want to customize or which to replace.
Builders
modalBuilder
- the main builder representing the whole modal, provides defaultModalWidget
ModalWidget
builders:
selectorBuilder
- represents the Wallet list or QR code selectorwalletButtonBuilder
- represents Android modal content (single button with 'Connect')walletListBuilder
- represents iOS/Desktop modal content (list of wallets)qrCodeBuilder
- represents QR Code content
ModalSelectorWidget
builder:
walletSegmentThumbBuilder
- represents the Wallet/Desktop segmented control thumbqrSegmentThumbBuilder
- represents the QR Code segmented control thumb
ModalWalletListWidget
builders:
rowBuilder
- represents a Wallet row in the Wallet listsearchBuilder
- represents a search/filter widget to filter Wallet list.onSearchTermChanged
callback needs to be implemented for filtering to work. The functionality is based on Wallet name.
Properties
List of customisable widgets:
ModalWidget
- represents the whole modalModalSelectorWidget
- represents the segmented control widget for choosing between list and QR codeModalSegmentThumbWidget
- represents a segment in the main segmented control widgetModalWalletButtonWidget
- represents the single button widget (for Android)ModalWalletListWidget
- represents the list of wallets (for iOS and desktop)ModalQrCodeWidget
- represents the QR code widget
Note on iOS
There are currently 2 mechanisms to navigate from one app to another using links in iOS: using native (deep) links (an older mechanism) and universal links. These are preferred and use the usual http(s) scheme. The native links use custom schemes (eg. algorand://
) and proper use of custom schemes requires special permissions in iOS (scheme needs to be added to LSApplicationQueriesSchemes
).
Each Wallet registry record (which the package uses to determine how to communicate with the Wallet app) can specify either a native (deep) link or universal link (or both). The package first tries to verify the universal link and if this fails uses the native link. The problem is that without the special permission mentioned above the app is unable to verify the deep link. As a workaround, the package does not verify the deep links and just invokes them. The downside of this approach is that if the corresponding Wallet app is not installed, the OS would just try to open Safari and throws an error about an invalid link.
You can override this default behavior by setting shouldVerifyNativeLinks
to true
on the defaultModalWidget
. This allows for greater flexibility when you are only interested in some Wallets (using only deep links) and want the correct behaviour. Note that the verification will always fail if the custom scheme is not added to LSApplicationQueriesSchemes
and the app will be redirected to App Store.
NOTE: This would ONLY affect Wallets without registered universal links.
References:
canOpenUrl
url_launcher
- package used internally to lauch WC URLs
Platform overrides
It is possible override the default behavior on certain platform to customize the platform experience. For example you can override for Android to show the wallet list rather than a single button. It is recommended to stick with platform defaults.
Example:
modalBuilder: (context, uri, callback, defaultModalWidget) {
return defaultModalWidget.copyWith(
platformOverrides: const ModalWalletPlatformOverrides(
android: ModalWalletType.listMobile,
),
);
}
This would force the library to use walletListBuilder
on the Android platform. There are 3 types of types available:
button
- shows single button (default for Android),walletButtonBuilder
is usedlistMobile
- shows list of possible wallets which can be linked on the mobile platform (default for iOS),walletListBuilder
is usedlistDesktop
- shows list of possible wallets which can be linked on the desktop platform (default for desktop),walletListBuilder
is used
Platform can be overriden to use any of the above types, the default functionality is not guaranteed (due to restriction on some platforms) but it allows more customization on each platform.
Example
The aim of the example app is to demonstrate simple transaction using QR code modal. The connected wallet has to be configured for Ethereum (Goerli) or Algorand test network with at least 0.001 tokens available (plus fee amount for the transaction). After connecting to the wallet the app would try to transfer 0.001 Eth/Algo from the wallet account to the same account (you should see some fee being deducted as well).
Migration guide
0.1.x to 0.2.x
selectorBuilder
was added to add more flexibility to customize the whole selector segmented control. ModalSelectorWidget
now represents this widget.
walletSegmentThumbBuilder
andqrSegmentThumbBuilder
was moved into the newModalSelectorWidget
segmentedControlBackgroundColor
was renamed tobackgroundColor
and moved toModalSelectorWidget
segmentedControlPadding
was renamed topadding
and moved toModalSelectorWidget
cardShape
was added toModalWidget
to represent card shape parameter
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.