Relay v2 API
Prepare, register, and subscribe to an official Relay v2 session.
Relay v2 API
The Relay v2 client in @glyph-oss/connect uses an official relay session with separate write and read capabilities. The default and only accepted relay origin is https://relay.glyphq.org.
Types
interface GlyphRelayCapabilities {
session: string;
callbackCap: string;
readCap: string;
}
interface GlyphRelayUrls extends GlyphRelayCapabilities {
registerUrl: string;
callbackUrl: string;
streamUrl: string;
resultUrl: string;
}
interface GlyphPreparedRelaySession extends GlyphRelayUrls {
registered: true;
}Capability strings are generated as opaque, high-entropy base64url values. Keep the callback capability only where the wallet needs its callback URL. Keep the read capability in the dApp process and do not put it in a callback URL.
Functions
createRelayCapabilities(options?)
Creates and validates a distinct session, callback capability, and read capability. It accepts a partial GlyphRelayCapabilities object when a caller needs to provide values from a secure session store.
relayUrls(capabilities?, relayUrl?)
Returns the four URLs for a session without making a network request:
| URL | Method | Purpose |
|---|---|---|
registerUrl | POST | Initialize the session with the two capabilities. |
callbackUrl | POST | Wallet delivery endpoint. |
streamUrl | GET | dApp SSE subscription endpoint. |
resultUrl | GET | dApp polling endpoint. |
The relayUrl must be exactly https://relay.glyphq.org.
registerRelaySession(capabilities, relayUrl?)
Builds the URLs and posts JSON containing callbackCap and readCap to registerUrl. A successful response returns the URLs. The registration endpoint must be called before the wallet sends a callback.
prepareRelaySession(capabilities?, relayUrl?)
Creates capabilities, registers them, and returns a GlyphPreparedRelaySession. Pass this prepared value to subscribeViaRelayV2().
subscribeViaRelayV2(subscription, session, options?)
Subscribes to session.streamUrl and resolves with the first valid callback result. subscription can be a request object, an expected callback object, or a nonce string. When a nonce string is used, options.expectedType is required.
interface GlyphRelayOptions {
relayUrl?: string;
expectedType?: GlyphRequestType;
timeoutMs?: number;
onStatus?: (status: GlyphRequestStatus) => void;
verification?: GlyphCallbackVerificationOptions;
}The default stream timeout is five minutes. The function validates the callback against the subscription's nonce and type, and uses verification when strict signed-envelope verification is required.
parseSSEStream(body)
Parses a standards-compliant ReadableStream<Uint8Array> into { event, data } records. The relay client handles result, timeout, and close events for you.
Lifecycle
import { k12, verify } from "@qubic.org/crypto";
import {
createEnvelope,
createTransferRequest,
launchGlyphRequest,
prepareRelaySession,
subscribeViaRelayV2,
} from "@glyph-oss/connect";
const request = createTransferRequest({
type: "transfer",
dapp: { origin: "https://example.app" },
to: recipientIdentity,
amount: "1000",
});
const session = await prepareRelaySession();
const envelope = createEnvelope(request, { callback: session.callbackUrl });
const resultPromise = subscribeViaRelayV2(request, session, {
verification: {
requireSigned: true,
expectedRequestHash: envelope.request_hash,
expectedNetwork: envelope.network,
expectedDappOrigin: request.dapp.origin,
expectedExp: request.exp ?? null,
expectedCallbackUrl: session.callbackUrl,
verifySignature: ({ algorithm, payload, signature, publicKey }) => {
if (algorithm !== "qubic-schnorrq-sha256") return false;
return verify(k12(payload, 32), signature, publicKey);
},
},
});
launchGlyphRequest(envelope);
const result = await resultPromise;Prepare first, subscribe with the returned read URL, launch with the returned callback URL, and handle the result. Do not construct an unregistered session or replace a read URL with a callback URL.
Relay lifetime and errors
The relay stores an accepted JSON result for up to ten minutes. An SSE stream waits up to five minutes, and a session allows at most five listeners. A callback is accepted once. Registration, callback, stream, and result requests are rate limited and validate HTTP method, content type, URL path, and capability authorization.
