# Bitsong WalletConnect messages
## Introduction
Description of [WalletConnect](https://walletconnect.com/) messages used to comunicate between [BitsongJS](https://github.com/bitsongofficial/bitsongjs) powered DApps and [Bitsong mobile wallet](https://github.com/bitsongofficial/wallet-mobile). The key idea is to reuse most of the WC (WalletConnect) message structure while keeping a certain degree of flexibility. The messages should range from high level, ready to use, ones to low level, highly customizable ones. Both version 1 and 2 of WC will be kept in mind
## WalletConnect v1.0 message types
WC 1.0 mostly takes into consideration [Ethereum](https://ethereum.org/) messages. The relevant one is [Send Custom Request](https://docs.walletconnect.com/1.0/quick-start/dapps/client#sign-personal-message-personal_sign). This method has the following fields:
- id (numeric): could be used alongside an alphanumeric name to ease out methods renaming between versions.
- method (string): for the alphanumeric name of the method.
- jsonrpc (string): target version of the protocol (BitsongJS, not WC). Usefull in case of breaking changes to allow new versions of the [mobile wallet](https://github.com/bitsongofficial/wallet-mobile) to support older versions of the [BitsongJS](https://github.com/bitsongofficial/bitsongjs) API while DApps transition.
- params (array): actual params for the message. It's an array in typescript but is actually not required anywhere on the WC library
## WalletConnect v2.0
WC 2.0 has a more chain agnostic API that fit our needs perfectly. The general [request](https://docs.walletconnect.com/2.0/javascript/sign/dapp-usage#making-requests) method has the following fields:
- topic (WalletConnect topic): used for pairing, it's used by WC but is not method specific.
- chainId (string): used to identify the target chain. As our [wallet](https://github.com/bitsongofficial/wallet-mobile) is multichain it could be used to identify the target chain to do the operation on.
- request (Object): contains the same parameters as WC 1.0 message.
## Bitsong messages format
Leveraging WC 1.0 but adapting it to a multichain environment the result is:
```ts
type walletConnectMessage = {
id: number,
method: string,
jsonrpc: string,
params: {
chain: string,
data: any,
}
}
```
Three things are immediately noticeable:
- No address is present. The active profile at the time of the connection will always be used for the DApp. Only the chain can be specified.
- params field is an object and not an array. This will require defining our own type file for WC. We will only override params type and not rewrite all the fields. This opens up to the problem of not catching a change in WC API in a future version but other solutions such as having the object the only element of the array
```ts
params: [{
chain: string,
data: any,
}]
```
or have an array of array syntax
```ts
params: [
["chain", string],
["data", any],
]
```
is not as clean and do not work as well with typescript map type
- The chain field used to target a specific chain in the mobile wallet is inside the params field. Moving forward to WC 2.0 the chainId field will be used and params will contain the method specific parameters directly.
One of the requirement for some methods is sending bytes. For those cases a Base64 encoding could be used.
The response format is:
```ts
type walletConnectResponse = {
method: string,
status: boolean,
payload: operationPayload | errorMessage,
}
```
Where `operationPayload` will always contain the transaction hash but vary for the other fields depending on the method.
## Message types
Messages can be divided into 3 macro types
### High level messages
Those messages will be easily accessible from the [BitsongJS](https://github.com/bitsongofficial/bitsongjs) library with common functions. Some examples are:
```ts
function Send(chain: string, addressee: string, amount: amount[]) {}
function Claim(chain: string, validators?: validator[]) {}
```
And the above mentioned structure with the method name, id, version and params will be constructed automatically. On the [wallet](https://github.com/bitsongofficial/wallet-mobile) end those are the messages that will have a full developed user friendly UI.
### Not explicitly implemented but Stargate compatible messages
Those can be requested with the
```ts
function SignAndBroadcast(chain: chains, messages: StargateMsg[]) {}
```
function and are characterized by the fact that they have not been implemented either by the mobile wallet or JS library in any explicit way but are compatible with the underlying structure. The messages parameter is an array of [Stargate](https://cosmos.github.io/cosmjs/latest/stargate/index.html) formatted messages and will be displayed by the wallet in a generic json like view and will be broadcasted automatically. The return data is the same as the high level methods.
### Completely custom messages
For those the
```ts
function Sign(chain: chains, messages: any[]) {}
```
function will be used. In this case messages is an array of arbitrary data. Each message will be signed and returned as is, it will not be broadcasted by the [mobile wallet](https://github.com/bitsongofficial/wallet-mobile) but instead the signed messages are available in the respose to be used as needed. The mobile wallet will just show the various messages one by one as json.
## Summary
The proposed structure should cover most of the use cases. Possible improvements could be:
- Develop a generic UI for non standard messages more user friendly than a json
- As all the methods require the chain parameter to be specified a function that wraps the API returning an object with the same interface except for the chain parameter could be handy.
```ts
function withChain(api: api, chain: chains)
{
return {}
}
const bitsongAPI = withChain(genericApi, "bitsong")
const cosmosAPI = withChain(genericApi, "cosmos")
```
## Typescript definitions
```ts
enum chains {}
type chainMap = {
[k in chains]: {
address: string,
}
}
type api = {}
const genericApi = {}
function withChain(api: api, chain: chains)
{
return {}
}
const chainApi = withChain(genericApi, "bitsong")
type address = string
type amount = {
amount: string,
denom: string,
}
type validator = {}
type StargateMsg = {
typeUrl: string,
value: any,
}
type proposal = number
enum voteOption {
VOTE_OPTION_UNSPECIFIED,
VOTE_OPTION_YES,
VOTE_OPTION_ABSTAIN,
VOTE_OPTION_NO,
VOTE_OPTION_NO_WITH_VETO,
UNRECOGNIZED = -1,
}
type proposalType = string
function Send(chain: chains, addressee: address, amount: amount[]) {}
function IBCSend(chain: chains, destinationChain: chains, addressee: address, amount: amount) {} {}
function Claim(chain: chains, validators?: validator[]) {}
function Delegate(chain: chains, amount: amount, validator: validator) {}
function Redelegate(chain: chains, amount: amount, currentValidator: validator, newValidator: validator) {}
function Undelegate(chain: chains, amount: amount, validator: validator) {}
function SignAndBroadcast(chain: chains, messages: StargateMsg[]) {}
//Second step
function Vote(chain: chains, proposal: proposal, vote: voteOption) {}
function Deposit(chain: chains, proposal: proposal, amount: amount[]) {}
function SubmitProposal(
chain: chains,
title: string,
type: proposalType | string,
description: string,
initialDeposit: amount[]) {}
//Third step
function Sign(chain: chains, messages: any[]) {}
// Query in futuro
type operation = string
type walletConnectMessage = {
method: operation,
jsonrpc: string,
params: {
chain: chains,
data: any,
}
}
interface operationPayload {}
type errorMessage = {
message: string,
code: number,
}
type walletConnectResponse = {
method: operation,
status: boolean,
payload: operationPayload | errorMessage,
}
interface BroadcastedOperationPayload extends operationPayload {
hash: string,
}
interface SubmitProposalPayload extends BroadcastedOperationPayload {
proposalId: proposal
}
interface SendPayload extends BroadcastedOperationPayload {
fee: amount
}
interface SignPayload extends operationPayload {
signedMessage: byte[] | string, // Da decidere
}
```