Skip to main content

Subscribe to Updates

Step-by-step guide for registering balance and transfer subscriptions and handling push notifications.

Prerequisites: Connect and Authenticate. You must have an active, authenticated connection before subscribing.


What You're Doing

Once connected, you can register to receive push notifications for:

  • balance changes on one or more tokens;
  • new confirmed transfers involving your wallet on one or more tokens.

Both registrations are sent as signed messages, like any other gateway request. Both are cancelled automatically when your connection closes.


Subscribe to Balance Updates

async function subscribeToBalances(ws, signer, domainSeparators) {
const payload = {
requestId: crypto.randomUUID(),
domainSeparators,
};
const msg = await buildSignedMessage(signer, 'SUBSCRIBE_BALANCE', payload);
ws.send(JSON.stringify(msg));
}

// Example: subscribe to two tokens
subscribeToBalances(ws, signer, [USDC_DOMAIN_SEPARATOR, EURC_DOMAIN_SEPARATOR]);

The gateway responds with SUBSCRIBE_BALANCE_ACK listing the active tokens. After that, a BALANCE_UPDATE is pushed whenever your balance changes for any subscribed token:

case 'SUBSCRIBE_BALANCE_ACK':
console.log('Balance subscriptions active:', msg.payload.subscribedSeparators);
break;

case 'BALANCE_UPDATE':
const { domainSeparator, balance } = msg.payload;
updateBalanceDisplay(domainSeparator, balance);
break;

Subscribe to Transfer Notifications

async function subscribeToTransfers(ws, signer, domainSeparators) {
const payload = {
requestId: crypto.randomUUID(),
domainSeparators,
};
const msg = await buildSignedMessage(signer, 'SUBSCRIBE_TRANSFERS', payload);
ws.send(JSON.stringify(msg));
}

subscribeToTransfers(ws, signer, [USDC_DOMAIN_SEPARATOR]);
case 'SUBSCRIBE_TRANSFERS_ACK':
console.log('Transfer subscriptions active:', msg.payload.subscribedSeparators);
break;

case 'TRANSFER_NOTIFICATION':
const { transfer } = msg.payload;
console.log(`${transfer.direction} ${transfer.value} — block ${transfer.blockNumber}`);
// If direction is 'OUT' and this matches a pending payment, it is now settled.
break;

Unsubscribe

To cancel a subscription for specific tokens:

async function unsubscribe(ws, signer, channel, domainSeparators) {
const payload = {
requestId: crypto.randomUUID(),
channel, // 'BALANCE' or 'TRANSFERS'
domainSeparators,
};
const msg = await buildSignedMessage(signer, 'UNSUBSCRIBE', payload);
ws.send(JSON.stringify(msg));
}

// Remove one token from the balance channel
unsubscribe(ws, signer, 'BALANCE', [EURC_DOMAIN_SEPARATOR]);

Re-subscribing After Reconnection

Subscriptions do not survive a connection close. After reconnecting, re-register:

async function onReconnect(ws, signer) {
await subscribeToBalances(ws, signer, myTokenList);
await subscribeToTransfers(ws, signer, myTokenList);

// Also re-sync current state, since notifications during
// the disconnection window were not delivered.
await sendGetBalance(ws, signer, myTokenList);
await sendGetHistory(ws, signer, myTokenList);
}

Using Transfer Notifications for Settlement Confirmation

The TRANSFER_NOTIFICATION channel is the correct signal for confirmed payment settlement. A payment submitted via SUBMIT_PAYMENT reaches SUCCESS status when the network accepts the transaction, but this is not final. The TRANSFER_NOTIFICATION arrives only after the transfer-history service has observed the on-chain event with the required block confirmation depth.

To ensure you receive the settlement notification for a payment you are submitting, subscribe to transfers on the relevant token before submitting the payment.


Common Mistakes

MistakeResultFix
Subscribing after submitting a paymentMay miss the TRANSFER_NOTIFICATION if confirmation is fastSubscribe before submitting
Not re-subscribing after reconnectionNo notifications received on the new connectionRe-register in your reconnection handler
Assuming subscriptions persist across reconnectsSilent data gapSubscriptions are connection-scoped; always re-register