Keyboard shortcuts

Press โ† or โ†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Bridging USDC/USDT

A bridge is an order that pays a recipient from another chain or over Lightning, with no funds moving through the SDK. The payer pays the cross-chain provider, and the provider delivers to the recipient: a Spark address, a Lightning address, or a USDC/USDT address on another chain.

Bridging suits a server that facilitates payments: it needs only your API key, no seed and no storage.

Getting a bridging client

Build a BridgingClientBridgingClientBridgingClientBridgingClientBridgingClientBridgingClientBridgingClientBridgingClientBridgingClient from your API key with new_bridging_clientnew_bridging_clientnewBridgingClientnewBridgingClientnewBridgingClientnewBridgingClientnewBridgingClientNewBridgingClientNewBridgingClient. Keep it for the life of your process: it caches the provider's routes and prices between calls.

Rust
let config = default_bridging_config("<your api key>".to_string());
let client = new_bridging_client(config).await?;
Swift
let config = defaultBridgingConfig(apiKey: "<your api key>")
let client = try await newBridgingClient(config: config)
Kotlin
val config = defaultBridgingConfig("<your api key>")
val client = newBridgingClient(config)
C#
var config = BreezSdkSparkMethods.DefaultBridgingConfig(apiKey: "<your api key>");
var client = await BreezSdkSparkMethods.NewBridgingClient(config: config);
Javascript
const config = defaultBridgingConfig('<your api key>')
const client = await newBridgingClient(config)
React Native
const config = defaultBridgingConfig('<your api key>')
const client = await newBridgingClient(config)
Flutter
BridgingConfig config = defaultBridgingConfig(apiKey: "<your api key>");
BridgingClient client = await newBridgingClient(config: config);
Python
config = default_bridging_config(api_key="<your api key>")
try:
    client = await new_bridging_client(config=config)
except Exception as error:
    logging.error(error)
    raise
Go
config := breez_sdk_spark.DefaultBridgingConfig("<your api key>")
client, err := breez_sdk_spark.NewBridgingClient(config)
if err != nil {
	return nil, err
}

An app that already runs the SDK, including in server mode, can get a client from it instead. The client shares the SDK's API key, and its cross-chain settings when they are set. Bridging doesn't need cross-chain payments enabled.

Rust
let client = sdk.get_bridging_client()?;
Swift
let client = try sdk.getBridgingClient()
Kotlin
val client = sdk.getBridgingClient()
C#
var client = sdk.GetBridgingClient();
Javascript
const client = sdk.getBridgingClient()
React Native
const client = sdk.getBridgingClient()
Flutter
BridgingClient client = sdk.getBridgingClient();
Python
try:
    client = sdk.get_bridging_client()
except Exception as error:
    logging.error(error)
    raise
Go
client, err := sdk.GetBridgingClient()
if err != nil {
	return nil, err
}

Creating a bridge

  1. List the routes that can pay the recipientrecipientrecipientrecipientrecipientrecipientrecipientRecipientRecipient with get_routesget_routesgetRoutesgetRoutesgetRoutesgetRoutesgetRoutesGetRoutesGetRoutes. Each BridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePairBridgeRoutePair has a sourcesourcesourcesourcesourcesourcesourceSourceSource, what the payer pays, and a destinationdestinationdestinationdestinationdestinationdestinationdestinationDestinationDestination, what the recipient receives. Pick one by the assetassetassetassetassetassetassetAssetAsset and chainchainchainchainchainchainchainChainChain of its sides.
  2. Call create_bridgecreate_bridgecreateBridgecreateBridgecreateBridgecreateBridgecreateBridgeCreateBridgeCreateBridge with the same recipient, the route, the amount and, when needed, the payer's refund address.
  3. Show the payer the returned payment_requestpayment_requestpaymentRequestpaymentRequestpaymentRequestpaymentRequestpaymentRequestPaymentRequestPaymentRequest, and store the bridge_idbridge_idbridgeIdbridgeIdbridgeIdbridgeIdbridgeIdBridgeIdBridgeId and status_tokenstatus_tokenstatusTokenstatusTokenstatusTokenstatusTokenstatusTokenStatusTokenStatusToken to look up the status later. The response also carries the deposit and the expected delivery.
