{"id":13820305,"url":"https://github.com/walletconnect/walletconnectflutterv2","last_synced_at":"2025-04-07T12:10:17.328Z","repository":{"id":65909001,"uuid":"600004982","full_name":"WalletConnect/WalletConnectFlutterV2","owner":"WalletConnect","description":"WalletConnect v2 client made in Dart for Flutter.","archived":false,"fork":false,"pushed_at":"2024-09-17T13:11:22.000Z","size":5855,"stargazers_count":116,"open_issues_count":19,"forks_count":60,"subscribers_count":16,"default_branch":"develop","last_synced_at":"2024-10-29T10:34:52.418Z","etag":null,"topics":["dart","flutter"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/walletconnect_flutter_v2","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WalletConnect.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-10T11:18:07.000Z","updated_at":"2024-10-23T04:32:11.000Z","dependencies_parsed_at":"2023-09-29T07:33:53.097Z","dependency_job_id":"f4efe697-5967-40a3-a6e5-322ff60b6f7f","html_url":"https://github.com/WalletConnect/WalletConnectFlutterV2","commit_stats":{"total_commits":432,"total_committers":17,"mean_commits":25.41176470588235,"dds":0.5046296296296297,"last_synced_commit":"f36b8c6d6c0d368ecfa49f1823cfc6966f59156b"},"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WalletConnect%2FWalletConnectFlutterV2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WalletConnect%2FWalletConnectFlutterV2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WalletConnect%2FWalletConnectFlutterV2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WalletConnect%2FWalletConnectFlutterV2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WalletConnect","download_url":"https://codeload.github.com/WalletConnect/WalletConnectFlutterV2/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247648977,"owners_count":20972945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter"],"created_at":"2024-08-04T08:01:01.202Z","updated_at":"2025-04-07T12:10:17.311Z","avatar_url":"https://github.com/WalletConnect.png","language":"Dart","funding_links":[],"categories":["Flutter"],"sub_categories":["Flutter SDK / Libraries"],"readme":"# ⚠️ WARNING\n\n### This package is no longer maintened, please upgrade to Reown packages.\n\n- Reown packages: [https://pub.dev/publishers/reown.com/packages](https://pub.dev/publishers/reown.com/packages)\n- Read more at: [https://docs.reown.com/advanced/walletconnect-deprecations#flutter](https://docs.reown.com/advanced/walletconnect-deprecations#flutter)\n- WalletKit Updgrade guide: [https://docs.reown.com/walletkit/upgrade/from-web3wallet-flutter](https://docs.reown.com/walletkit/upgrade/from-web3wallet-flutter)\n- AppKit Updgrade guide: [https://docs.reown.com/appkit/upgrade/from-web3modal-flutter](https://docs.reown.com/appkit/upgrade/from-web3modal-flutter)\n\n# Overview\n\nWalletConnect Dart v2 package for WalletKit and AppKit. https://walletconnect.com/.\n\nCheck out official docs: https://docs.walletconnect.com/\n\n# To Use\n\n## Pair, Approve, and Sign/Auth\n\n### dApp Flow\n```dart\n// To create both an Auth and Sign API, you can use the Web3App\n// If you just need one of the other, replace Web3App with SignClient or AuthClient\n// SignClient wcClient = await SignClient.createInstance(\n// AuthClient wcClient = await AuthClient.createInstance(\n// BE MINDFUL THAT AuthClient is currently deprecated and will be removed soon.\n// Authentication methods, including One-Click Auth, are now withing SignClient\nWeb3App wcClient = await Web3App.createInstance(\n  projectId: '123',\n  relayUrl: 'wss://relay.walletconnect.com', // The relay websocket URL, leave blank to use the default\n  metadata: PairingMetadata(\n    name: 'Your dApp Name (Requester)',\n    description: 'A dapp that can request that transactions be signed',\n    url: 'https://walletconnect.com',\n    icons: ['https://avatars.githubusercontent.com/u/37784886'],\n    redirect: Redirect( // Specially important object if you the Wallet to navigate back to your dapp\n      native: 'mydapp://',\n      universal: 'https://mydapp.com/app',\n    ),\n  ),\n);\n\n// For a dApp, you would connect with specific parameters, then display\n// the returned URI.\nConnectResponse resp = await wcClient.connect(\n  optionalNamespaces: {\n    'eip155': RequiredNamespace(\n       // Any Ethereum chain you want to connect with\n      chains: ['eip155:1', 'eip155:5'],\n       // Requestable Methods, see MethodsConstants class for reference\n      methods: ['personal_sign', 'eth_sendTransaction'],\n       // Optional requestable events, see EventsConstants for reference\n      events: ['accountsChanged'],\n    ),\n  },\n);\n// display connection uri withih a QR code or use it to launch a wallet\nUri? uri = resp.uri;\n// Example:\n// final encodedUri = Uri.encodeComponent(uri.toString());\n// launchUrlString('metamask://wc?uri=$encodedUri', mode: LaunchMode.externalApplication);\n\n// Once you've displayed the URI, you can wait for the future, and hide the QR code once you've received session data\nfinal SessionData session = await resp.session.future;\n\n// Now that you have a session, you can request signatures\nfinal dynamic signResponse = await wcClient.request(\n  topic: session.topic,\n  chainId: 'eip155:1',\n  request: SessionRequestParams(\n    method: 'eth_signTransaction',\n    params: '{json serializable parameters}',\n  ),\n);\n// Unpack, or use the signResponse.\n// Structure is dependant upon the JSON RPC call you made.\n\n\n// [DEPRECATED]\n// You can also request authentication\nfinal AuthRequestResponse authReq = await wcClient.requestAuth(\n  params: AuthRequestParams(\n    aud: 'http://localhost:3000/login',\n    domain: 'localhost:3000',\n    chainId: 'eip155:1',\n    statement: 'Sign in with your wallet!',\n  ),\n  pairingTopic: resp.pairingTopic,\n);\n\n// Await the auth response using the provided completer\nfinal AuthResponse authResponse = await authReq.completer.future;\nif (authResponse.result != null) {\n  // Having a result means you have the signature and it is verified.\n\n  // Retrieve the wallet address from a successful response\n  final walletAddress = AddressUtils.getDidAddress(authResponse.result!.p.iss);\n}\nelse {\n  // Otherwise, you might have gotten a WalletConnectError if there was un issue verifying the signature.\n  final WalletConnectError? error = authResponse.error;\n  // Of a JsonRpcError if something went wrong when signing with the wallet.\n  final JsonRpcError? error = authResponse.jsonRpcError;\n}\n\n// Instead of connect() and then requestAuth() you can leverage One-Click Auth\n// Which is connection (session proposal) and authentication (SIWE) in just 1 step\nfinal SessionAuthRequestResponse authReq = await wcClient.authenticate(\n  params: SessionAuthRequestParams(\n    chains: ['eip155:1', 'eip155:5'],\n    domain: 'yourdomain.com',\n    uri: 'https://yourdomain.com/login',\n    nonce: AuthUtils.generateNonce(),\n    statement: 'Welcome to my example dApp.',\n    methods: ['personal_sign', 'eth_sendTransaction'],\n  ),\n);\n// display authentication uri withih a QR code or use it to launch a wallet\nUri? uri = authReq.uri;\n// Example:\n// final encodedUri = Uri.encodeComponent(uri.toString());\n// launchUrlString('metamask://wc?uri=$encodedUri', mode: LaunchMode.externalApplication);\n// IMPORTANT: Not every wallet supports One-Click Auth yet but don't worry, if wallet does not support it, \n// it will fallback to regular session proposal automatically\n\n// Once you've displayed the URI, you can wait for the future, and hide the QR code once you've received session data\nfinal SessionAuthResponse authResponse = await authReq.completer.future;\nif (authResponse.session != null) {\n  // Having a result means you have succesfully authenticated and created a session\n}\nelse {\n  // Otherwise, you might have gotten a WalletConnectError if there was un issue verifying the signature.\n  final WalletConnectError? error = authResponse.error;\n  // Of a JsonRpcError if something went wrong when signing with the wallet.\n  final JsonRpcError? error = authResponse.jsonRpcError;\n}\n\n\n\n// You can also respond to events from the wallet, like session events\nwcClient.registerEventHandler(\n  chainId: 'eip155:1',\n  event: 'accountsChanged',\n);\nwcClient.onSessionEvent.subscribe((SessionEvent? session) {\n  // Do something with the event\n});\n```\n\n### Wallet Flow\n```dart\nWeb3Wallet wcClient = await Web3Wallet.createInstance(\n  projectId: '123',\n  relayUrl: 'wss://relay.walletconnect.com', // The relay websocket URL, leave blank to use the default\n  metadata: PairingMetadata(\n    name: 'Your Wallet Name (Responder)',\n    description: 'A wallet that can be requested to sign transactions',\n    url: 'https://walletconnect.com',\n    icons: ['https://avatars.githubusercontent.com/u/37784886'],\n    redirect: Redirect( // Specially important object if you want dApps to be able to open you wallet\n      native: 'mywallet://',\n      universal: 'https://mywallet.com/app',\n    ),\n  ),\n);\n\n// For a wallet, setup the proposal handler that will display the proposal to the user after the URI has been scanned.\nlate int id;\nwcClient.onSessionProposal.subscribe((SessionProposal? args) async {\n  // Handle UI updates using the args.params\n  // Keep track of the args.id for the approval response\n  if (args != null) {\n    id = args!.id;\n    // To check VerifyAPI validation in regards of the dApp is trying to connnect you can check verifyContext\n    // More info about VerifyAPI https://docs.walletconnect.com/web3wallet/verify\n    final isScamApp = args.verifyContext?.validation.scam;\n    final isInvalidApp = args.verifyContext?.validation.invalid;\n    final isValidApp = args.verifyContext?.validation.valid;\n    final unknown = args.verifyContext?.validation.unknown;\n    //\n    // Present the UI to the user, and allow them to reject or approve the proposal\n    await wcClient.approveSession(\n      id: args.id,\n      namespaces: args.params.generatedNamespaces!,\n      sessionProperties: args.params.sessionProperties,\n    );\n    // Or to reject...\n    // Error codes and reasons can be found here: https://docs.walletconnect.com/2.0/specs/clients/sign/error-codes\n    await wcClient.rejectSession(\n      id: id,\n      reason: Errors.getSdkError(Errors.USER_REJECTED),\n    );\n  }\n});\n\n// If you are planning to support One-Click Auth then you would have to subscribe to onSessionAuthRequest events\nwcClient.onSessionAuthRequest.subscribe((SessionAuthRequest? args) async {\n  // Handle UI updates using the args.params\n  // Keep track of the args.id for the approval response\n  if (args != null) {\n    id = args!.id;\n    // To check VerifyAPI validation in regards of the dApp is trying to connnect you can check verifyContext\n    // More info about VerifyAPI https://docs.walletconnect.com/web3wallet/verify\n    final isScamApp = args.verifyContext?.validation.scam;\n    final isInvalidApp = args.verifyContext?.validation.invalid;\n    final isValidApp = args.verifyContext?.validation.valid;\n    final unknown = args.verifyContext?.validation.unknown;\n    //\n    // Process Authentication request\n    final SessionAuthPayload requestPayload = args.authPayload;\n    final responsePayload = AuthSignature.populateAuthPayload(\n      authPayload: requestPayload,\n      chains: ['eip155:1', 'eip155:5'], // Your supported EVM chains\n      methods: ['personal_sign', 'etg_sendTransaction'], // Your supported methods\n    );\n    // For every chain you support you decide to sign a the message\n    final message = _web3Wallet!.formatAuthMessage(\n      iss: 'did:pkh:eip155:1:0xADDRESS.....',\n      cacaoPayload: CacaoRequestPayload.fromSessionAuthPayload(\n        responsePayload,\n      ),\n    );\n    // final hexSignature = * signMessage(message) *\n    // And creates a Cacao object with it\n    final cacao = AuthSignature.buildAuthObject(\n      requestPayload: CacaoRequestPayload.fromSessionAuthPayload(\n        responsePayload,\n      ),\n      signature: CacaoSignature(\n        t: CacaoSignature.EIP191,\n        s: hexSignature,\n      ),\n      iss: 'did:pkh:eip155:1:0xADDRESS.....',\n    );\n    //\n    // To respond with the signed messages and create a session for the dapp you use approveSessionAuthenticate\n    await _web3Wallet!.approveSessionAuthenticate(\n      id: args.id,\n      auths: [cacao], // You would have here as many cacaos as messages your wallet signed\n    );\n    // To reject to session authenticate request you use rejectSessionAuthenticate\n    await _web3Wallet!.rejectSessionAuthenticate(\n      id: args.id,\n      reason: Errors.getSdkError(Errors.USER_REJECTED_AUTH),\n    );\n  }\n});\n\n// Also setup the methods and chains that your wallet supports\nfinal signRequestHandler = (String topic, dynamic parameters) async {\n  // Handling Steps\n  // 1. Parse the request, if there are any errors thrown while trying to parse\n  // the client will automatically respond to the requester with a \n  // JsonRpcError.invalidParams error\n  final parsedResponse = parameters;\n\n  // 1. If you want to fail silently, you can throw a WalletConnectErrorSilent\n  if (failSilently) {\n    throw WalletConnectErrorSilent();\n  }\n\n  // 2. Show a modal to the user with the signature info: Allow approval/rejection\n  bool userApproved = await showDialog( // This is an example, you will have to make your own changes to make it work.\n    context: context,\n    builder: (context) {\n      return AlertDialog(\n        title: const Text('Sign Transaction'),\n        content: SizedBox(\n          width: 300,\n          height: 350,\n          child: Text(parsedResponse.toString()),\n        ),\n        actions: [\n          ElevatedButton(\n            onPressed: () =\u003e Navigator.pop(context, true),\n            child: Text('Accept'),\n          ),\n          ElevatedButton(\n            onPressed: () =\u003e Navigator.pop(context, false),\n            child: Text('Reject'),\n          ),\n        ],\n      );\n    },\n  );\n\n  // 3. Respond to the dApp based on user response\n  if (userApproved) {\n    // Returned value must be a primitive, or a JSON serializable object: Map, List, etc.\n    return 'Signed!';\n  }\n  else {\n    // Throw an error if the user rejects the request\n    throw Errors.getSdkError(Errors.USER_REJECTED_SIGN);\n  }\n}\n\nwcClient.registerRequestHandler(\n  chainId: 'eip155:1',\n  method: 'eth_sendTransaction',\n  handler: signRequestHandler,\n);\n\n// If you want to the library to handle Namespace validation automatically, \n// you can register your events and accounts like so:\nwcClient.registerEventEmitter(\n  chainId: 'eip155:1',\n  event: 'chainChanged',\n);\nwcClient.registerAccount(\n  chainId: 'eip155:1',\n  account: '0xabc',\n);\n\n// If your wallet receives a session proposal that it can't make the proper Namespaces for,\n// it will broadcast an onSessionProposalError\nwcClient.onSessionProposalError.subscribe((SessionProposalError? args) {\n  // Handle the error\n});\n\n/* [DEPRECATED] */\n// Setup the auth handling\nclientB.onAuthRequest.subscribe((AuthRequest? args) async {\n\n  // This is where you would \n  // 1. Store the information to be signed\n  // 2. Display to the user that an auth request has been received\n\n  // You can create the message to be signed in this manner\n  String message = clientB.formatAuthMessage(\n    iss: TEST_ISSUER_EIP191,\n    cacaoPayload: CacaoRequestPayload.fromPayloadParams(\n      args!.payloadParams,\n    ),\n  );\n});\n\n// For auth, you can do the same thing: Present the UI to them, and have them approve the signature.\n// Then respond with that signature. In this example I use EthSigUtil, but you can use any library that can perform\n// a personal eth sign.\nString sig = EthSigUtil.signPersonalMessage(\n  message: Uint8List.fromList(message.codeUnits),\n  privateKey: 'PRIVATE_KEY',\n);\nawait wcClient.respondAuthRequest(\n  id: args.id,\n  iss: 'did:pkh:eip155:1:ETH_ADDRESS',\n  signature: CacaoSignature(t: CacaoSignature.EIP191, s: sig),\n);\n// Or rejected\n// Error codes and reasons can be found here: https://docs.walletconnect.com/2.0/specs/clients/sign/error-codes\nawait wcClient.respondAuthRequest(\n  id: args.id,\n  iss: 'did:pkh:eip155:1:ETH_ADDRESS',\n  error: Errors.getSdkError(Errors.USER_REJECTED_AUTH),\n);\n//\n\n// You can also emit events for the dApp\nawait wcClient.emitSessionEvent(\n  topic: sessionTopic,\n  chainId: 'eip155:1',\n  event: SessionEventParams(\n    name: 'chainChanged',\n    data: 'a message!',\n  ),\n);\n\n// Finally, you can disconnect\nawait wcClient.disconnectSession(\n  topic: pairing.topic,\n  reason: Errors.getSdkError(Errors.USER_DISCONNECTED),\n);\n```\n\n### Reconnecting the WebSocket\n\n```dart\n// If your WebSocket dies, you can reconnect it the with the following method\nwcClient.core.relayClient.connect();\n```\n\n### Responding to Data Changes (Event Handling)\n\nThe dart library has all of the events listed in the [specification](https://docs.walletconnect.com/2.0/specs/clients/sign/session-events).\n\nHowever, instead of using strings to identify the events, each event has it's own dedicated object like so:\n\n```dart\nwcClient.onSessionEvent.subscribe((SessionEvent? session) {\n  // Do something with the event\n});\n```\n\n# Platform Permissions\n\n## MacOS\n\nThis library requires that you add the following to your `DebugProfile.entitlements` and `Release.entitlements` files so that it can connect to the WebSocket server.\n\n```xml\n\u003ckey\u003ecom.apple.security.network.client\u003c/key\u003e\n\u003ctrue/\u003e\n```\n\n# To Test\n\nRun tests using `flutter test --dart-define=PROJECT_ID=xxx`.\nExpected flutter version is: \u003e`3.0.0`\n\nTo output logs while testing, you can set the `core.logger.level = Level.info` to see only warnings and errors, or `Level.info` to see all logs.\n\n# Commands Run in CI\n\n* `flutter analyze`\n* `dart format --output=none --set-exit-if-changed .`\n\n# Useful Commands\n\n* `flutter pub run build_runner build --delete-conflicting-outputs` - Regenerates JSON Generators\n* `flutter doctor -v` - get paths of everything installed.\n* `flutter pub get`\n* `flutter upgrade`\n* `flutter clean`\n* `flutter pub cache clean`\n* `flutter pub deps`\n* `flutter pub run dependency_validator` - show unused dependencies and more\n* `dart format lib/* -l 120`\n* `flutter analyze`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwalletconnect%2Fwalletconnectflutterv2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwalletconnect%2Fwalletconnectflutterv2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwalletconnect%2Fwalletconnectflutterv2/lists"}