diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/rfc/0046-walletconnect-namespaces/0047-walletconnect-namespaces.md b/rfc/0046-walletconnect-namespaces/0047-walletconnect-namespaces.md new file mode 100644 index 0000000..3dbaf19 --- /dev/null +++ b/rfc/0046-walletconnect-namespaces/0047-walletconnect-namespaces.md @@ -0,0 +1,248 @@ +--- +Number: "0047" +Category: Standards Track +Status: Proposal +Author: fefe@magickbase.com +Created: 2022-08-08 +--- + +# WalletConnect Namespaces Protocol + +## Abstract + +This RFC describes a namespaces protocol which is a standardized object defined by the [Chain Agnostic Improvement Proposal (CAIP)](https://github.com/ChainAgnostic/CAIPs) that ensures a common industry standard for chain agnostic purposes. + +## Motivation + +WalletConnect is an open-source protocol that enables secure and seamless communication between decentralized applications (dApps) and wallets on various blockchains. By establishing a remote connection using end-to-end encryption, WalletConnect allows users to interact with dApps through their preferred wallet without exposing their private keys. + +Users will encounter two namespaces: the proposal namespace and the session namespace when connecting wallets and dApps. Upon approval, the wallet will then send a session namespace that includes all the accounts, chains, methods, and events it has approved. + +## Specification + +Here is an example of a session approval message passing the namespace. + +``` +{ + ... + "namespaces": { + "ckb": { + "chains": [ "ckb:mainnet", ... ], + "accounts": [ "ckb:mainnet:${account_id}" ], + "methods": [ "ckb_signTransaction", ... ], + "events": [ "accountChanged", ... ], + } + }, + "sessionProperties": { + "scriptBases": ",", + }, + ... +} +``` + +### chains + +A general blockchain identification schema has been defined in [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md). Its implementation for the CKB blockchain is as stated below + +| Component | Description | +| ------------------- | --------------------------------- | +| caip2-like chain_id | namespace + : + chain_reference | +| namespace | ckb | +| chain_reference | One of (mainnet, testnet, devnet) | + +### accounts + +> CAIP-10 defines a way to identify an account in any blockchain specified by CAIP-2 blockchain id. + +For context, see the [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) specification. + +| Component | Description | +| ---------------------- | ------------------------------------------------ | +| caip10-like account_id | namespace + : + chain_reference + : + identity | +| namespace | ckb | +| chain_id | One of (mainnet, testnet, devnet) | +| identity | The hash obtained by the first pk of the account | + +### methods + +#### ckb_getAddresses + +Get the Address[^1] list by specific lock script base[^2], in the format of `:`. + +- Parameters + +```ts +{ + [] :{ + page: { + size: number // the size of address list to return + before: string // used as the end point of the returned address list(excluded) + after: string // used as the start point of the returned address(excluded) + }, + type: 'generate' | 'all' // set 'generate' to generate new addresses if necessary; set 'all' to get existent addresses + } +} +``` + +- Returns + +```ts +{ + '' : Address[], + '' : Address[], +} +``` + +#### ckb_signTransaction + +Get a Transaction[^3] over the provided instructions. + +- Parameters + +```ts +{ + transaction: Transaction + actionType: 'sign' | 'signAndSend' + description: string +} +``` + +- Returns + +```ts +{ + transaction?: SignedTransaction + hash?: string +} +``` + +#### ckb_signMessage + +Get a signature for the provided message from the specified signer address. + +- Parameters + +```ts +{ + message: string, // the message to sign + address: string // address of which private to sign +} +``` + +- Returns + +```ts +{ + signature: string +} +``` + +### events + +#### accountChanged + +Emit the event when the account changed + +```ts +{ + name: "accountChanged", + data: string +} +``` + +#### addressesChanged + +Emit the event when addresses changed + +```ts +{ + name: "addressesChanged", + data: { + addresses: Address[], + changeType: 'add' | 'consume' // add: new addresses created; consume: addresses consumed + } +} +``` + +### compound types + +#### Address + +```ts +interface Address { + address: string + identifier: string + description: string + balance: string + index: number +} +``` + +#### Transaction + +```ts +interface Transaction { + cellDeps: { + outPoint: { + txHash: string; + index: string; + }; + depType: string; + }[]; + headerDeps: string[]; + inputs: { + previousOutput: { + txHash: string; + index: string; + }; + since: string; + capacity: string; + lock: { + args: string; + codeHash: string; + hashType: 'type' | 'data'; + }; + lockHash: string; + }[]; + outputs: { + capacity: string; + lock: { + args: string; + codeHash: string; + hashType: 'type' | 'data'; + }; + type: { + args: string; + codeHash: string; + hashType: 'type' | 'data'; + }; + }[]; + outputsData: string[]; + description: string; + [key: string]: any; +} +``` + +#### SignedTransaction + +```ts +interface interface SignedTransaction { + transaction: Transaction; + signatures: { + [hash: string]: string[]; + }; + description: string; + [key: string]: any; +} +``` + +## Further reading + +1. [Reference-level explanation](./Reference-level-explanation.md) +2. Namespaces https://docs.walletconnect.com/2.0/specs/clients/sign/namespaces + +## Refs + +[^1]: Address: a compound type of CKB address, defined as [Address](#address); +[^2]: Script Base: It's the combination of `code_hash` and `hash_type` of a specific `script` in the format `:`. Without a concrete `args` of the `script`, the `script base` refers to the set of an abstract script. The relation between `script base` and `script` can be considered as `class` and `instance`; +[^3]: Transaction: a compound type of CKB transaction, defined as [Transaction](#transaction). diff --git a/rfc/0046-walletconnect-namespaces/Reference-level-explanation.md b/rfc/0046-walletconnect-namespaces/Reference-level-explanation.md new file mode 100644 index 0000000..d7168a7 --- /dev/null +++ b/rfc/0046-walletconnect-namespaces/Reference-level-explanation.md @@ -0,0 +1,272 @@ +# Reference-level explanation + +Here is a flowchart illustrating this linking process: + +```mermaid +graph TB + dAppGenerateQR[dApp: Generate QR Code] -- URI --> walletScanQR[Wallet: Scan QR Code] + walletScanQR -- Extract symKey, topic, relay info --> walletConnect[Wallet: Connect to Relay Server] + walletConnect -- Subscribe to topic --> walletSubscribed[Wallet: Subscribed to Topic] + dAppConnect[dApp: Connect to Relay Server] --> dAppSubscribed[dApp: Subscribed to Topic] + dAppSubscribed -- Send encrypted session_proposal --> walletSubscribed + walletSubscribed -- Receive session_proposal --> walletReview[Wallet: Approve or Reject] + walletReview -- Send encrypted approve_session --> dAppReceiveApprove[dApp: Receive approve_session] + dAppReceiveApprove --> dAppSecureCommunication[dApp: Establish secure communication] + walletReview --> walletSecureCommunication[Wallet: Establish secure communication] +``` + + +https://github.com/Magickbase/neuron-public-issues/assets/11756869/50deb328-171a-4237-985d-daa85238b9d2 + + + +## Initialization + +This `PROJECT_ID` will be described in-depth in the External Tasks section of this document + +### dapp + +```javascript + import { Web3Modal } from "@web3modal/standalone"; + import { SignClient } from "@walletconnect/sign-client"; + + SignClient.init({ + projectId: PROJECT_ID, + metadata: { + name: "Demo Dapp", + description: "Demo Dapp for WalletConnect", + url: location.href, + icons: [], + }, + }); +``` + +### wallet + +First, we need to instanciate `@walletconnect/core`, passing a `PROJECT_ID` that is registered on https://walletconnect.com + +Using the `core` instance, we can init the `@walletconnect/web3wallet` instance passing it and some metadata with information about the wallet: + +```javascript +import { Core } from '@walletconnect/core' +import { IWeb3Wallet, Web3Wallet } from '@walletconnect/web3wallet' + +const core = new Core({ + projectId: PROJECT_ID, +}) + +Web3Wallet.init({ + core, + metadata: { + name: 'Neuron', + url: 'https://github.com/nervosnetwork/neuron', + icons: [], + description: '', + }, +}) +``` + +## Pairing + +On both wallets, we need to enable the user to scan a QRCode containing the connection URI and also allow him to manage his connected sections + +### dApp + +```javascript +const { uri, approval } = await signClient.connect({ + requiredNamespaces: { + ckb: { + chains: ["ckb:testnet"], + methods: ["ckb_getAddresses","ckb_signMessage","ckb_signTransaction"], + events: ["accountChanged","addressesChanged"], + }, + }, + sessionProperties: { + scriptBases: ",", + }, +}); +await web3Modal.openModal({ uri }); +const session = await approval(); + +``` + +### wallet + +```javascript +await web3Wallet.core.pairing.pair({ uri: walletConnectUri }) +``` + + +## Handling session proposals + +A `session_proposal` event is received by the wallet just as soon as the connection is established with the relay server, so we need to handle it by displaying the proposal request to the user with a popup to accept or reject it. + +### proposal (wallet received) + +```javascript +{ + "id": 1690302681590244, + "params": { + "id": 1690302681590244, + "pairingTopic": "78eba166ce5385e54afe5e58df9394c16d731c3496140bc9371b1ce7ad274919", + "expiry": 1690302988, + "requiredNamespaces": { + "ckb": { + "chains": [ + "ckb:testnet", + ], + "methods": [ + "ckb_getAddresses", + "ckb_signMessage", + "ckb_signTransaction" + ], + "events": [ + "accountChanged", + "addressesChanged" + ] + } + }, + "optionalNamespaces": {}, + "relays": [ + { + "protocol": "irn" + } + ], + "proposer": { + "publicKey": "930fb9ac962835844bd6bc22afae8fe19ea4673e56e1179474477ced7291b650", + "metadata": { + "name": "Demo Dapp", + "description": "Demo Dapp for WalletConnect", + "url": "http://localhost:3100/", + "icons": [] + } + }, + "sessionProperties": { + "scriptBases": "," + } + }, + "verifyContext": { + "verified": { + "verifyUrl": "", + "validation": "UNKNOWN", + "origin": "http://localhost:3100/" + } + } +} + +``` + +### session (dApp received) + +```javascript +{ + "topic": "04478855bfbec1470ce6a1da7be45547c097c3be0c303a17e883962a16e9c760", + "relay": { + "protocol": "irn" + }, + "expiry": 1690907597, + "namespaces": { + "ckb": { + "accounts": [ + "ckb:testnet:ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqwh8z6fkne05j0emqeen59qnn8a6xkm3fs0xf9en" + ], + "methods": [ + "ckb_getAddresses", + "ckb_signMessage", + "ckb_signTransaction" + ], + "events": [ + "accountChanged", + "addressesChanged" + ] + } + }, + "acknowledged": true, + "pairingTopic": "ac5727dca7a8ab7fef8afd5d6688afc833dce5513f00316cf62c27fa0e4976f4", + "requiredNamespaces": { + "ckb": { + "chains": [ + "ckb:testnet" + ], + "methods": [ + "ckb_getAddresses", + "ckb_signMessage", + "ckb_signTransaction" + ], + "events": [ + "accountChanged", + "addressesChanged" + ] + } + }, + "optionalNamespaces": {}, + "controller": "6743f243e8e1e7e08d041b1342fb4a936c9b4f904930948b4c1c35e83686461a", + "self": { + "publicKey": "d664efb0c3829b7aace810d73effb2d1d9b6c83d896123b169359f6d50f2d173", + "metadata": { + "name": "Demo Dapp", + "description": "Demo Dapp for WalletConnect", + "url": "http://localhost:3100/", + "icons": [] + } + }, + "peer": { + "publicKey": "6743f243e8e1e7e08d041b1342fb4a936c9b4f904930948b4c1c35e83686461a", + "metadata": { + "name": "Neuron", + "url": "https://github.com/nervosnetwork/neuron", + "icons": [], + "description": "" + } + } +} + +``` + +## Handling session requests + +After the session is established, we will receive RPC requests through the `session_request` event, here is an example request(ckb_signMessage): + +### session request(wallet received) + +```javascript +{ + "id": 1690303076942789, + "topic": "4037816dd9a6ddadae1336cf3f13bde5e327b84f58c17ee14a74d97497d095b8", + "params": { + "request": { + "method": "ckb_signMessage", + "params": { + "address": "ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqwh8z6fkne05j0emqeen59qnn8a6xkm3fs0xf9en", + "message": "This is a like message" + } + }, + "chainId": "ckb:testnet" + }, + "verifyContext": { + "verified": { + "verifyUrl": "", + "validation": "UNKNOWN", + "origin": "http://localhost:3100/" + } + } +} +``` + +### result (dApp received) +#### approved +```javascript +{ + "signature": "0xcf1e3196731313a1ca4cee73fb217539d359fe874e01be620e4ceeff4b51a1853f3e241210aaa030e8716fe5aec934f0be3e4c42963cdd2b9719c882b459ed0301" +} + +``` + +#### rejected +```javascript +{ + "code": 5000, + "message": "User rejected." +} + +``` diff --git a/sdk/ckb-walletconnect-sdk.md b/sdk/ckb-walletconnect-sdk.md new file mode 100644 index 0000000..4486af5 --- /dev/null +++ b/sdk/ckb-walletconnect-sdk.md @@ -0,0 +1,211 @@ +# Introduction +This article will present the usage of `CKB's WalletConnect SDK`, an auxiliary library built on top of WalletConnect which wraps the protocol for integration within the CKB ecosystem. + +## Why do I need WalletConnect in my dApp? +Almost every decentralized application needs user's authentication to send a signed transaction to the blockchain. From minting tokens to making a simple transfer, users must always sign their transactions whenever the client-side application needs to call a SmartContract method that requires the user's Account. + +Without a solution like WalletConnect, the user would need to trust their private key to the dApp in order to sign. For obvious reasons, outside of testing environments, this is a huge security issue. The dApp could simply use the key to maliciously steal funds or sign something not approved by the user. + +## Requirements +Create an account on Wallet Connect website and then create a new Project, it's super easy, with just a few fields on the form. After that, you will be able to get your projectId and use it on your application. + +## Installation +Install the dependency on your client-side application + +``` +npm i @nervosnetwork/ckb-walletconnect-sdk @walletconnect/sign-client @web3modal/standalone +``` + +## Setup +Initialize the SDK with the following code: +``` +import CkbWC from '@nervosnetwork/ckb-walletconnect-sdk' +import SignClient from '@walletconnect/sign-client' + +const ckbWC = new CkbWC(await SignClient.init({ + projectId: '', // the ID of your project on Wallet Connect website + metadata: { + name: 'MyApplicationName', // your application name to be displayed on the wallet + description: 'My Application description', // description to be shown on the wallet + url: 'https://myapplicationdescription.app/', // url to be linked on the wallet + icons: ['https://myapplicationdescription.app/myappicon.png'] // icon to be shown on the wallet + } +})) +``` + +## Using the SDK + +### Check if the user has a session +``` +if (ckbWC.isConnected()) { + console.log(ckbWC.getAccount()) + console.log(ckbWC.getChain()) + console.log(ckbWC.session.namespaces); +} +``` + +### Connect to the Wallet + +``` +if (!ckbWC.isConnected()) { + const { uri, approval } = await ckbWC.connect({ + chain: "ckb:testnet", + scriptBases: [] // default: [] represent all types + }) + + await web3Modal.openModal({ uri }); + await approval(); + + console.log(ckbWC.isConnected() ? 'Connected successfully' : 'Connection refused') +} +``` + +### Disconnect +``` +await ckbWC.disconnect(); +``` + +#### Get Addresses + +Get the active address list by specific lock script types + +``` +await ckbWC.getAddresses(params) +``` +- Parameters +``` +{ + [] :{ + page: { + size: number + before: number + after: number + }, + type: 'derived' | 'all' + } +} +``` + +- Returns +``` +{ + '' : Address[], + '' : Address[], +} +``` + +#### Sign Transaction + +Get a transaction over the provided instructions. + +``` +await ckbWC.signTransaction(params) +``` + +- Parameters +``` +{ + data: { + cell_deps: { + out_point: { + tx_hash: string + index: string + } + dep_type: string + }[] + header_deps: string[] + inputs: { + previous_output: { + index: string + tx_hash: string + } + since: string + }[] + outputs: { + capacity: string + lock: { + args: string + code_hash: string + hash_type: 'type' | 'data' + }, + type: { + args: string + code_hash: string + hash_type: 'type' | 'data' + } + }[] + outputs_data: string[] + }, + description: string +} +``` + +- Returns +``` +{ + transaction: Transaction +} +``` + +#### Sign Message + +Get a signature for the provided message from the requested signer address. +``` +const signature = await ckbWC.signMessage(params) +``` +- Parameters +``` +{ + message: string, // the message to sign + address: string // address of which private to sign +} +``` + +- Returns +``` +{ + signature: string +} +``` + +#### Listen Account Changed Event + +``` +ckbWC.onAccountChanged((event) => { + // console.log(event) +}) +``` +- Event +``` +{ + account: string, + addresses: Address[] +} +``` + +#### Listen Addresses Changed Event + +``` +ckbWC.onAddressesChanged((event) => { + // console.log(event) +}) +``` +- Event +``` +{ + ...Address, + changeType: 'add' | 'consume' +}[] +``` + +#### Listen Chain Changed Event + +``` +ckbWC.onChainChanged((event) => { + // console.log(event) +}) +``` +- Event +``` +string // chain +``` diff --git a/sdk/ckb-walletconnect-wallet-sdk.md b/sdk/ckb-walletconnect-wallet-sdk.md new file mode 100644 index 0000000..abdbf7a --- /dev/null +++ b/sdk/ckb-walletconnect-wallet-sdk.md @@ -0,0 +1,136 @@ +# Introduction +This article will present the usage of `CKB's WalletConnect Wallet SDK`, an auxiliary library built on top of WalletConnect which wraps the protocol for integration within the CKB ecosystem. + +## Why do I need WalletConnect in my wallet? + +WalletConnect is an established chain-agnostic open source protocol for connecting decentralized applications to wallets. Whereas there are different options on how to safely implement such connection, WalletConnect is a widely supported standard across different wallets, chains and applications, and it's technical approach is simple, safe and proven. + +WalletConnect provides a more secure and convenient experience for users and reduces the difficulty of wallet integration for dapp developers. More and more dapps and three-way wallet integration libraries are authorising and signing transactions via WalletConnect. + + +## Requirements +Create an account on Wallet Connect website and then create a new Project, it's super easy, with just a few fields on the form. After that, you will be able to get your projectId and use it on your wallet. + +## Getting Started + +### Install + +``` +npm install ckb-walletconnect-wallet-sdk +``` + +### Usage + +- Initialization + +```javascript +import { Core } from "@walletconnect/core"; +import { CkbWallet, getSdkError, CKBWalletAdapter, GetAddressesParams, SignTransactionParams, SignMessageParams } from "ckb-walletconnect-wallet-sdk"; + +class Adapter implements CKBWalletAdapter { + async ckb_getAddresses(params: GetAddressesParams) { + // ... + } + + async ckb_signTransaction(params: SignTransactionParams) { + // ... + } + + async ckb_signMessage(params: SignMessageParams) { + // ... + } +} + +const core = new Core({ + projectId: process.env.PROJECT_ID, +}); + +const walletSDK = await CkbWallet.init({ + core, + metadata: { + name: "MyWalletnName", + description: "My Wallet description", + url: "https://mywalletdescription.com", + icons: ["https://mywalletdescription.com/mywalleticon.png"], + }, + adapter: new Adapter() +}); +``` + +- Connect + +```javascript +await walletSDK.connect(uri); +``` +- Proposals + +```javascript +const proposals = walletSDK.proposals +``` + +- Sessions + +```javascript +const sessions = walletSDK.sessions +``` + +- Session Requests + +```javascript +const requests = walletSDK.requests() +``` + +- Session Approval + +```javascript +const session = await walletSDK.approve({ + id: proposal.id, + chain: 'testnet', + identity: 'xxxxxxxxxx', + scriptBases: ['0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8'] +}); +``` + +- Session Rejection + +```javascript +const session = await walletSDK.reject(proposal.id); +``` + +- Session Disconnect + +```javascript +await walletSDK.disconnect(session.topic); +``` + +- Responding to Session Requests + +```javascript +// Approve +await walletSDK.approveRequest(request); + +// or Reject +await walletSDK.rejectRequest(request); + +``` + +- Emit Session Events + +```javascript +await walletSDK.emitSessionEvent({ + topic, + event: { + name: "accountsChanged", + data: ["xxxxxxxxxx"], + }, + chainId: "ckb:testnet", +}); +``` + +- Handle Events + +```javascript +walletSDK.emitter.on("proposals", handler); +walletSDK.emitter.on("sessions", handler); +walletSDK.emitter.on("requests", handler); +``` diff --git a/ux/wallet-connect-ux/FAQ_en.md b/ux/wallet-connect-ux/FAQ_en.md new file mode 100644 index 0000000..068fa9e --- /dev/null +++ b/ux/wallet-connect-ux/FAQ_en.md @@ -0,0 +1,84 @@ +# FAQ + +### What is Account + +For users, an account is a collection of addresses derived from a set of mnemonics or root private keys according to a specified algorithm. + +Technically, it refers to a set of addresses derived using a specified algorithm. It involves generating a public key (Public Key) by adding a seed with certain rules (hierarchical deterministic wallet), and then combining it with a lock script to create a set of addresses. These addresses are derived based on the combination of the public key and lock script constraints. + +### What is Account ID + +Account ID specifically refers to the hash value of the first root of the user's mnemonic words. Account ID is used to distinguish addresses belonging to a set of mnemonic words/root private keys from addresses that do not belong to them. User interactions with the blockchain do not directly involve the Account or Account ID. + +### What is Lock Hash? + +Lock Hash is the hash value derived from the code hash in the lock script, the hash type in the lock script, and the arguments in the lock script. + +For users, the Lock Hash does not reveal the corresponding business logic. Therefore, when a dapp requests a set of addresses, it typically exposes the code hash in the lock script as a readable field in the Dapp Request Auth. The mapping table between Dapp Request Auth and Lock Hash will be updated on a third-party platform. + +### What is Payment method +A Payment Method is used to identify the label of a transaction type in the CKB transaction. Unlike transactions in some account-based blockchain models, the mentioned payment method is a tag based on the Lock Hash of the Cell transfered by the user. Currently, this tag is resolved off-chain to provide readability for users to understand transaction differences. + +### What is a Description + +In CKB, the Description of a transaction refers to the field that contains arbitrary text within the transaction. It provides descriptive information about the transaction's purpose or other related details. The description field is optional and can be used to provide additional information about the transaction, such as its purpose, notes, or labels. + +### What is Locktime + +In CKB, Locktime refers to the locking timestamp of a transaction. It is a mechanism used to control when a transaction can be confirmed and executed. Each transaction can set a Locktime value, which can be an absolute timestamp or a value relative to the current block height. + +When a transaction is created, it may be assigned a Locktime to specify that the transaction cannot be confirmed and executed until a certain time or block height in the future. This can be used to implement specific transaction logic, such as delayed payment or conditional payments. + +Until the specified Locktime is reached, the transaction is considered unspendable and will not be included in blocks by miners. Once the specified Locktime is reached, the transaction can be confirmed and executed. + +Locktime is optional in CKB, and not all transactions need to set a Locktime. It provides a flexible way to control the execution time of transactions, increasing the functionality and diversity of CKB's applications. + +### Why are there multiple "to" addresses in a transaction? +CKB transactions are based on the UTXO (Unspent Transaction Output) model, where a transaction can have multiple inputs and outputs. + +In a transaction, each output address contains the "Data" and "Witness" fields. + +### About Dapp and Lock Hash Requests +- About Lock Hash: + When a Dapp requests the Lock Hash method without any parameters, the Dapp defaults to requesting all Lock Hashes. When the parameters include a Lock Hash, the Dapp requests the specified Lock Hash. + +- About error responses: + - Panic when the user declines. + - Panic immediately if the wallet does not support the requested DappAuth from the Dapp. + +### Interaction rules between Hot Wallets, Observer Wallets, and Dapps + +> Offline Wallet Case: Considering the current priority of demands, we believe that the case of hot wallets connecting to Dapps is more common. Therefore, the interaction entities in this protocol are "hot wallets" and "Dapps". The case where Dapps directly connect to offline wallets is not considered within the scope of this protocol. If you want to use an offline wallet, it should be used in conjunction with a hot wallet. Therefore, when using an offline wallet, it will be treated as an observe wallet. + +- When a wallet connects to the network and interacts with a Dapp, the interaction process can be found at [this link](https://github.com/Magickbase/neuron-public-issues/issues/148). +- When a wallet is used as an observe wallet, it can establish a connection with a Dapp to retrieve relevant data. + +### Why is the dapp Auth field necessary? + +Limiting Dapp's access to the dapp Auth field helps minimize the exposure of user information. + +Each derived public key is used only once and corresponds to a specific lock type, ensuring that addresses cannot be converted between each other. If the application's business logic only requires the use of A and B type addresses, there is no need to obtain C type addresses. By authorizing the lock type, the exposure of C addresses to the DApp is prevented, reducing the exposure of user information. + +It is also possible that the application supports both A and B type addresses, but the user prefers not to use B type addresses. In this case, the user can edit the authorization to restrict the application to only use A type addresses to complete the business logic. + +### How does dapp Auth field protect the privacy for users? + + +For example, consider an aggregation dapp that displays assets and requires access to all of a user's addresses. However, the user may not want to expose all of their information to this particular dapp. + +In the current design, the dapp auth field is a MUST field, while the wallet's response to the dapp is optional. Therefore, it is necessary to respond, and in the namespace protocol, when a dapp requests authorization, it includes specific values for each requested field (such as supported methods, event listeners, lock types). The wallet will respond with supported values for the corresponding fields (methods, event notifications, lock types) based on its implementation, and the lock types will depend on user authorization. + +For instance, when the dapp requests authorization with lockTypes [secp256k1, acp], the wallet's UX will display [x] secp256k1, [x] acp, [ ] omnilock. Based on the wallet's personalized design, if the user cancels the selection of acp and agrees, the wallet will return lockTypes: [secp256k1]. The wallet will remind the user of the supported/unsupported functionalities based on the user's authorization information. + +When requesting authorization, the dapp should first call ckb_getSupportedLockTypes to obtain the supported lock types range. If the wallet's returned lock range does not support the business logic of the dapp, the dapp should not request authorization. Instead, it should prompt the user with the reason. The dapp should have a clear understanding of its own requirements and communicate them to the wallet. + +### Why dapp Auth field is MUST rather than SHOULD + +If the dapp does not specify the lock range, there will be a confusing flow when the dapp's process design is not well thought out: + +1. The dapp blindly requests addresses for all lock types. +2. The wallet returns addresses for all types. +3. The dapp realizes that it doesn't need all the addresses. +4. The user becomes confused, authorizes the request, but cannot perform any further operations. + +To avoid this flow, it is recommended to require the dapp to specify the lock range when requesting authorization. This can be achieved by providing a method in the SDK to fetch all addresses. When the dapp calls the SDK, it will explicitly understand the purpose of this method and have better control over the address retrieval process. diff --git a/ux/wallet-connect-ux/pic/CheckDetails.png b/ux/wallet-connect-ux/pic/CheckDetails.png new file mode 100644 index 0000000..9307c6b Binary files /dev/null and b/ux/wallet-connect-ux/pic/CheckDetails.png differ diff --git a/ux/wallet-connect-ux/pic/CheckTransactionDetail.png b/ux/wallet-connect-ux/pic/CheckTransactionDetail.png new file mode 100644 index 0000000..502a99e Binary files /dev/null and b/ux/wallet-connect-ux/pic/CheckTransactionDetail.png differ diff --git a/ux/wallet-connect-ux/pic/ConnectFlow.png b/ux/wallet-connect-ux/pic/ConnectFlow.png new file mode 100644 index 0000000..0e47b3a Binary files /dev/null and b/ux/wallet-connect-ux/pic/ConnectFlow.png differ diff --git a/ux/wallet-connect-ux/pic/ConnectRequest.png b/ux/wallet-connect-ux/pic/ConnectRequest.png new file mode 100644 index 0000000..df6e885 Binary files /dev/null and b/ux/wallet-connect-ux/pic/ConnectRequest.png differ diff --git a/ux/wallet-connect-ux/pic/Connecting.png b/ux/wallet-connect-ux/pic/Connecting.png new file mode 100644 index 0000000..2e69a03 Binary files /dev/null and b/ux/wallet-connect-ux/pic/Connecting.png differ diff --git a/ux/wallet-connect-ux/pic/ConnecttingInformation.png b/ux/wallet-connect-ux/pic/ConnecttingInformation.png new file mode 100644 index 0000000..8abdd9a Binary files /dev/null and b/ux/wallet-connect-ux/pic/ConnecttingInformation.png differ diff --git a/ux/wallet-connect-ux/pic/Entry1.png b/ux/wallet-connect-ux/pic/Entry1.png new file mode 100644 index 0000000..4fbcde3 Binary files /dev/null and b/ux/wallet-connect-ux/pic/Entry1.png differ diff --git a/ux/wallet-connect-ux/pic/OfflineWallet.png b/ux/wallet-connect-ux/pic/OfflineWallet.png new file mode 100644 index 0000000..8a1fd68 Binary files /dev/null and b/ux/wallet-connect-ux/pic/OfflineWallet.png differ diff --git a/ux/wallet-connect-ux/pic/Overview.png b/ux/wallet-connect-ux/pic/Overview.png new file mode 100644 index 0000000..7a16a4a Binary files /dev/null and b/ux/wallet-connect-ux/pic/Overview.png differ diff --git a/ux/wallet-connect-ux/pic/SigningaMessage.png b/ux/wallet-connect-ux/pic/SigningaMessage.png new file mode 100644 index 0000000..fd22471 Binary files /dev/null and b/ux/wallet-connect-ux/pic/SigningaMessage.png differ diff --git a/ux/wallet-connect-ux/pic/Unconnected.png b/ux/wallet-connect-ux/pic/Unconnected.png new file mode 100644 index 0000000..a67703a Binary files /dev/null and b/ux/wallet-connect-ux/pic/Unconnected.png differ diff --git a/ux/wallet-connect-ux/pic/confirm-reject.png b/ux/wallet-connect-ux/pic/confirm-reject.png new file mode 100644 index 0000000..16d51fb Binary files /dev/null and b/ux/wallet-connect-ux/pic/confirm-reject.png differ diff --git a/ux/wallet-connect-ux/pic/modifyInfo.png b/ux/wallet-connect-ux/pic/modifyInfo.png new file mode 100644 index 0000000..9ea6e05 Binary files /dev/null and b/ux/wallet-connect-ux/pic/modifyInfo.png differ diff --git a/ux/wallet-connect-ux/ux-protocol.md b/ux/wallet-connect-ux/ux-protocol.md new file mode 100644 index 0000000..93c9c94 --- /dev/null +++ b/ux/wallet-connect-ux/ux-protocol.md @@ -0,0 +1,181 @@ +--- +Number: "0000" +Category: Informational | Standards +Status: Draft (for Informational) | Proposal (for Standards) +Author: Your Name +Created: YYYY-MM-DD +--- + +## 1 Background +WalletConnect is the decentralized Web3 messaging layer and a standard to connect blockchain wallets to dapps. It is chain agnostic and built to work with any blockchain of user's choice. Currently, many blockchains have already implemented convenient communication using WalletConnect. However, for some specific type of blockchain protocols like Bitcoin with UTXO model, CKB with Cell model, and so on, the current interaction methods are **NOT** well-suited. While using these chains, users are able to send **different kinds of tokens** with **multiple addresses** in a **single** transaction. + +Take CKB network for example, some wallets like Neuron supports signing/sending transaction directly. But it can't communicate with dapp to initiate signatures and transactions. + +So we proposed a way to integrate WalletConnect to achieve collaboration with dapp quickly. + + + + + +## 2 Abstract +This article introduces **a user interaction specification** for the WalletConnect protocol based on CKB. The main focus of the article is to present a universal component that can be integrated into various wallet projects. If you're a developer or a product manager of a crypto wallet, this may help you understand what it looks like. + +The article will demonstrate how the WalletConnect connection, for a multi-address model or so-called Account Model which means users could simultaneously using multiply addresses within one series of mnemonics, should be reflected in the user interaction layer, covering the main processes, states, fields, and more related to the universal component. Reading this article will help you develop an roughly understanding of how a user could connect his ckb "account" to a dapp by WalletConnect , what the fields should be contained and what it looks, should you wish to enable this feature in your wallet. + +To avoid some misunderstanding on UI side, the prototype is designed without any specific context, and we also introduce all the related fields fist before the prototype, it's recommended to take the Corresponding functions and Labels in to consideration while designing your own UI based on this article. The Corresponding functions and Labels could also help when you find some numbers or feilds on the prototype, you can go back to check what the fields means. + + + + +## 3 Overview of WalletConnect UX protocol + +Wallet Application usually provide some entries and a popup window for showing the wallet information for the users. +The entries could keep using the same original one, like a scan icon adopted in many current crypto wallets. + +![pic 3](pic/Entry1.png) + +After clicking this icon, and scan the walletconnect QR Code on users' trusted website, the user will be prompted to see the connection information + +For our walletconnect general component, we intergrated the entry and the connection information. Below is the overview of what it looks like. You can quick scan all the fields to be displayed for users roughly. +![pic 1](pic/Overview.png) + +## 4 UX Protocol Description + +### 4.1 Connecting flowchart + + +> Still scanning QR code is the most used and also recommended for users to connect to dapp with your wallet, connectting by pasting the WalletConnect code could be used for testing. + +#### 4.1.1 Corresponding functions and Labels +All the labels and functions which are used to construct the the prototype are listed if you'd like to integrate them into your app in your own way. + +|Flow|Name|Type|Requirement Levels|Note| +| -- | -- | -- | -- | -- | +|Connecting flow|Scan WalletConnect QR code|Function|MUST|--| +| Connecting flow | Connect by WalletConnect-code | Function | SHOULD NOT | Supposed to be only used for testing | +| Connecting flow | link | Label | MUST | The URL of the dapp | +| Connecting flow | Network | Label | MUST | The network of current CKB blockchain | +| Connecting flow | Account | Label | MUST | The account user is using on wallet.Usually, it's the current using series of nmnemonics | +| Connecting flow | Lock Hash | Label | MUST | This means the lock method for user address sets that dapp would like to get access to. [Why this is necessary?](/Neuron-PRDs/WalletConnect/FAQ_en.md)| +| Connecting flow | Disconnect | Function | MUST | -- | + + +![pic 4](pic/ConnectFlow.png) + + + +#### 4.1.2 Status1: Unconnected + +While the dapp is unconnected with the wallet, users can use scan WalletConnect QR code function in order to connect the dapp. This function is just like the single address communication WalletConnect protocol. + +![picture 13](pic/Unconnected.png) + + +#### 4.1.3 Status2: Connecting + +To go on connectting, users are always supposed to click a scan button, and if the QR code is correct then the dapp and wallet are trying to communicate following the protocol. If the QR code is not in correct format, some corresponding error messages will pop up. + +![picture 14](pic/Connecting.png) + + +#### 4.1.4 Status3: Connect Request + +Once the WalletConnection information fecthes back, the wallet shows the connection request information, including the dapp name, its url, network, Account and Auth. + +- The network refers to the CKB network to which the dapp is going to connect. +- The Account refers to the CKB wallet account that the user is going to use. +- The Auth refers to the lock method for user addresses. Typically, a user's addresses can be divided into different adress sets based on the lock method they use, and here various classification methods are provided. dapps can request the specific address sets they need, and users can choose to revoke authorization for certain address sets. It is specified that when the method for requesting Lock Hash from Dapp side has no parameters, the Dapp requests all Lock Hashes. When the Dapp provides specific Lock Hashes, it requests the specified Lock Hashes addresses set. + +To cancel this request, just press the Reject button. + +![ConnectRequest](pic/ConnectRequest.png) + +#### 4.1.5 Status4: Connectting Information + +After the connection is established, the dapp will maintain a persistent connection with the wallet. The relevant connection information, the confirmed information from the previous step, will still be displayed here. Users can disconnect from the dapp at any time. + +![ConnecttingInformation](pic/ConnecttingInformation.png) + +### 4.2 Signing a Message +When a dapp requires the user to perform a signature operation, it can be done through a signature information flow. + +|Flow|Name|Type|Requirement Levels|Note| +| -- | -- | -- | -- | -- | +| Signing a Message | link | Label | MUST | The URL of the dapp | +| Signing a Message | Network | Label | MUST | The network that dapp wants the user to sign on | +| Signing a Message | Message | Label | MUST | The message that dapp wants the user to sign with| + +Based on the Connected state, the dapp will send a signature request to the wallet. Users can choose to sign or not sign the request on the wallet. + +![picture 21](pic/SigningaMessage.png) + +Users should be familiar with, understand, and trust the content of their signature before proceeding. + + +### 4.3 Signing Tx flowchart + +#### 4.3.1 Corresponding functions and Labels +|Flow|Name|Type|Requirement Levels|Note| +| -- | -- | -- | -- | -- | +| Send a transaction | link | Label | MUST | The URL of the dapp | +| Send a transaction | Network | Label | MUST | The network that dapp wants the user to sign on | +| Send a transaction | Payment method | Label | SHOULD | Currently, the CKB transactions are all TRANSFER. | +| Send a transaction | To Address List | Label | MUST | **There could be more than 1 address in this case. So the whole list should also be shown to the user.** | +| Send a transaction | Asset Amounts | Label | MUST | This value represents the total capacity change of connected addresses in this transaction. And if there is any other kind of Cell like SUDT or NFT and so on, a **label** MUST be marked next to the CKB number, like 1,00,300CKB*(including 10SUDT).| +| Send a transaction | Fee or Fee Rate | Label | MUST | -- | +| Send a transaction | Description | Label | MUST | -- | +| Send a transaction | Locktime | Label | OPTIONAL | -- | +| Send a transaction | Recieve Amount for individual address in the to_address list. | Label | MUST | This refers to the amounts that every individual address will receive | +| Send a transaction | Transaction Info Modify | Function | MUST | Users are able to modify or adjust some data in the transaction like Fee Rate | +| Send a transaction | Transaction Data for individual address | Label | MUST | -- | +| Send a transaction | Witness for individual address | Label | MUST | -- | +| Send a transaction | Decode Data for individual address | Function | SHOULD | The individual data could be decoded for easier reading, however, different sources have been given for users/wallet to choose. | +| Send a transaction | Transaction Raw Data | Label | SHOULD | Transaction Input will be displayed for professional users or any advanced usage. Through the transaction raw data, users can understand the inputs and outputs associated with this transaction.| + +When dapp initializes a transaction, this component will pop up/ show, And these fields will show as we proposed. + +#### 4.3.2 To confirm/reject a transaction from dapp + +- Normally, if the user want sign the transaction by simply click the NEXT btn then click CONFIRM btn. +![picture 27](pic/confirm-reject.png) + + +- To reject or cancel this transaction , you can click REJECT Btn +on the first step. + + +#### 4.3.3 To modify the transaction information + +- Click the modify icon +![picture 24](pic/modifyInfo.png) + + +- Then modify information in corresponding text field, and continue. + +#### 4.3.4 Further examine the receiving address and its detailed data + +The following chart shows different cases where the user wants to check the receiving addresses and there are multiple reciever addresses or multiple assets. + +While do your own design, it's recommended that all the reciever addresses and assets related in this transaction should be able to reached and examined by the user. + +- Check more addresses and go to the individual address detail pages. + +![pic 4](pic/CheckDetails.png) + + + + + + +### 4.4 While wallet is offline + +Offline Wallet Case: Considering the current priority of demands, we believe that the case of hot wallets connecting to Dapps is more common. Therefore, the interaction entities in this protocol are "hot wallets" and "Dapps". See more at [FAQ](/ux/wallet-connect-ux/FAQ_en.md). + +While wallet is offline, a pop-up could be triggered to remind user to reconnect or keep offline. + +|Flow|Name|Type|Requirement Levels|Note| +| -- | -- | -- | -- | -- | +| Offline usage | link | Label | MUST | The URL of the dapp | +| Offline usage | Network Name | Label | MUST | The network that dapp wants the user to sign on | + +![picture 30](pic/OfflineWallet.png)