Rust
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
let recipient = "<recipient>".to_string();

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
let routes = client
    .get_routes(GetBridgeRoutesRequest {
        recipient: recipient.clone(),
    })
    .await?
    .routes;
let route = routes
    .into_iter()
    .find(|r| r.source.asset == "USDC" && r.source.chain == "base")
    .ok_or_else(|| anyhow::anyhow!("No route from USDC on Base"))?;

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
let response = client
    .create_bridge(CreateBridgeRequest {
        recipient,
        route,
        amount: 10_000_000,
        // Required to pay a Lightning address.
        refund_address: Some("<payer address on Base>".to_string()),
        fee_policy: None,
        max_slippage_bps: None,
    })
    .await?;

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
info!("Pay with: {}", response.payment_request);
info!("Bridge id: {}", response.bridge_id);
Swift
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
let recipient = "<recipient>"

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
let routes = try await client.getRoutes(
    request: GetBridgeRoutesRequest(recipient: recipient)
).routes
guard
    let route = routes.first(where: {
        $0.source.asset == "USDC" && $0.source.chain == "base"
    })
else {
    throw NSError(domain: "Bridging", code: 1)
}

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
let response = try await client.createBridge(
    request: CreateBridgeRequest(
        recipient: recipient,
        route: route,
        amount: BInt(10_000_000),
        // Required to pay a Lightning address.
        refundAddress: "<payer address on Base>",
        feePolicy: nil,
        maxSlippageBps: nil
    ))

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
print("Pay with: \(response.paymentRequest)")
print("Bridge id: \(response.bridgeId)")
Kotlin
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
val recipient = "<recipient>"

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
val routes = client.getRoutes(GetBridgeRoutesRequest(recipient = recipient)).routes
val route = routes.find { it.source.asset == "USDC" && it.source.chain == "base" }
    ?: throw IllegalArgumentException("No route from USDC on Base")

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
val response = client.createBridge(
    CreateBridgeRequest(
        recipient = recipient,
        route = route,
        amount = BigInteger.fromLong(10_000_000L),
        // Required to pay a Lightning address.
        refundAddress = "<payer address on Base>",
        feePolicy = null,
        maxSlippageBps = null,
    )
)

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
// Log.v("Breez", "Pay with: ${response.paymentRequest}")
// Log.v("Breez", "Bridge id: ${response.bridgeId}")
C#
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
var recipient = "<recipient>";

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
var routes = (await client.GetRoutes(
    request: new GetBridgeRoutesRequest(recipient: recipient)
)).routes;
var route = routes.First(
    r => r.source.asset == "USDC" && r.source.chain == "base"
);

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
var request = new CreateBridgeRequest(
    recipient: recipient,
    route: route,
    amount: new BigInteger(10_000_000),
    // Required to pay a Lightning address.
    refundAddress: "<payer address on Base>",
    feePolicy: null,
    maxSlippageBps: null
);
var response = await client.CreateBridge(request: request);

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
Console.WriteLine($"Pay with: {response.paymentRequest}");
Console.WriteLine($"Bridge id: {response.bridgeId}");
Javascript
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
const recipient = '<recipient>'

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
const { routes } = await client.getRoutes({ recipient })
const route = routes.find((r) => r.source.asset === 'USDC' && r.source.chain === 'base')
if (route === undefined) {
  throw new Error('No route from USDC on Base')
}

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
const response = await client.createBridge({
  recipient,
  route,
  amount: BigInt(10_000_000),
  // Required to pay a Lightning address.
  refundAddress: '<payer address on Base>',
  feePolicy: undefined,
  maxSlippageBps: undefined
})

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
console.log(`Pay with: ${response.paymentRequest}`)
console.log(`Bridge id: ${response.bridgeId}`)
React Native
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
const recipient = '<recipient>'

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
const { routes } = await client.getRoutes({ recipient })
const route = routes.find((r) => r.source.asset === 'USDC' && r.source.chain === 'base')
if (route === undefined) {
  throw new Error('No route from USDC on Base')
}

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
const response = await client.createBridge({
  recipient,
  route,
  amount: BigInt(10_000_000),
  // Required to pay a Lightning address.
  refundAddress: '<payer address on Base>',
  feePolicy: undefined,
  maxSlippageBps: undefined
})

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
console.log(`Pay with: ${response.paymentRequest}`)
console.log(`Bridge id: ${response.bridgeId}`)
Flutter
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
String recipient = "<recipient>";

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
final routesResponse = await client.getRoutes(
  request: GetBridgeRoutesRequest(recipient: recipient),
);
BridgeRoutePair route = routesResponse.routes.firstWhere(
  (r) => r.source.asset == "USDC" && r.source.chain == "base",
);

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
final response = await client.createBridge(
  request: CreateBridgeRequest(
    recipient: recipient,
    route: route,
    amount: BigInt.from(10000000),
    // Required to pay a Lightning address.
    refundAddress: "<payer address on Base>",
    feePolicy: null,
    maxSlippageBps: null,
  ),
);

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
print("Pay with: ${response.paymentRequest}");
print("Bridge id: ${response.bridgeId}");
Python
try:
    # Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
    # address.
    recipient = "<recipient>"

    # List the routes that pay them and pick what the payer pays in, e.g.
    # USDC on Base.
    routes_response = await client.get_routes(
        request=GetBridgeRoutesRequest(recipient=recipient)
    )
    route = next(
        (
            r
            for r in routes_response.routes
            if r.source.asset == "USDC" and r.source.chain == "base"
        ),
        None,
    )
    if route is None:
        raise ValueError("No route from USDC on Base")

    # Ask for $10. The amount is in the recipient's stablecoin when they are
    # paid in one, the payer's otherwise (6 decimals for USDC). The deposit
    # is refunded to the payer's address if the recipient can't be paid.
    request = CreateBridgeRequest(
        recipient=recipient,
        route=route,
        amount=10_000_000,
        # Required to pay a Lightning address.
        refund_address="<payer address on Base>",
        fee_policy=None,
        max_slippage_bps=None,
    )
    response = await client.create_bridge(request=request)

    # Show the payer what to pay, and store the bridge id and status token to
    # look up the status later.
    logging.debug(f"Pay with: {response.payment_request}")
    logging.debug(f"Bridge id: {response.bridge_id}")
