Sample Navigation

Code demonstrating how to navigate to the SDK view with SwiftUI or UIKit

SwiftUI - Navigation Destination

import SwiftUI

struct ContentView: View {
    @State private var viewModel = ViewModel()
    
    var body: some View {
        NavigationStack(path: $viewModel.path) {
            Button("ReadyRemit SDK v10.0.0") {
                viewModel.showReadyRemitSDK()
            }
            .navigationDestination(for: NavigationItem.self) {
                AnyView($0.view)
            }
        }
    }
}

#Preview {
    ContentView()
}
import ReadyRemitSDK
import SwiftUI

extension ContentView {
    struct NavigationItem: Identifiable {
        let id = UUID()
        let view: any View
    }

    @Observable
    class ViewModel {
        var path: NavigationPath = .init()
        
        func showReadyRemitSDK() {
            ReadyRemit.shared.startSDK(
                fetchAccessTokenDetails: fetchAccessTokenDetails,
                verifyFundsAndCreateTransfer: verifyFundsAndCreateTransfer,
            ) { [weak self] readyRemitSDKView in
                guard let self else { return }
                self.path.append(NavigationItem(view: readyRemitSDKView))
            }
        }

        private func fetchAccessTokenDetails() async throws -> AccessTokenDetails {
            Task {
                guard let url = URL(string: "https://example.com/v1/oauth/token") else {
                    throw URLError(.badURL)
                }
                var urlRequest = URLRequest(url: url)
                urlRequest.httpMethod = "POST"
                let (data, urlResponse) = try await URLSession.shared.data(for: urlRequest)
                guard let httpURLResponse = urlResponse as? HTTPURLResponse else {
                    throw URLError(.badServerResponse)
                }
                switch httpURLResponse.statusCode {
                case 200...299:
                    // CreateAccessTokenDetailsResponse must conform to AccessTokenDetails
                    return try JSONDecoder().decode(CreateAccessTokenDetailsResponse.self, from: data)
                default:
                    throw CustomError.unsuccessfulResponse
                }
            }
        }
      
        private func verifyFundsAndCreateTransfer(
            transferRequest: ReadyRemit.TransferRequest
        ) async throws(ReadyRemitError) -> TransferDetails {
            Task {
                guard let url = URL(string: "https://example.com/v1/verifyFundsAndCreateTransfer") else {
                    throw URLError(.badURL)
                }
                var urlRequest = URLRequest(url: url)
                urlRequest.httpMethod = "POST"
                urlRequest.httpBody = try JSONEncoder().encode(transferRequest)
                let (data, urlResponse) = try await URLSession.shared.data(for: urlRequest)
                guard let httpURLResponse = urlResponse as? HTTPURLResponse else {
                    throw URLError(.badServerResponse)
                }
                switch httpURLResponse.statusCode {
                case 200...299:
                    // CreateTransferDetailsResponse must conform to TransferDetails
                    return try JSONDecoder().decode(CreateTransferDetailsResponse.self, from: data)
                default:
                    throw ReadyRemitError(code: .none, message: "Insufficient Funds")
                }
            }
        }
    }
}

SwiftUI - Sheet

import SwiftUI

struct ContentView: View {
    @State private var viewModel = ViewModel()
    
    var body: some View {
        NavigationStack(path: $viewModel.path) {
            Button("ReadyRemit SDK v10.0.0") {
                viewModel.showReadyRemitSDK()
            }
            .sheet(item: $viewModel.readyRemitSheetItem) {
                AnyView($0.view)
            }
        }
    }
}

#Preview {
    ContentView()
}
import ReadyRemitSDK
import SwiftUI

extension ContentView {
    struct SheetItem: Identifiable {
        let id = UUID()
        let view: any View
    }

    @Observable
    class ViewModel {
        var path: NavigationPath = .init()
        var readyRemitSheetItem: SheetItem?
        
        func showReadyRemitSDK() {
            ReadyRemit.shared.startSDK(
                fetchAccessTokenDetails: fetchAccessTokenDetails,
                verifyFundsAndCreateTransfer: verifyFundsAndCreateTransfer,
            ) { [weak self] readyRemitSDKView in
                guard let self else { return }
                self.readyRemitSheetItem = .init(view: readyRemitSDKView)
            }
        }

        private func fetchAccessTokenDetails() async throws -> AccessTokenDetails {
            Task {
                guard let url = URL(string: "https://example.com/v1/oauth/token") else {
                    throw URLError(.badURL)
                }
                var urlRequest = URLRequest(url: url)
                urlRequest.httpMethod = "POST"
                let (data, urlResponse) = try await URLSession.shared.data(for: urlRequest)
                guard let httpURLResponse = urlResponse as? HTTPURLResponse else {
                    throw URLError(.badServerResponse)
                }
                switch httpURLResponse.statusCode {
                case 200...299:
                    // CreateAccessTokenDetailsResponse must conform to AccessTokenDetails
                    return try JSONDecoder().decode(CreateAccessTokenDetailsResponse.self, from: data)
                default:
                    throw CustomError.unsuccessfulResponse
                }
            }
        }
      
        private func verifyFundsAndCreateTransfer(
            transferRequest: ReadyRemit.TransferRequest
        ) async throws(ReadyRemitError) -> TransferDetails {
            Task {
                guard let url = URL(string: "https://example.com/v1/verifyFundsAndCreateTransfer") else {
                    throw URLError(.badURL)
                }
                var urlRequest = URLRequest(url: url)
                urlRequest.httpMethod = "POST"
                urlRequest.httpBody = try JSONEncoder().encode(transferRequest)
                let (data, urlResponse) = try await URLSession.shared.data(for: urlRequest)
                guard let httpURLResponse = urlResponse as? HTTPURLResponse else {
                    throw URLError(.badServerResponse)
                }
                switch httpURLResponse.statusCode {
                case 200...299:
                    // CreateTransferDetailsResponse must conform to TransferDetails
                    return try JSONDecoder().decode(CreateTransferDetailsResponse.self, from: data)
                default:
                    throw ReadyRemitError(code: .none, message: "Insufficient Funds")
                }
            }
        }
    }
}

UIKit - Push View Controller


UIKit - Present View Controller