Bitcoin real-time market application practice [Swift code]

In this article, we will learn how to use websocket to develop a Swift application that can receive and display Bitcoin / Bitcoin prices in real time.

Let's take a look at our final results:

Bitcoin development links:

1. Creating WebSocket with URLSession

With the help of URLSession WebSocket task, it is very easy to create WebSockets with URLSession. The following describes the five core operations of a WebSocket connection.

First, open connection:

let urlSession = URLSession(configuration: .default)
let webSocketTask = urlSession.webSocketTask(with: "wss://ws.finnhub.io?token=XYZ")
webSocketTask.resume()

Second, send string or data

webSocketTask.send(.string("Hello")){error in ...}

Third, receive the response result message

webSocketTask.receive{result in  ...}

4th, disconnect

webSocketTask.cancel(with: .goingAway, reason: nil)

Fifth, we can use the ping/pong mechanism to ensure that the connection remains active:

webSocketTask?.sendPing { (error) in ... }

2. Implementation of bitcoin real-time market interface based on SwiftUI + WebSocket

First to this website Generate an API KEY that can access bitcoin quotes:

The following SwiftUI view contains an SF symbol image and a text box that shows the real-time price of bitcoin:

import SwiftUI
import Combine
import Foundation

struct ContentView: View {
    
    @ObservedObject var service = WebSocketService()
    
    var body: some View {
        
        VStack{
            
            Image(systemName: "bitcoinsign.circle.fill")
                .font(.system(size: 150))
                .foregroundColor(Color(red: 247 / 255, green: 142 / 255, blue: 26 / 255))
                .padding()
            
            Text("USD")
                .font(.largeTitle)
                .padding()
            
            Text(service.priceResult)
                .font(.system(size: 60))
            
        }.onAppear {
            self.service.connect()
        }
    }
}

priceResult needs to be published from the ObservableObject class -- it can be found in WebSocketService.swift below See:

class WebSocketService : ObservableObject {
  
    private let urlSession = URLSession(configuration: .default)
    private var webSocketTask: URLSessionWebSocketTask?
    
    private let baseURL = URL(string: "wss://ws.finnhub.io?token=XYZ")!
    
    let didChange = PassthroughSubject<Void, Never>()
    @Published var price: String = ""
    
    private var cancellable: AnyCancellable? = nil
    
    var priceResult: String = "" {
        didSet {
            didChange.send()
        }
    }

    init() {
        cancellable = AnyCancellable($price
            .debounce(for: 0.5, scheduler: DispatchQueue.main)
            .removeDuplicates()
            .assign(to: \.priceResult, on: self))
        
    }
}

In the above code, we defined some properties and established the subscription in the init method. You need to replace XYZ with your own API KEY.

It is important to use operators on Publisher. We used Debounce to reduce the frequency of real-time updates and removedupdates to eliminate duplicate values.

To manually send changes to the SwiftUI view, you can trigger the didChange.send() method when the priceResult property is updated.

Other codes for constructing WebSocketService class of WebSocket URLSession are as follows:

class WebSocketService : ObservableObject {

func connect() {
        
        stop()
        webSocketTask = urlSession.webSocketTask(with: baseURL)
        webSocketTask?.resume()
        
        sendMessage()
        receiveMessage()
    }

    func stop() {
        webSocketTask?.cancel(with: .goingAway, reason: nil)
    }
    
    private func sendMessage()
    {
        let string = "{\"type\":\"subscribe\",\"symbol\":\"BINANCE:BTCUSDT\"}"
        
        let message = URLSessionWebSocketTask.Message.string(string)
        webSocketTask?.send(message) { error in
            if let error = error {
                print("WebSocket couldn't send message because: \(error)")
            }
        }
    }
    
    private func receiveMessage() {
        webSocketTask?.receive {[weak self] result in
            
            switch result {
            case .failure(let error):
                print("Error in receiving message: \(error)")
            case .success(.string(let str)):
                
                do {
                    let decoder = JSONDecoder()
                    let result = try decoder.decode(APIResponse.self, from: Data(str.utf8))
                    DispatchQueue.main.async{
                        self?.price = "\(result.data[0].p)"
                    }
                    
                } catch  {
                    print("error is \(error.localizedDescription)")
                }
                
                self?.receiveMessage()
                
            default:
                print("default")
            }
        }
    }
}

The following structure model is used to decode the response results of the API:

struct APIResponse: Codable {
    var data: [PriceData]
    var type : String
    
    private enum CodingKeys: String, CodingKey {
        case data, type
    }
}
struct PriceData: Codable{
    
    public var p: Float
    
    private enum CodingKeys: String, CodingKey {
        case p
    }
}

Now run the app using the WatchOS emulator, which looks like this:

Original link: Using Swift to develop bitcoin real-time market application huizhi.com

Tags: Blockchain Swift PHP Java emulator

Posted on Wed, 19 Feb 2020 20:53:21 -0500 by OmegaB