except Exception as error:
    logging.error(error)
    raise
Go
// Who to pay: a Spark address, a Lightning address or an EVM/Solana/Tron
// address.
recipient := "<recipient>"

// List the routes that pay them and pick what the payer pays in, e.g.
// USDC on Base.
routesResponse, err := client.GetRoutes(breez_sdk_spark.GetBridgeRoutesRequest{
	Recipient: recipient,
})
if err != nil {
	return err
}
routes := routesResponse.Routes
var route *breez_sdk_spark.BridgeRoutePair
for i := range routes {
	if routes[i].Source.Asset == "USDC" && routes[i].Source.Chain == "base" {
		route = &routes[i]
		break
	}
}
if route == nil {
	return errors.New("no route from USDC on Base")
}

// Ask for $10. The amount is in the recipient's stablecoin when they are
// paid in one, the payer's otherwise (6 decimals for USDC). The deposit is
// refunded to the payer's address if the recipient can't be paid.
refundAddress := "<payer address on Base>"
response, err := client.CreateBridge(breez_sdk_spark.CreateBridgeRequest{
	Recipient: recipient,
	Route:     *route,
	Amount:    new(big.Int).SetInt64(10_000_000),
	// Required to pay a Lightning address.
	RefundAddress:  &refundAddress,
	FeePolicy:      nil,
	MaxSlippageBps: nil,
})
if err != nil {
	return err
}

// Show the payer what to pay, and store the bridge id and status token to
// look up the status later.
log.Printf("Pay with: %s", response.PaymentRequest)
log.Printf("Bridge id: %s", response.BridgeId)

