InteractiveService
public final class InteractiveService : @unchecked Sendable
Implements SEP-0024 - Hosted Deposit and Withdrawal.
This class provides an interactive flow for deposits and withdrawals where the anchor service requires user interaction through a web interface. The user completes KYC and other requirements in the anchor’s hosted web application, then the anchor handles the on/off-ramp process.
SEP-0024 enables a standardized way for wallets to integrate with anchor services for fiat on/off-ramps. The anchor hosts a web interface where users can provide additional information like KYC data, bank account details, or complete email verification.
Typical Workflow
- Initialize Service: Create InteractiveService from anchor’s domain
- Check Capabilities: Query /info endpoint to see supported assets and features
- Authenticate: Obtain JWT token using SEP-0010 WebAuthenticator
- Initiate Flow: Start deposit or withdraw, receive interactive URL
- User Interaction: Open URL in webview/browser for user to complete requirements
- Monitor Status: Poll transaction endpoint to track progress
Example: Complete Deposit Flow
// Step 1: Initialize service from domain
let serviceResult = await InteractiveService.forDomain(
domain: "https://testanchor.stellar.org"
)
guard case .success(let service) = serviceResult else { return }
// Step 2: Check what assets are supported
let infoResult = await service.info()
guard case .success(let info) = infoResult else { return }
print("Supported assets: \(info.deposit.keys)")
// Step 3: Get JWT token (using SEP-0010)
let jwtToken = "..." // Obtained from WebAuthenticator
// Step 4: Initiate deposit
let depositRequest = Sep24DepositRequest(
assetCode: "USDC",
account: userAccountId,
jwt: jwtToken
)
let depositResult = await service.deposit(request: depositRequest)
switch depositResult {
case .success(let response):
// Step 5: Open interactive URL in webview
print("Open this URL: \(response.url)")
// User completes KYC and provides deposit information
// Step 6: Monitor transaction status
let txRequest = Sep24TransactionRequest(
id: response.id,
jwt: jwtToken
)
let statusResult = await service.getTransaction(request: txRequest)
// Check response.transaction.status
case .failure(let error):
print("Deposit initiation failed: \(error)")
}
Example: Withdraw Flow
let withdrawRequest = Sep24WithdrawRequest(
assetCode: "USDC",
dest: "bank_account",
account: userAccountId,
jwt: jwtToken
)
let result = await service.withdraw(request: withdrawRequest)
switch result {
case .success(let response):
// Open interactive URL
print("Complete withdraw at: \(response.url)")
// User provides bank details and completes verification
// Then sends USDC to the anchor's account
case .failure(let error):
print("Withdraw failed: \(error)")
}
Transaction Status Monitoring
// Poll for transaction status updates
let txRequest = Sep24TransactionRequest(
id: transactionId,
jwt: jwtToken
)
let result = await service.getTransaction(request: txRequest)
if case .success(let response) = result {
switch response.transaction.status {
case "incomplete":
// User needs to complete interactive flow
case "pending_user_transfer_start":
// Waiting for user to send funds
case "pending_anchor":
// Anchor is processing
case "completed":
// Transaction complete
case "error":
// Transaction failed
default:
break
}
}
Fee Information
let feeRequest = Sep24FeeRequest(
operation: "deposit",
assetCode: "USDC",
amount: "100",
jwt: jwtToken
)
let feeResult = await service.fee(request: feeRequest)
if case .success(let feeResponse) = feeResult {
print("Fee: \(feeResponse.fee)")
}
Error Handling
let result = await service.deposit(request: depositRequest)
switch result {
case .success(let response):
// Handle success
case .failure(let error):
switch error {
case .authenticationRequired:
// JWT token missing or expired, re-authenticate with SEP-10
case .anchorError(let message):
// Anchor-specific error (e.g., unsupported asset, amount too large)
case .parsingResponseFailed(let message):
// Response parsing error
case .horizonError(let horizonError):
// Network or HTTP error
}
}
Integration with Other SEPs
SEP-0024 often works together with:
- SEP-0010: Required for authentication (JWT tokens)
- SEP-0012: For standalone KYC (may be handled in interactive flow)
- SEP-0038: For cross-asset swaps during deposit/withdraw
Security Considerations
- Always use HTTPS for production
- Validate JWT tokens are current
- Open interactive URLs in a secure webview
- Monitor transaction status to detect issues
- Handle user cancellations gracefully
See also:
- SEP-0024 Specification
- [WebAuthenticator] for SEP-0010 authentication
- [StellarToml] for service discovery
-
The base URL of the SEP-24 interactive service endpoint for hosted deposit and withdrawal.
Declaration
Swift
public let serviceAddress: String -
Initializes a new InteractiveService instance with the specified SEP-24 transfer server endpoint URL.
Declaration
Swift
public init(serviceAddress: String)Parameters
serviceAddressThe URL of the SEP-24 transfer server (e.g., “https://example.com/sep24”)
-
forDomain(domain:Asynchronous) Creates an InteractiveService instance based on information from the stellar.toml file for a given domain.
Fetches the stellar.toml file from
{domain}/.well-known/stellar.tomland extracts the TRANSFER_SERVER_SEP0024 URL.Declaration
Swift
public static func forDomain(domain: String) async -> InteractiveServiceForDomainEnumParameters
domainThe anchor’s domain including scheme (e.g., “https://testanchor.stellar.org”)
Return Value
InteractiveServiceForDomainEnum with the service instance, or an error
-
info(language:Asynchronous) Get the anchor’s basic info about what their TRANSFER_SERVER_SEP0024 supports to wallets and clients.
Returns information about supported assets, deposit/withdraw features, and fee structures.
Declaration
Swift
public func info(language: String? = nil) async -> Sep24InfoResponseEnumParameters
languageLanguage code specified using ISO 639-1. Description fields in the response should be in this language. Defaults to “en”.
Return Value
Sep24InfoResponseEnum with anchor capabilities, or an error
-
fee(request:Asynchronous) Get the anchor’s reported fee that would be charged for a given deposit or withdraw operation.
This is important to allow an anchor to accurately report fees to a user even when the fee schedule is complex. If a fee can be fully expressed with the fee_fixed, fee_percent or fee_minimum fields in the /info response, then an anchor will not implement this endpoint.
Declaration
Swift
public func fee(request: Sep24FeeRequest) async -> Sep24FeeResponseEnumParameters
requestSep24FeeRequest containing operation type, asset code, amount, and JWT token
Return Value
Sep24FeeResponseEnum with fee amount, or an error
-
deposit(request:Asynchronous) Initiates a SEP-24 deposit transaction, returning an interactive URL for the user to complete KYC and deposit requirements.
The user should be redirected to the returned URL to complete the deposit flow in the anchor’s web interface.
Declaration
Swift
public func deposit(request: Sep24DepositRequest) async -> Sep24InteractiveResponseEnumParameters
requestSep24DepositRequest containing asset code, destination account, and JWT token
Return Value
Sep24InteractiveResponseEnum with interactive URL and transaction ID, or an error
-
withdraw(request:Asynchronous) Initiates a SEP-24 withdrawal transaction, returning an interactive URL for the user to provide withdrawal details and complete verification.
The user should be redirected to the returned URL to complete the withdrawal flow in the anchor’s web interface.
Declaration
Swift
public func withdraw(request: Sep24WithdrawRequest) async -> Sep24InteractiveResponseEnumParameters
requestSep24WithdrawRequest containing asset code, destination type, and JWT token
Return Value
Sep24InteractiveResponseEnum with interactive URL and transaction ID, or an error
-
getTransactions(request:Asynchronous) Retrieves a list of SEP-24 transactions for the authenticated user, filtered by asset code and optional parameters.
Use this to show transaction history or monitor multiple pending transactions.
Declaration
Swift
public func getTransactions(request: Sep24TransactionsRequest) async -> Sep24TransactionsResponseEnumParameters
requestSep24TransactionsRequest containing asset code, filters, pagination options, and JWT token
Return Value
Sep24TransactionsResponseEnum with list of transactions, or an error
-
getTransaction(request:Asynchronous) Retrieves the status and details of a single SEP-24 transaction by ID, Stellar transaction ID, or external transaction ID.
Use this to poll for transaction status updates during the deposit/withdrawal flow.
Declaration
Swift
public func getTransaction(request: Sep24TransactionRequest) async -> Sep24TransactionResponseEnumParameters
requestSep24TransactionRequest containing transaction identifier(s) and JWT token
Return Value
Sep24TransactionResponseEnum with transaction details and status, or an error
View on GitHub
Install in Dash