Skip to main content

Usage of Sync API

In order to provide state synchronization between user's devices we must add Sync API support. As per Sync API requierments user must sign additional message to enable state synchronization.

Stores

State synchronization is achieved by sharing the same key value stores among every client that user registered in Chat API. For Chat API there are following stores:

Sent Invites Store

Store that handles synchronized state of invites that are sent by multiple clients. Whenever any client sends an invite it needs to update the store with name com.walletconnect.chat.sentInvites with SentInvite data structure.

Store Key

Key of Sent Invite Store must be equal to responseTopic from SentInvite data structure.

SentInvite

SentInvite structure contains minimal data required to complete Invite Protocol.

{
"id": number,
"message": string,
"inviterAccount": string,
"inviteeAccount": string,
"inviterPubKeyY": string,
"inviterPrivKeyY": string,
"status": 'pending' | 'rejected' | 'approved',
"responseTopic": string,
"symKey": string,
"timestamp": number
}

Example SentInvite payload:

{
"id": 1684319157629569,
"message": "Hey there! Wanna chat?",
"inviterAccount": "eip155:1:0x45B84Bc460Ab29691858A28d782e2fdd575A4dBb",
"inviteeAccount": "eip155:1:0xc2256117Ed8bA25AE30061f6b001DeDCbd1BBBee",
"inviterPubKeyY": "a579e7742c5e3efb3fa2dc092bfdeef0c877323e498423b1eabae7fb5bda9253",
"inviterPrivKeyY": "b82c2781ba532ecd069ec89e4e7cda05c7b5dee27b6e08cdf412d22ff3d2517c",
"status": "pending",
"responseTopic": "0b88a80bbcd9cc4169d9d9f8cf784108d41ef7be89ef5152348941d2dbecfb89",
"symKey": "e1e01461243ee392d847e8c7df293e88cbc4199550c0a21feec3b7651809eb13",
"timestamp": 1684319157629569
}

Threads Store

Store that handles synchronized state of chat threads that blockchain account is having. Whenever any client accepts an invite or receives response to sent invite it needs to update the store with name com.walletconnect.chat.threads with Thread data structure.

Store Key

Key of Threads Store must be equal to topic from Thread data structure.

Thread

Thread structure contains minimal data required to receive messages in chat thread

{
"topic": string,
"selfAccount": string,
"peerAccount": string,
"symKey": string
}

Example Thread payload:

{
"topic": "1ded8a18c7e702b6eb4439ae9c3528c2d56df25a85ab5f8f289696400d2ec180",
"selfAccount": "eip155:1:0x45B84Bc460Ab29691858A28d782e2fdd575A4dBb",
"peerAccount": "eip155:1:0xc2256117Ed8bA25AE30061f6b001DeDCbd1BBBee",
"symKey": "7ebf752fd66bbcc95d7f2d70b23bc470a0990f31ea3b5aca909dd63eb96535df"
}

Invite Keys Store

Store that handles synchronized state of current invite key, which allows other clients to invite the blockchain account. Whenever any client registers invite key in Keys Server it needs to update the store with name com.walletconnect.chat.inviteKeys with InviteKeys data structure.

Store Key

Key of Invite Keys Store must be equal to account from InviteKeys data structure.

InviteKeys

InviteKeys structure contains minimal data required to share received invites across clients

{
"publicKey": string,
"privateKey": string,
"account": string
}

Example InviteKeys payload:

{
"publicKey": "09fea56ae6259ae51b6b5a3a080cc382453284e5f1bafe0ce48849401d25d03e",
"privateKey": "80327450269353e1d2d13752805bd8922ef2893ff6041fe5e833ee432d1b1a4d",
"account": "eip155:1:0x1AAe9864337E821f2F86b5D27468C59AA333C877"
}

Received Invites Status Store

Store that handles synchronized state of received invites status, which allows other clients to acknowledge that some other responded already responded to invite. Whenever a client rejects received invite com.walletconnect.chat.receivedInviteStatuses with ReceivedInviteStatus data structure.

Store Key

Key of Received Invites Status Store must be equal to id from ReceivedInviteStatus data structure.

ReceivedInviteStatus

ReceivedInviteStatus structure contains minimal data required to share received invites updates across clients

{
"id": number,
"status": string,
}

Example ReceivedInviteStatus payload:

{
"id": 12325311235235,
"status": "approved",
}

Handling multiclient Chat Requests and Responses

In a multiclient environment there are clients that didn't send a JsonRpcRequest but must be able to handle JsonRpcResponse. For instance, when user A wants to invite user B to chat thread. User A uses his mobile device A1 and sends an JsonRpcRequest for all user B devices, in meantime his desktop client A2 gets an update about the invite that was sent. Since A1 send a JsonRpcRequest it has a protection against duplicate/multiple JsonRpcResponse coming from B clients. A2 which didn't send the request must firstly ensure that protection and also have all necessary data required to act on the response.

Invite Protocol in multiclient environment

A1,A2 - clients that have access A blockchain account keys. Ax - all clients that have access B blockchain account keys. B1,B2 - clients that have access B blockchain account keys. Bx - all clients that have access B blockchain account keys.

A1 retrieves the public key associated with B's blockchain account, publicKey X. A1 generates a keyPair Y to encrypt the invite with derived DH symKey I. A1 sends invite encrypted with type 1 envelope to the invite topic including publicKey Y. A2 get updated with sent invite that contains response topic and symKey I and privKeyY

Invite topic is derived as the hash of the publicKey X.

B1 decrypts type 1 envelope with the privateKey X and publicKey Y and deriving DH symKey I. B1 accepts the invite and generates a keyPair Z for chat thread. B1 sends response with publicKey Z on response topic encrypted with type 0 envelope.

Response topic is derived as the hash of the symKey I.

B1 derives symKey T using publicKey Y and privKey Z. B1 updates thread storage B2 get updated with thread that contains topic, selfAccount, peerAccount and symKey T B2 needs to update status (or remove) of received invite with peerAccount

Thread topic is derived as the hash of the symKey T.

Ax receives response which includes publicKey Z. Ax derives symKey T using privKey Y and publicKey Z. Ax tries to update thread storage if not yet updated

Ax and Bx both subscribe to thread topic and encrypt messages with symKey T.

Receiving Messages in multiclient environment

A1,A2 - clients that have access A blockchain account keys. Ax - all clients that have access A blockchain account keys. B1,B2 - clients that have access B blockchain account keys. Bx - all clients that have access B blockchain account keys.

Whenever A1 sends a message to blockchain account B, all Bx clients receive it as wc_chatMessage request, and then responds with wc_chatMessage response to blockchain account Ax clients that it received the message. In multiclient environment any Ax client, that didn't send the message also receives wc_chatMessage request however they shouldn't respond with wc_chatMessage response unless the device also has account B registered within the Chat Client.