tzip-10.md 10.6 KB
Newer Older
pascuin's avatar
pascuin committed
1
---
Julien Hamilton's avatar
Julien Hamilton committed
2
tzip: 10
pascuin's avatar
pascuin committed
3 4 5
title: Wallet Interaction Standard
author: Alessandro De Carli <[email protected]>, Mike Godenzi <[email protected]>, Andreas Gassmann <[email protected]>, Pascal Brun <@pascuin>
discussions-to: https://forum.tezosagora.org/t/wallet-interaction-standard/1399
Julien Hamilton's avatar
Julien Hamilton committed
6
status: Work In Progress
pascuin's avatar
pascuin committed
7 8 9 10
type: LA
created: 2019-09-17
---

Julien Hamilton's avatar
Julien Hamilton committed
11
## Summary
pascuin's avatar
pascuin committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

Communication between wallets and decentralised applications.

## Abstract

This document describes the communication between an app (decentralised application on Tezos) and wallet (eg. browser extension).

## Motivation

A user wants to be able to interact with decentralised applications e.g. uniswap-like decentralised exchange or a game that uses NFTs, he wants to use his preferred wallet and avoid having to install a new wallet for each application he uses.

To enable adoption of decentralised applications in the Tezos ecosystem a standard for the communication between these apps and wallets is needed. Application developers shouldn't need to implement yet another wallet just for their use case and users shouldn't need a multitude of wallets just to use a certain service.

This standard should form consensus of how the types of messsages for this communication look like.

## Specification

### Communication Protocol Version 1.0.0 (Version code 1)

The entire protocol relies on asynchronous calls. A call consists of a request message and a asynchronous response message.

## Versioning

The transport layer is responsible for the communication of the protocol version. All of the discussed messages will be wrapped with a protocol header including the version code.

## Message Types

The following chapters describe the different message types that exist between the app and wallet. Even though in some programming languages the order of keys in a dictionary/map is arbitrary
for this protocol the order does matter. Also this protocol assumes a secure and authenticated transport layer was established hence no messages can be spoofed.

### 1. Permission

App requests permission to access account details from wallet.

#### Request

```typescript
type PermissionScope =
  | "read_address"
  | "sign"
  | "payment_request"
  | "threshold";

interface PermissionRequest {
  scope: PermissionScope[];
}
```

`appMetadata`: An App should be identifiable by the user, for example with a name and icon.

`scope`: The App should ask for permissions to do certain things, for example for a list of addresses or if the App can request to sign a transaction (maybe even without confirmation for micro-transactions). The following scopes are defined:

- `read_address`: this indcates the app want to be able to read the address.
- `sign`: this indicates the app wants to be able to sign.
- `payment_request`: this indicates the app wants to perform payment requests.
- `threshold`: this indicates the app wants the wallet to show the user a threshold prompt, so that in future transactions below this threshold can be handled automatically by the wallet.

#### Response

```typescript
interface PermissionResponse [
  { address: string; networks: string[]; permissions: PermissionScope[] };
]
```

#### Errors

`NO_ADDRESS_ERROR`: Will be returned if there is no address present for the protocol / network requested.

`NOT_GRANTED_ERROR`: Will be returned if the permissions requested by the App were not granted.

#### Notes

The `threshold` scope is only an optional suggestion for the wallet. Even if the wallet does not support this it will still be compatible with the protocol.

### 2. Sign Payload

App requests that a payload is signed.

#### Request

```typescript
interface SignPayloadRequest {
  payload: byte[];
  sourceAddress: string;
}
```

`payload`: The unsigned, payload.

#### Response

```typescript
interface SignPayloadResponse {
  signature: byte[];
}
```

`signature`: The signature of the payload.

#### Errors

`NOT_GRANTED_ERROR`: Will be returned if the signature was blocked

`NO_PRIVATE_KEY_FOUND_ERROR`: Will be returned if the private key matching the sourceAddress could not be found

### 3. Payment Request

App sends parameters like `recipient` and `amount` to the wallet and the wallet will prepare the transaction and broadcast it.

#### Request

```typescript
interface PaymentRequest {
  network: string;
  recipient: string;
  amount: string;
  source?: string;
}
```

`network`: The network used for the payment request.

`recipient`: The address of the recipient.

`amount`: The amount that will be sent, as a string in mutez (smallest unit).

`source`: The source address. This is optional. If no source is set, the wallet will let the user chose.

#### Response

```typescript
interface PaymentResponse {
  transactionHash: string;
}
```

`transactionHash`: The transaction hash if it has been broadcast to the node (see `PaymentRequest`)

#### Errors

`PARAMETERS_INVALID_ERROR`: Will be returned if any of the parameters are invalid

`BROADCAST_ERROR`: Will be returned if the user choses that the transaction is broadcast but there is an error (eg. node not available)

### 4. Broadcast Transactions

