ADR-180: Communication protocols

More details about this document
Latest published version:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on


This document lists and describes the official communication protocols available for realms (ADR-110). This document should be updated regularly when the implementations change or are added to the explorers.


Solution Space Exploration

Decentraland explorers connect to different communications transports via connection strings, URL-like identifiers containing all the information needed to select the technology and establish the connection to the target network.

The basic structure of a connection string is defined with the following BNF:

PROTOCOL          := !':' [A-Za-z][A-Za-z0-9-]+
PARAMETERS        := any+

Here are some examples:
^^^^^^^                                                    protocol
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ parameter

^^^^^^^         protocol
        ^^^^^^^ parameter

^^^^^^^                                                    protocol
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ parameter


The realms will provide ways to get a connection string for our session. A communications adapter must be created with that connection string, which will use a communications transport under the hood.

All communications adapters must implement the semantics defined in ADR-104. Some adapters, like livekit, may take advantage of their underlying implementations to set up Voice chat.

TODO: Document the voicechat semantics

Resolution of communications transport

  1. Get the connection string
  2. Parse it and separate the components protocol and params [protocol, params] = str.split(':', max: 2)
  3. Find the function that handles the protocol and call it with the params


Here is the list of officially supported protocols

signed-login verifications

The signed login exists as part of a "handshake" mechanism to enable authenticated log-ins and access control to different communication services like Livekit.

The verifications of the signed fetch must look for the following properties: intent, signer, and isGuest.

// connectionString = "signed-login:https://my-server/authenticate-comms"

import { Request } from "express"
import * as dcl from "decentraland-crypto-middleware"
  (req: Request & dcl.DecentralandSignatureData, res) => {
    const address: string = req.auth
    const metadata: Record<string, any> = req.authMetadata
    const isGuest: boolean = req.authMetadata.isGuest

    if (!validateMetadata(req.authMetadata)) {
      res.json({ message: "Access denied, invalid metadata" })

    if (!validateAddressHasAccess(address, isGuest)) {
      res.json({ message: "Access denied" })

    // if this point is reached, we can generate a safe token for the address
    res.json({ fixedAdapter: getAdapterFor(address) })

function validateMetadata(metadata: Record<string, any>) {
  if (metadata.signer !== "dcl:explorer" || metadata.intent !== "dcl:explorer:comms-handshake") {
    // this validation prevents signedFetch from the SDK to be used
    // to authenticate users into comms
    return false
  return true

Implementations of signed-login SHOULD add more safety mechanisms like HMAC-signed tokens to their URLs to prevent fraudulent logins.

RFC 2119 and RFC 8174

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.


Copyright and related rights waived via CC0-1.0. Living