glyphdocs
Protocol / Relay

Protocol v2 fields and bindings

Understand request hashes, network bindings, and signed callback payloads.

Protocol v2 fields and bindings

Protocol v2 binds a wallet action to the dApp, delivery route, network, request, and returned result. The same values must survive serialization and transport without being silently changed. For an approachable overview of how those bindings move through Glyph Connect and Relay, see Understand Glyph Connect and Relay v2.

Request envelope

A request uses the glyph-connect-request/2 protocol and is encoded at:

glyph://v2/request?d=<base64url JSON envelope>

The envelope contains:

FieldMeaning
protocolThe request protocol marker, glyph-connect-request/2.
requestThe typed request with type, dApp metadata, nonce, expiry, and action fields.
callbackAn HTTPS callback URL or null.
redirect_uriAn HTTPS redirect URL or null.
networkA binding such as qubic:mainnet, qubic:testnet, or a custom hashed binding.
request_hashsha256:<base64url digest> over the other five fields.

The SDK canonicalizes the dApp origin and normalizes missing delivery values to null before hashing. The hash input is:

{
  protocol,
  request,
  callback: callback ?? null,
  redirect_uri: redirect_uri ?? null,
  network,
}

The canonical JSON routine sorts object keys and emits deterministic JSON. Never recompute the hash from a differently shaped object.

Origin and delivery binding

The request's dapp.origin is a credential-free HTTPS origin with no path, query, or fragment. A direct callback and redirect_uri must have the same canonical origin. The only delivery exception is the official Relay v2 callback endpoint at https://relay.glyphq.org.

A Relay stream URL is a read endpoint, not a wallet delivery URL. It must not be placed in callback or redirect_uri.

Signed callback envelope

Wallet 0.16.5 returns a signed v2 callback envelope:

interface GlyphCallbackSignaturePayload {
  version: "glyph-connect-callback-envelope/2";
  request_hash: string;
  network: GlyphNetworkBinding;
  nonce: string;
  dapp_origin: string;
  request_type: GlyphRequestType;
  exp: number | null;
  issued_at: number;
  result_hash: string;
  relay: GlyphCallbackRelayBinding;
}

The outer object contains version, the result, this payload, and a proof:

interface GlyphCallbackProof {
  algorithm: "qubic-schnorrq-sha256";
  identity: string;
  public_key: string;
  signature: string;
  signed_payload: string;
}

result_hash binds the exact canonical JSON result. signed_payload must be the canonical JSON representation of the payload. The signature covers the UTF-8 bytes of signed_payload, not a reserialized or pretty-printed variant.

Relay binding

For a Relay v2 callback, the signed relay binding identifies the official relay route and session without exposing the callback write secret in the signed callback URL field. The v2-relevant fields are:

  • callback_url
  • official_relay
  • route
  • session_id
  • callback_capability_fingerprint

verifyCallbackEnvelope() canonicalizes the expected official Relay v2 callback URL before comparing it to the signed binding. Pass the original callback URL as expectedCallbackUrl rather than trying to reproduce the fingerprint in application code.

Network binding

Use the exported bindings for the two named networks:

import { GLYPH_MAINNET, GLYPH_TESTNET } from "@glyph-oss/connect";

For a custom RPC object, use createCustomNetworkBinding(). The resulting qubic:custom:sha256:<hash> ID is a content binding. All participants must hash the same canonical object.

Verification rule

A result is accepted only when the request record, network, callback route, result hash, canonical signed payload, trusted public key, and SchnorrQ signature all agree. Use k12 and verify from @qubic.org/crypto@1.0.0 for the final dApp-side signature check. If any field is different, reject the callback instead of attempting to repair or reinterpret it.

On this page