App requests a signed transaction to be broadcast.

#### Request

```typescript
interface BroadcastRequest {
  network: string;
  signedTransaction: byte[];
}
```

`network`: The network used for the payment request.

`signedTransaction`: The signed transaction payload

#### Response

```typescript
interface BroadcastResponse {
  transactionHash: string;
}
```

`transactionHash`: The transaction hash.

#### Errors

`TRANSACTION_INVALID_ERROR`: Will be returned if the transaction is not parsable or is rejected by the node.

`BROADCAST_ERROR`: Will be returned if the user choses that the transaction is broadcast but there is an error (eg. node not available).

## Transport Layer

This standard requires a transport layer that can cover the following use cases:

- Same Device Desktop to Desktop (e.g. Galleon)
- Same Device Desktop to Hardware Wallet (e.g. Ledger)
- Same Device Mobile to Mobile (e.g. Cortez)
- Two Device Desktop to online Mobile (e.g. Wetez)
- Two Device Desktop to offline Mobile (e.g. AirGap)

The transport layer used for app-wallet communication we propose is using a decentralised messaging service. We are proposing to use the [matrix protocol](https://matrix.org/). Other projects in the blockchain
space like [Raiden](https://medium.com/raiden-network/raiden-transport-explained-939d7741b6f4) have been using matrix successfully to cover very similar requirements. The long term vision is that
the Tezos reference node will eventually include such a messaging service by default, replacing the matrix network in the long term.

The main reasons why we propose to use a decentralized messaging service as the transport layer between app and wallet are:

- decentralization
- enables modern user experience
- covers all of the scenarios described above
- easy to integrate with all kind of wallets
- minimal effort to "join" for a wallet
- support for oracles (e.g. push service)

### Serialisation

The serialisation used for the transport layer messages requires an algorithm which is space efficient and fast to encode/decode. These properties rule out the common encoding standards
XML and JSON. After researching various alternatives (BSON, RLP, Protocol buffers and amino) we propose to use the space efficient yet very easy to implement RLP encoding. The main reasons
why we are proposing RLP are:

- simple algorithm, no need to generate/compile code on a per-message basis (like with e.g. protocol buffers)
- very space efficient (only 1-2 bytes of overhead per new structure)
- same object always has same byte output, making it suitable to use with signatures <sup>1</sup>

<sup>1</sup> this is not a hard requirement for this initiative as of now, we can however foresee that it might become relevant in future.

#### 1. Handshake (opening a channel)

Communication between app and wallet requires a secure setup. This is the proposed handshake process:

1. we define the communication/transport layer as 'channel'
2. app generates and stores (e.g. local storage) a channel asymmetric key pair
3. app serialises public key, channel version, app name, app id (url) and app icon (url) in an handshake uri <sup>2</sup>
4. handshake uri is either shown as QR or made openable by app
5. wallet receives handshake uri
6. wallet generates and stores a channel asymmetric key pair
7. wallet serialises public key and channel version in an handshake uri
8. wallet uses P2P network layer to reach out to app and send handshake uri <sup>3</sup>
9. wallet and app compute DH symmetric channel key
10. symmetric encrypted acknowledgment message is sent
11. channel is open

**Why not simply use directly the crypto address in the wallet?**  
There would be one big upside namely the wallet-app channel could be easily restored on any wallet that
imported the crypto private key material, this would also allow the user to accept/confirm messages coming from the app on different devices. The reason for the decision against such a solution is because it would imply that if a app sets up a channel once with a wallet it will always be able to send messages to it in future and since security is of outmost importance for this standard the decision has been made to have random channel keys which can be destroyed/ignored when an app turns rogue.

<sup>2</sup> app id and app icon can be spoofed by any dapp, however the browser extension should make sure that spoofing is avoided. Also the user always has to check him/herself if the shown URL matches
the one in his/her address bar.
<sup>3</sup> public key is used to derive address on which both parties are listening.

#### 2. Unresponsive counter party

If for whatever reason one party will not respond to messages anymore the user should be informed accordingly. The user can then choose to either close the channel and reopen or just
retry at a later point in time.

#### 3. Closing a channel

Closing a channel will require one of the parties to send a channel close operation. After closing the channel the party will no longer listen to the channel (fire and forget).

#### 4. Cleanup

Channels without activity for 90 days should be considered as dead. All state related to that channel should be removed.

## Test Cases

_TBD: Test cases for an implementation are strongly recommended as are any proofs of correctness via formal methods._

## Implementations

_TBD: Any implementation must be completed before any TZIP is given status “Last Call”, but it need not be completed before the TZIP is merged as draft._

## Apendix

### Wallets implementing the standard

- [AirGap](https://airgap.it)

### Applications using the standard

- TBD

## Copyright

Copyright and related rights waived via
[CC0](https://creativecommons.org/publicdomain/zero/1.0/).