Skip to main content
Every error thrown by the Transfer SDK is a TransferError instance with a machine-readable code property. This lets you branch on failure mode without parsing message strings.

TransferError

import { TransferError, getDisplayMessage } from '@swype-org/transfer';
class TransferError extends Error {
  readonly code: TransferErrorCode;
  constructor(code: TransferErrorCode, message: string);
}

Error codes

CodeMeaningUser-facing message
TRANSFER_DISMISSEDUser dismissed the transfer (tapped backdrop, pressed Escape, or closed the flow).”The transfer was dismissed before the transfer completed.”
SIGNER_REQUEST_FAILEDSigner returned a non-2xx response.”Unable to start the payment. Please try again.”
SIGNER_NETWORK_ERRORNetwork failure reaching the signer.”Unable to reach the payment server. Check your connection and try again.”
SIGNER_RESPONSE_INVALIDSigner response missing required fields (merchantId, payload, signature, preview).”The payment server returned an unexpected response.”
SIGNER_TIMEOUTSigner did not respond within signerTimeoutMs.”The payment server took too long to respond. Please try again.”
FLOW_TIMEOUTEntire flow exceeded flowTimeoutMs.”The payment flow timed out. Please try again.”
INVALID_REQUESTBad input (missing amount, invalid address, destroyed instance, etc.).”Invalid payment request. Please check your input.”

getDisplayMessage

Returns a user-friendly display string for a TransferError. You can show this directly in your UI.
function getDisplayMessage(error: TransferError): string

Usage

try {
  await transfer.requestDeposit({ /* ... */ });
} catch (err) {
  if (err instanceof TransferError) {
    // Show user-friendly message in your UI
    showToast(getDisplayMessage(err));

    // Log machine-readable code for debugging
    console.error(err.code, err.message);
  }
}

React

The useBlinkTransfer hook provides displayMessage as a convenience:
const { error, displayMessage } = useBlinkTransfer({ signer: '/api/sign-payment' });

// displayMessage is null when there is no error,
// otherwise it's the result of getDisplayMessage(error)
{error && <p className="error">{displayMessage}</p>}

Handling specific error codes

try {
  await transfer.requestDeposit({ /* ... */ });
} catch (err) {
  if (!(err instanceof TransferError)) throw err;

  switch (err.code) {
    case 'TRANSFER_DISMISSED':
      // User intentionally closed — no action needed
      break;
    case 'SIGNER_REQUEST_FAILED':
    case 'SIGNER_NETWORK_ERROR':
    case 'SIGNER_TIMEOUT':
      // Signer issue — prompt retry
      showRetryDialog(getDisplayMessage(err));
      break;
    case 'SIGNER_RESPONSE_INVALID':
      // Integration bug — log for investigation
      reportError(err);
      break;
    case 'FLOW_TIMEOUT':
      // Flow took too long — prompt retry
      showRetryDialog(getDisplayMessage(err));
      break;
    case 'INVALID_REQUEST':
      // Bad input — show validation error
      showValidationError(getDisplayMessage(err));
      break;
  }
}

TransferErrorCode

The union of all error code strings:
type TransferErrorCode =
  | 'TRANSFER_DISMISSED'
  | 'SIGNER_REQUEST_FAILED'
  | 'SIGNER_NETWORK_ERROR'
  | 'SIGNER_RESPONSE_INVALID'
  | 'SIGNER_TIMEOUT'
  | 'FLOW_TIMEOUT'
  | 'INVALID_REQUEST';