Recipients

RecipientPayer pays fromRecipient receives
Spark addressUSDC/USDT on another chainBitcoin, or a stablecoin token such as USDB
Lightning address, including a Cash App $cashtagUSDC/USDT on another chainBitcoin over Lightning
USDC/USDT address on another chainLightning, or USDC/USDT on any chainUSDC/USDT on that chain

Pass the recipient as you have it: a Spark address, a Lightning address or $cashtag, or an address or EIP-681 URI on another chain. A recipient that can't be bridged fails with SdkError::InvalidInputSdkError.INVALID_INPUTSdkError.invalidInputSdkError.InvalidInputSdkError.InvalidInputSdkError.InvalidInputSdkError.InvalidInputSdkErrorInvalidInputSdkError.InvalidInput.

Routes move only USD stablecoins and Bitcoin. For a recipient on another chain, the address decides which routes apply: an EVM address is paid on any EVM chain, unless it names a chain or token (as an EIP-681 URI does). That can be hundreds of routes, so filter them by the sources you accept.

Amount and fees

The amountamountamountamountamountamountamountAmountAmount is in the base units of the stablecoin the recipient receives, per its side's BridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.decimalsBridgeRoutePairSide.DecimalsBridgeRoutePairSide.Decimals. When the recipient receives Bitcoin, it's in the stablecoin the payer pays instead. These routes carry USD-pegged stablecoins, so at parity it is the USD value: 1_000_000 is 1 USDC (6 decimals), about $1. USDC and USDT on BNB Chain have 18 decimals.

fee_policyfee_policyfeePolicyfeePolicyfeePolicyfeePolicyfeePolicyFeePolicyFeePolicy decides who absorbs the provider fee. FeePolicy::FeesExcludedFeePolicy.FEES_EXCLUDEDFeePolicy.feesExcludedFeePolicy.FeesExcludedFeePolicy.FeesExcludedFeePolicy.FeesExcludedFeePolicy.FeesExcludedFeePolicyFeesExcludedFeePolicy.FeesExcluded (the default) adds it on top of what the payer pays, and FeePolicy::FeesIncludedFeePolicy.FEES_INCLUDEDFeePolicy.feesIncludedFeePolicy.FeesIncludedFeePolicy.FeesIncludedFeePolicy.FeesIncludedFeePolicy.FeesIncludedFeePolicyFeesIncludedFeePolicy.FeesIncluded takes it out of the amount. The fee includes your partner fee if you set one.

Refund address

When the payer pays from another chain, refund_addressrefund_addressrefundAddressrefundAddressrefundAddressrefundAddressrefundAddressRefundAddressRefundAddress is their address on that chain. If the recipient can't be paid, the provider refunds the payment there. It must belong to the sourcesourcesourcesourcesourcesourcesourceSourceSource chain's family, e.g. an EVM 0x... address for USDC on Base.

It's required to pay a Lightning address, and recommended whenever the payer pays from another chain: without one, the provider has no address to refund to. A payer paying over Lightning needs none, and any address given is ignored.

Response fields

CreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponseCreateBridgeResponse carries what the payer pays, the quote, and what tracks the bridge:

FieldMeaning
bridge_idbridge_idbridgeIdbridgeIdbridgeIdbridgeIdbridgeIdBridgeIdBridgeIdIdentifies the bridge. Store it to look its status up.
status_tokenstatus_tokenstatusTokenstatusTokenstatusTokenstatusTokenstatusTokenStatusTokenStatusTokenPass it to get_bridge_statusget_bridge_statusgetBridgeStatusgetBridgeStatusgetBridgeStatusgetBridgeStatusgetBridgeStatusGetBridgeStatusGetBridgeStatus with the bridge_idbridge_idbridgeIdbridgeIdbridgeIdbridgeIdbridgeIdBridgeIdBridgeId.
payment_requestpayment_requestpaymentRequestpaymentRequestpaymentRequestpaymentRequestpaymentRequestPaymentRequestPaymentRequestWhat the payer pays: an EIP-681 URI on EVM chains, a BOLT11 invoice over Lightning, otherwise the bare deposit address.
info.deposit_addressinfo.deposit_addressinfo.depositAddressinfo.depositAddressinfo.depositAddressinfo.depositAddressinfo.depositAddressInfo.DepositAddressInfo.DepositAddressThe deposit address on the source chain, or the BOLT11 invoice over Lightning.
info.deposit_amountinfo.deposit_amountinfo.depositAmountinfo.depositAmountinfo.depositAmountinfo.depositAmountinfo.depositAmountInfo.DepositAmountInfo.DepositAmountThe amount the payer pays, in the source asset's base units (sats over Lightning).
info.expected_received_amountinfo.expected_received_amountinfo.expectedReceivedAmountinfo.expectedReceivedAmountinfo.expectedReceivedAmountinfo.expectedReceivedAmountinfo.expectedReceivedAmountInfo.ExpectedReceivedAmountInfo.ExpectedReceivedAmountThe amount the recipient is expected to receive, in info.destination_assetinfo.destination_assetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetInfo.DestinationAssetInfo.DestinationAsset base units (sats for Bitcoin).
info.destination_assetinfo.destination_assetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetinfo.destinationAssetInfo.DestinationAssetInfo.DestinationAssetThe asset the recipient receives, e.g. USDC, USDB or BTC.
info.token_identifierinfo.token_identifierinfo.tokenIdentifierinfo.tokenIdentifierinfo.tokenIdentifierinfo.tokenIdentifierinfo.tokenIdentifierInfo.TokenIdentifierInfo.TokenIdentifierThe Spark token identifier when the recipient receives a Spark token such as USDB.
info.service_fee_amountinfo.service_fee_amountinfo.serviceFeeAmountinfo.serviceFeeAmountinfo.serviceFeeAmountinfo.serviceFeeAmountinfo.serviceFeeAmountInfo.ServiceFeeAmountInfo.ServiceFeeAmountProvider fee, including your partner fee if you set one, in info.service_fee_assetinfo.service_fee_assetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetInfo.ServiceFeeAssetInfo.ServiceFeeAsset units.
info.service_fee_assetinfo.service_fee_assetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetInfo.ServiceFeeAssetInfo.ServiceFeeAssetDenomination of the fee. Absent means the fee is in sats.
info.service_fee_asset_decimalsinfo.service_fee_asset_decimalsinfo.serviceFeeAssetDecimalsinfo.serviceFeeAssetDecimalsinfo.serviceFeeAssetDecimalsinfo.serviceFeeAssetDecimalsinfo.serviceFeeAssetDecimalsInfo.ServiceFeeAssetDecimalsInfo.ServiceFeeAssetDecimalsDecimals of info.service_fee_assetinfo.service_fee_assetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetinfo.serviceFeeAssetInfo.ServiceFeeAssetInfo.ServiceFeeAsset, for formatting the fee. Absent when the fee is in sats or the provider did not report them.
info.expires_atinfo.expires_atinfo.expiresAtinfo.expiresAtinfo.expiresAtinfo.expiresAtinfo.expiresAtInfo.ExpiresAtInfo.ExpiresAtQuote expiry, in seconds since the Unix epoch. Create the bridge again for a fresh quote if it lapses before the payer pays.

Tracking a bridge

Read a bridge's status with get_bridge_statusget_bridge_statusgetBridgeStatusgetBridgeStatusgetBridgeStatusgetBridgeStatusgetBridgeStatusGetBridgeStatusGetBridgeStatus, passing the bridge_idbridge_idbridgeIdbridgeIdbridgeIdbridgeIdbridgeIdBridgeIdBridgeId and status_tokenstatus_tokenstatusTokenstatusTokenstatusTokenstatusTokenstatusTokenStatusTokenStatusToken that create_bridgecreate_bridgecreateBridgecreateBridgecreateBridgecreateBridgecreateBridgeCreateBridgeCreateBridge returned.

Rust
let response = client
    .get_bridge_status(GetBridgeStatusRequest {
        bridge_id,
        status_token,
    })
    .await?;
match response.status {
    BridgeStatus::Completed => info!("Delivered {:?}", response.amount_out),
    BridgeStatus::Refunded | BridgeStatus::Failed | BridgeStatus::Expired => {
        info!("Not delivered: {:?}", response.status)
    }
    _ => info!("Not final yet: {:?}", response.status),
}
Swift
let response = try await client.getBridgeStatus(
    request: GetBridgeStatusRequest(bridgeId: bridgeId, statusToken: statusToken))
switch response.status {
case .completed:
    print("Delivered \(response.amountOut.map { "\($0)" } ?? "unknown")")
case .refunded, .failed, .expired:
    print("Not delivered: \(response.status)")
default:
    print("Not final yet: \(response.status)")
}
Kotlin
val response = client.getBridgeStatus(
    GetBridgeStatusRequest(bridgeId = bridgeId, statusToken = statusToken)
)
when (response.status) {
    BridgeStatus.COMPLETED -> {
        // Log.v("Breez", "Delivered ${response.amountOut}")
    }
    BridgeStatus.REFUNDED, BridgeStatus.FAILED, BridgeStatus.EXPIRED -> {
        // Log.v("Breez", "Not delivered: ${response.status}")
    }
    else -> {
        // Log.v("Breez", "Not final yet: ${response.status}")
    }
}
C#
var response = await client.GetBridgeStatus(
    request: new GetBridgeStatusRequest(bridgeId: bridgeId, statusToken: statusToken)
);
switch (response.status)
{
    case BridgeStatus.Completed:
        Console.WriteLine($"Delivered {response.amountOut}");
        break;
    case BridgeStatus.Refunded:
    case BridgeStatus.Failed:
    case BridgeStatus.Expired:
        Console.WriteLine($"Not delivered: {response.status}");
        break;
    default:
        Console.WriteLine($"Not final yet: {response.status}");
        break;
}
Javascript
const response = await client.getBridgeStatus({ bridgeId, statusToken })
switch (response.status) {
  case 'completed': {
    console.log(`Delivered ${response.amountOut ?? 'unknown'}`)
    break
  }
  case 'refunded':
  case 'failed':
  case 'expired': {
    console.log(`Not delivered: ${response.status}`)
    break
  }
  default: {
    console.log(`Not final yet: ${response.status}`)
  }
}
React Native
const response = await client.getBridgeStatus({ bridgeId, statusToken })
switch (response.status) {
  case BridgeStatus.Completed:
    console.log(`Delivered ${response.amountOut ?? 'unknown'}`)
    break
  case BridgeStatus.Refunded:
  case BridgeStatus.Failed:
  case BridgeStatus.Expired:
    console.log(`Not delivered: ${BridgeStatus[response.status]}`)
    break
  default:
    console.log(`Not final yet: ${BridgeStatus[response.status]}`)
}
Flutter
final response = await client.getBridgeStatus(
  request: GetBridgeStatusRequest(
    bridgeId: bridgeId,
    statusToken: statusToken,
  ),
);
switch (response.status) {
  case BridgeStatus.completed:
    print("Delivered ${response.amountOut}");
    break;
  case BridgeStatus.refunded:
  case BridgeStatus.failed:
  case BridgeStatus.expired:
    print("Not delivered: ${response.status}");
    break;
  default:
    print("Not final yet: ${response.status}");
}
Python
try:
    response = await client.get_bridge_status(
        request=GetBridgeStatusRequest(
            bridge_id=bridge_id, status_token=status_token
        )
    )
except Exception as error:
    logging.error(error)
    raise
status = response.status
if status == BridgeStatus.COMPLETED:
    logging.debug(f"Delivered {response.amount_out}")
elif status in (BridgeStatus.REFUNDED, BridgeStatus.FAILED, BridgeStatus.EXPIRED):
    logging.debug(f"Not delivered: {status}")
else:
    logging.debug(f"Not final yet: {status}")
