Skip to content
This repository has been archived by the owner on Jul 10, 2020. It is now read-only.

Implement auto generation for blockchain provider for Swift #110

Open
vikmeup opened this issue Sep 6, 2019 · 1 comment
Open

Implement auto generation for blockchain provider for Swift #110

vikmeup opened this issue Sep 6, 2019 · 1 comment

Comments

@vikmeup
Copy link
Contributor

vikmeup commented Sep 6, 2019

Define a protocol that could be described in JSON structure to automate generation of the provider and all the models. Based on your JSON code, you should be able to generate current Swift code.

It has to be extendable and support many formats for models and routes and use Moya provider as networking layer.

Example in TypeScript: https://github.com/trustwallet/web-core/blob/master/packages/rpc/src/cosmos/CosmosRPC.ts

Additional:

  • Use any language/tools that's most suitable for this problem.
  • In the future current code will require to generate templates to different languages in Java/Javascript and etc plan accordingly

Provider:

import Foundation
import Moya

enum WavesRPC {
    case balance(address: String)
    case transaction(String)
    case broadcast(Data)
    case nodeInfo
}

extension WavesRPC: TargetType {
    var baseURL: URL {
        return "https://waves-url.com"
    }

    var path: String {
        switch self {
        case .balance(let address):
            return "/addresses/balance/\(address)/0"
        case .transaction(let hash):
            return "/transactions/info/\(hash)"
        case .broadcast:
            return "/transactions/broadcast"
        case .nodeInfo:
            return "/node/status"
        }
    }

    var method: Moya.Method {
        switch self {
        case .balance, .transaction, .nodeInfo:
            return .get
        case .broadcast:
            return .post
        }
    }

    var sampleData: Data {
        return Data()
    }

    var task: Task {
        switch self {
        case .balance, .transaction, .nodeInfo:
            return .requestPlain
        case .broadcast(let data):
            return Task.requestData(data)
        }
    }

    var headers: [String: String]? {
        return [
            "content-type": "application/json",
        ]
    }
}

Models

struct WavesBalance: Codable {
    let balance: Int64
}

struct WavesSentTransaction: Codable {
    let id: String
}

struct WavesRPCError: Codable {
    let error: Int
    let message: String
}

struct WavesTransactionInfo: Codable {
    let height: Int64
}
@vikmeup vikmeup changed the title Implement auto generation for blockchain provider for Swift and TypeScript Implement auto generation for blockchain provider for Swift Sep 7, 2019
@vikmeup
Copy link
Contributor Author

vikmeup commented Sep 29, 2019

Ripple:

enum RippleRPC {
    case account(address: String)
    case broadcast(hex: String)
    case transaction(ID: String)
    case serverState
}

extension RippleRPC {
    var methodType: String {
        switch self {
        case .account: return "account_info"
        case .broadcast: return "submit"
        case .transaction: return "tx"
        case .serverState: return "server_state"
        }
    }
}

extension RippleRPC: TargetType {
    var baseURL: URL {
        return RPCServer(.ripple).rpcURL
    }

    var path: String {
        return "/"
    }

    var method: Moya.Method {
        return Moya.Method.post
    }

    var sampleData: Data {
        return Data()
    }

    var task: Task {
        let params: [String: Any]
        switch self {
        case .account(let address):
            params = [
                "account": address,
                "strict": true,
                "ledger_index": "current",
                "queue": true,
            ]
        case .serverState:
            params = [:]
        case .broadcast(let hex):
            params = [
                "tx_blob": hex,
            ]
        case .transaction(let ID):
            params = [
                "transaction": ID,
            ]
        }
        let parameters: [String: Any] = [
            "method": methodType,
            "params": [params],
        ]
        return .requestParameters(parameters: parameters, encoding: JSONEncoding())
    }

    var headers: [String: String]? {
        return [
            "accept": "application/json",
            "content-type": "application/json",
        ]
    }
}

Models:

struct JSONResult <T: Codable>: Codable {
    let result: T
}

struct RippleAccount: Codable {
    let data: RippleAccountData

    private enum CodingKeys: String, CodingKey {
        case data = "account_data"
    }
}

struct RippleAccountData: Codable {
    let Balance: String
    let Sequence: Int64
}

struct RippleLedger: Codable {
    let index: UInt64

    private enum CodingKeys: String, CodingKey {
        case index = "ledger_index"
    }
}

struct RippleJSONTransaction: Codable {
    let hash: String
}

struct RippleSentTransaction: Codable {
    let code: Int
    let message: String
    let tx: RippleJSONTransaction

    private enum CodingKeys: String, CodingKey {
        case code = "engine_result_code"
        case message = "engine_result_message"
        case tx = "tx_json"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.code = try container.decode(Int.self, forKey: .code)
        self.message = try container.decode(String.self, forKey: .message)
        if self.code != 0 {
            throw JSONRPCError(code: self.code, message: self.message)
        }
        self.tx = try container.decode(RippleJSONTransaction.self, forKey: .tx)
    }
}

struct RippleTransaction: Codable {
    let validated: Bool
}

struct RippleServerState: Codable {
    struct State: Codable {
        struct Ledger: Codable {
            let base_fee: Int64
        }
        let load_base: Int64
        let load_factor: Int64
        let validated_ledger: Ledger
    }
    let state: State
}

extension RippleServerState {
    var fee: BigInt {
        // From https://xrpl.org/transaction-cost.html#querying-the-transaction-cost, Current Transaction Cost in
        // Drops = (base_fee × load_factor) ÷ load_base

        return BigInt(state.validated_ledger.base_fee * state.load_factor) / BigInt(state.load_base)
    }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant