@kabila-tech/hedera-wallet-connect
TypeScript icon, indicating that this package has built-in type declarations

1.0.7 • Public • Published

Overview

This library extends the official hedera-wallet-connect repository with additional features. All new features are pull requests created in the official repo that have not yet been approved. You can view them here:


A few useful resources include:

WalletConnect brings the ecosystem together by enabling wallets and apps to securely connect and interact.

-- https://walletconnect.com

Hedera aims to be:

The open source public ledger for everyone

-- https://hedera.com


This package managed by the Hedera community and is intended to be a standard for ecosystem wallets and dApp providers utilizing WalletConnect as a their communications protocol. It utilizes the @hashgraph/sdk and provides functions to facilitate implementing the WalletConnect <> Hedera JSON-RPC spec which has been defined through the collaborative HIP process in HIP-820.

This library facilitates the implementation of the WalletConnect <> Hedera Spec which allows wallets and dApps to natively integrate with Hedera. It provides additional, out of network functionality with the hedera_signMessage function.

In short, it uses the Hedera javascript SDK to build transactions, serialize them, send to wallets for processing and return responses back to dApps.

Please note, this is distinct from the Implementation of Ethereum JSON-RPC APIs for Hedera. At the time of this writing, "the Hedera JSON-RPC relay implementation is in beta, offers limited functionality today, and is only available to developers."

The relay and this library have different intentions and serve different purposes - namely native Hedera integration vs. Ethereum compatability layers to ease developer onboarding for those more familiar with the Ethereum ecosystem.

Set up

To start using WalletConnect, sign up for an account at https://cloud.walletconnect.com. You will use your project id when initializing client libraries.

It is important to understand core WalletConnect concepts when integrating this library. Please reference the WalletConnect documentation.

Usage

Upon successfully configuring your dApp and/or wallet to manage WalletConnect sessions, you can use this library’s functions to easily create and handle requests for the Hedera network.

Wallet

This library provides a Wallet class that extends the Web3Wallet class provided by WalletConnect class

Event Listeners

WalletConnect emits various events during a session. Listen to these events to synchronize the state of your application:

// Handle pairing proposals
signClient.on('session_proposal', (event) => {
  // Display session proposal to the user and decide to approve or reject
})

// Handle session requests, like signing transactions or messages
signClient.on('session_request', (event) => {
  // Process the session request
})

// Handle session deletions
signClient.on('session_delete', (event) => {
  // React to session termination
})

Pairing with dApps

Pairing establishes a connection between the wallet and a dApp. Once paired, the dApp can send session requests to the wallet.

a. Pairing via URI

If a dApp shares a URI for pairing:

await signClient.core.pairing.pair({ uri: 'RECEIVED_URI' })

Upon successful pairing, the session_proposal event will be triggered.

b. Pairing via QR Codes

For a better user experience, dApps often share QR codes that wallets can scan to establish a pairing. Use a QR code scanning library to scan and obtain the URI, then proceed with pairing:

const scannedUri = '...' // URI obtained from scanning the QR code
await signClient.core.pairing.pair({ uri: scannedUri })

Handling Session Proposals

Upon receiving a session_proposal event, display the proposal details to the user. Allow them to approve or reject the session:

Handling Session Requests

Upon receiving a session_request event, process the request. For instance, if the dApp requests a transaction to be signed:

DApp

This library provides a simple interface to connect to a wallet and send requests using the DAppConnector class, which wraps the WalletConnect signClient and WalletConnectModal.

Initialization

import {
  DAppConnector,
  HederaSessionEvent,
  HederaChainId,
} from '@hashgraph/walletconnect-hedera'
import { LedgerId } from '@hashgraph/sdk'

const dAppMetadata = {
  name: '<Your dapp name>',
  description: '<Your dapp description>',
  url: '<Dapp url>',
  icons: ['<Image url>'],
}

const extensionIds = ['<Extension ID>']

const dAppConnector = new DAppConnector(
  dAppMetadata,
  LedgerId.TESTNET,
  projectId,
  Object.values(HederaJsonRpcMethod),
  [HederaSessionEvent.ChainChanged, HederaSessionEvent.AccountsChanged],
  [HederaChainId.Testnet],
  extensionIds,
)
await dAppConnector.init()

Pairing with Wallets

Establish a connection between a dApp and a wallet by pairing them. Multiple accounts can be paired simultaneously.

const session = await dAppConnector.openModal()

Sending Requests

Once paired, the dApp can send requests to the wallet. For instance, if the dApp wants to request a transaction to be signed:

const transaction = new TransferTransaction()
      .addHbarTransfer(0.0.12345, -1)
      .addHbarTransfer(receiver, 1)

const accountId = AccountId.fromString('0.0.12345')
const transactionSigned = await dAppConnector.signTransaction(
  accountId
  transaction,
)
1 - hedera_getNodeAddresses
const nodeAddresses = await dAppConnector.getNodeAddresses()
2- hedera_ExecuteTransaction
const transactionSigned = await dAppConnector.executeTransaction(
  accountId
  transaction,
)
3- hedera_signMessage
const response = await dAppConnector.signMessage(accountId, message)
4- handleExecuteQuery
const response = await dAppConnector.executeQuery(accountId, query)
5- hedera_signAndExecuteTransaction
const response = await dAppConnector.signAndExecuteTransaction(
  accountId
  transaction,
)
6- hedera_signTransaction
const transaction = await dAppConnector.signTransaction(
  accountId
  transaction,
)

Get a Signer

Use the accountId of a paired account to retrieve a signer and simplify interactions with the Wallet and multiple accounts.

const signer = dAppConnector.getSigner(AccountId.fromString('0.0.12345'))
const response = await signer.signAndExecuteTransaction(transaction)

Events

The events exposed by the DAppConnector can be accessed through the walletConnectClient prop. To learn more about these events, please refer to WalletConnect Session Events.

  dAppConnector.walletConnectClient.on('session_event', (event) => {
    // Handle session events, such as "chainChanged", "accountsChanged", etc.
    console.log(event)
  })

  dAppConnector.walletConnectClient.on('session_request_sent', (event) => {
    // Handle session events, such as "chainChanged", "accountsChanged", etc.
    console.log('session_request_sent: ', event)
  })

  dAppConnector.walletConnectClient.on('session_update', ({ topic, params }) => {
    // Handle session update
    const { namespaces } = params
    const _session = dAppConnector.walletConnectClient!.session.get(topic)
    // Overwrite the `namespaces` of the existing session with the incoming one.
    const updatedSession = { ..._session, namespaces }
    // Integrate the updated session state into your dapp state.
    console.log(updatedSession)
  })

Disconnecting

Disconnect single session
dAppConnector.disconnectSession(session.topic)
Disconnect all sessions
dAppConnector.disconnectAllSessions()

Extension popup

By default, it is not possible to directly pop up an extension with Wallet Connect. However, to allow this possibility, the dAppConnector accepts a list of extension IDs. If you create the AppConnector with an extension ID, it will automatically send a message to the extension to detect if it is installed. In case the extension is installed, it will be added to the available extensions and its data can be found at the extensions property of dAppConnector.

To connect an available extension, use the method connectExtension(<extensionId>). This will link the extension to the signer and session. Whenever you use the signer created for this session, the extension will automatically open. You can find out if the extension is available by checking the extensions property.

const dAppConnector = new DAppConnector(
  dAppMetadata,
  LedgerId.TESTNET,
  projectId,
  Object.values(HederaJsonRpcMethod),
  [HederaSessionEvent.ChainChanged, HederaSessionEvent.AccountsChanged],
  [HederaChainId.Testnet],
  ['<Extension ID 1>, <Extension ID 2>'],
)

[...]

dAppConnector?.extensions?.forEach((extension) => {
  console.log(extension)
})

const extension = dAppConnector?.extensions?.find((extension) => extension.name === '<Extension name>')
if (extension.available) {
  await dAppConnector!.connectExtension(extension.id);
  const signer = dAppConnector.getSigner(AccountId.fromString('0.0.12345'))

  // This request will open the extension
  const response = await signer.signAndExecuteTransaction(transaction)
}

Wallets that are compatible should be able to receive and respond to the following messages:

  • "hedera-extension-query-<extesnionId>": The extension is required to respond with "hedera-extension-response" and provide the next set of data in the metadata property.
    let metadata = {
      id: '<extesnionId>',
      name: '<Wallet name>',
      url: '<Wallet url>',
      icon: '<Wallet con>',
      description: '<Wallet url>',
    }
  • "hedera-extension-open-<extensionId>": The extension needs to listen to this message and automatically open.
  • "hedera-extension-connect-<extensionId>": The extension must listen to this message and utilize the pairingString property in order to establish a connection.

This communication protocol between the wallet and web dApps requires an intermediate script to use the Chrome API. Refer to the Chrome Extensions documentation

To enable communication between the extension and a web dApp embedded in an iframe, the wallet must support the following messages:

  • "hedera-iframe-query":The extension is required to respond with "hedera-iframe-response" and provide the next set of data in the metadata property.
    let metadata = {
      id: '<extesnionId>',
      name: '<Wallet name>',
      url: '<Wallet url>',
      icon: '<Wallet con>',
      description: '<Wallet url>',
    }
  • "hedera-iframe-connect": The extension must listen to this message and utilize the pairingString property in order to establish a connection.

The dAppConnector is designed to automatically initiate pairing without any need for user action, in case no sessions are noticed and an iframe extension is detected. To capture this event and the newly established session, you can utilize the onSessionIframeCreated function.

Demo & docs

This repository includes a vanilla html/css/javascript implementation with a dApp and wallet example useful for testing and development while integrating WalletConnect and Hedera.

The docs site utilizes Typedoc to generate a library documentation site at https://wc.hgraph.app/docs/

The demo source code lives in ./src/examples/typescript and is available at https://wc.hgraph.app

Passing tests

  • git commit -Ss "the commit message"

Package Sidebar

Install

npm i @kabila-tech/hedera-wallet-connect

Weekly Downloads

32

Version

1.0.7

License

Apache-2.0

Unpacked Size

14 MB

Total Files

61

Last publish

Collaborators

  • adrian_marin
  • franfernandez