Go
response, err := client.GetBridgeStatus(breez_sdk_spark.GetBridgeStatusRequest{
	BridgeId:    bridgeId,
	StatusToken: statusToken,
})
if err != nil {
	return err
}
switch response.Status {
case breez_sdk_spark.BridgeStatusCompleted:
	if response.AmountOut != nil {
		log.Printf("Delivered %v", *response.AmountOut)
	}
case breez_sdk_spark.BridgeStatusRefunded,
	breez_sdk_spark.BridgeStatusFailed,
	breez_sdk_spark.BridgeStatusExpired:
	log.Printf("Not delivered: %v", response.Status)
default:
	log.Printf("Not final yet: %v", response.Status)
}
StatusMeaning
BridgeStatus::CreatedBridgeStatus.CREATEDBridgeStatus.createdBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatusCreatedBridgeStatus.CreatedThe bridge was created, and the payer hasn't paid yet. An unpaid bridge stays BridgeStatus::CreatedBridgeStatus.CREATEDBridgeStatus.createdBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatus.CreatedBridgeStatusCreatedBridgeStatus.Created after its expires_atexpires_atexpiresAtexpiresAtexpiresAtexpiresAtexpiresAtExpiresAtExpiresAt. A late deposit on another chain may still be accepted at a new price. Stop polling when you no longer expect a payment.
BridgeStatus::PendingBridgeStatus.PENDINGBridgeStatus.pendingBridgeStatus.PendingBridgeStatus.PendingBridgeStatus.PendingBridgeStatus.PendingBridgeStatusPendingBridgeStatus.PendingThe provider is processing the payment, from confirming the deposit to paying the recipient. provider_statusprovider_statusproviderStatusproviderStatusproviderStatusproviderStatusproviderStatusProviderStatusProviderStatus gives the stage.
BridgeStatus::RefundingBridgeStatus.REFUNDINGBridgeStatus.refundingBridgeStatus.RefundingBridgeStatus.RefundingBridgeStatus.RefundingBridgeStatus.RefundingBridgeStatusRefundingBridgeStatus.RefundingThe recipient can't be paid, and the payment is being refunded.
BridgeStatus::CompletedBridgeStatus.COMPLETEDBridgeStatus.completedBridgeStatus.CompletedBridgeStatus.CompletedBridgeStatus.CompletedBridgeStatus.CompletedBridgeStatusCompletedBridgeStatus.CompletedThe recipient was paid. amount_outamount_outamountOutamountOutamountOutamountOutamountOutAmountOutAmountOut and delivery_tx_hashdelivery_tx_hashdeliveryTxHashdeliveryTxHashdeliveryTxHashdeliveryTxHashdeliveryTxHashDeliveryTxHashDeliveryTxHash record the delivery.
BridgeStatus::RefundedBridgeStatus.REFUNDEDBridgeStatus.refundedBridgeStatus.RefundedBridgeStatus.RefundedBridgeStatus.RefundedBridgeStatus.RefundedBridgeStatusRefundedBridgeStatus.RefundedThe payment was refunded to the refund_addressrefund_addressrefundAddressrefundAddressrefundAddressrefundAddressrefundAddressRefundAddressRefundAddress.
BridgeStatus::FailedBridgeStatus.FAILEDBridgeStatus.failedBridgeStatus.FailedBridgeStatus.FailedBridgeStatus.FailedBridgeStatus.FailedBridgeStatusFailedBridgeStatus.FailedThe bridge failed. error_codeerror_codeerrorCodeerrorCodeerrorCodeerrorCodeerrorCodeErrorCodeErrorCode gives the reason.
BridgeStatus::ExpiredBridgeStatus.EXPIREDBridgeStatus.expiredBridgeStatus.ExpiredBridgeStatus.ExpiredBridgeStatus.ExpiredBridgeStatus.ExpiredBridgeStatusExpiredBridgeStatus.ExpiredThe provider's order expired without a payment.

Limitations

  • Mainnet only. The cross-chain provider operates against live networks.
  • Polling only. Bridges send no events. Look the status up when you need it.