Skip to content

Commit

Permalink
Merge pull request #40 from XYOracleNetwork/feature/archivist-insert
Browse files Browse the repository at this point in the history
Feature/archivist insert
  • Loading branch information
JoelBCarter authored Nov 12, 2024
2 parents 8e8703f + 1a4ea3c commit 5a3852c
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 80 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ on:
push:
branches:
- main
pull_request:
branches:
- main
# pull_request:
# branches:
# - main

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cSpell.words": ["Alamofire", "keccak", "secp"]
"cSpell.words": ["Alamofire", "keccak", "secp", "unkeyed"]
}
8 changes: 8 additions & 0 deletions Sources/XyoClient/Address/AccountInstance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Foundation

public protocol AccountInstance {
var address: String? { get }
var addressBytes: Data? { get }
var previousHash: String? { get }
func sign(hash: String) throws -> String?
}
21 changes: 17 additions & 4 deletions Sources/XyoClient/Address/XyoAddress.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Foundation
import secp256k1

public class XyoAddress {
public class XyoAddress: AccountInstance {

private var _previousHash: String? = nil
private var _privateKey: secp256k1.Signing.PrivateKey?

public init(_ privateKey: Data? = generateRandomBytes()) {
Expand All @@ -14,6 +15,10 @@ public class XyoAddress {
self.init(privateKey.hexToData())
}

public var previousHash: String? {
return _previousHash
}

public var privateKey: secp256k1.Signing.PrivateKey? {
return _privateKey
}
Expand Down Expand Up @@ -48,6 +53,10 @@ public class XyoAddress {
return bytes.toHex(64)
}

public var address: String? {
return self.addressHex
}

public var addressBytes: Data? {
guard let keccakBytes = keccakBytes else { return nil }
return keccakBytes.subdata(in: 12..<keccakBytes.count)
Expand All @@ -58,11 +67,13 @@ public class XyoAddress {
return bytes.toHex(40)
}

public func sign(_ hash: String) throws -> String? {
public func sign(hash: String) throws -> String? {
let message = hash.hexToData()
guard message != nil else { return nil }
let sig = self.signature(message!)
return sig?.dataRepresentation.toHex()
let ret = sig?.dataRepresentation.toHex()
_previousHash = hash
return ret
}

public func signature(_ hash: Data) -> secp256k1.Signing.ECDSASignature? {
Expand Down Expand Up @@ -91,7 +102,9 @@ public class XyoAddress {
}

let rawRepresentation = Data(
bytes: &signature2.data, count: MemoryLayout.size(ofValue: signature2.data))
bytes: &signature2.data,
count: MemoryLayout.size(ofValue: signature2.data)
)

return try secp256k1.Signing.ECDSASignature(dataRepresentation: rawRepresentation)
} catch {
Expand Down
2 changes: 1 addition & 1 deletion Sources/XyoClient/ApiConfig.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public class XyoApiConfig {
public class ApiConfig {
var apiDomain: String
var token: String?

Expand Down
29 changes: 20 additions & 9 deletions Sources/XyoClient/ArchivistApi/ArchivistApiClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ public struct XyoApiBoundWitnessBody: Encodable {
}

public class XyoArchivistApiClient {
let config: XyoArchivistApiConfig

private static let ArchivistInsertQuerySchema = "network.xyo.query.archivist.insert"
private static let ArchivistInsertQuery: XyoPayload = XyoPayload(ArchivistInsertQuerySchema)

let config: XyoArchivistApiConfig
let queryAccount: AccountInstance
public var authenticated: Bool {
return self.token != nil
}
Expand All @@ -26,27 +30,34 @@ public class XyoArchivistApiClient {
return "\(self.config.apiDomain)/\(self.config.apiModule)"
}

private init(_ config: XyoArchivistApiConfig) {
private init(_ config: XyoArchivistApiConfig, _ account: AccountInstance?) {
self.config = config
self.queryAccount = account ?? XyoAddress()
}

public func insert(payloads: [XyoBoundWitnessJson]) async throws -> XyoBoundWitnessJson {
// TODO: Build query bound witness
public func insert(payloads: [XyoPayload]) async throws -> [XyoPayload] {
// Build QueryBoundWitness
let (bw, signed) = try BoundWitnessBuilder()
.payloads(payloads)
.signer(self.queryAccount)
.query(XyoArchivistApiClient.ArchivistInsertQuery)
.build()

// Perform the request and await the result
let responseData = try await AF.request(
self.url,
method: .post,
parameters: payloads,
parameters: ModuleQueryResult(bw: bw, payloads: signed),
encoder: JSONParameterEncoder.default
)
.validate()
.serializingData()
.value

// Attempt to decode the response data into XyoBoundWitnessJson
let decodedResponse = try JSONDecoder().decode([XyoBoundWitnessJson].self, from: responseData)
// TODO: Return payloads instead once they're deserializable
return decodedResponse[0]
let decodedResponse = try JSONDecoder().decode(ModuleQueryResult.self, from: responseData)

return decodedResponse.payloads
}

public func postBoundWitnesses(
Expand Down Expand Up @@ -98,7 +109,7 @@ public class XyoArchivistApiClient {
}

public static func get(_ config: XyoArchivistApiConfig) -> XyoArchivistApiClient {
return XyoArchivistApiClient(config)
return XyoArchivistApiClient(config, XyoAddress())
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/XyoClient/ArchivistApi/ArchivistApiConfig.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public class XyoArchivistApiConfig: XyoApiConfig {
public class XyoArchivistApiConfig: ApiConfig {
var apiModule: String
public init(_ apiModule: String, _ apiDomain: String, _ token: String? = nil) {
self.apiModule = apiModule
Expand Down
14 changes: 12 additions & 2 deletions Sources/XyoClient/BoundWitness/Body/BoundWitnessBodyJson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,29 @@ public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable, De
case payload_hashes
case payload_schemas
case previous_hashes
case query
case schema
}

public var addresses: [String?] = []
public var payload_hashes: [String] = []
public var payload_schemas: [String] = []
public var previous_hashes: [String?] = []
public var query: String?
public var schema: String

init(
_ addresses: [String?], _ previous_hashes: [String?], _ payload_hashes: [String],
_ payload_schemas: [String]
_ addresses: [String?],
_ previous_hashes: [String?],
_ payload_hashes: [String],
_ payload_schemas: [String],
_ query: String? = nil
) {
self.addresses = addresses
self.payload_hashes = payload_hashes
self.payload_schemas = payload_schemas
self.previous_hashes = previous_hashes
self.query = query
self.schema = "network.xyo.boundwitness"
}

Expand All @@ -36,6 +42,7 @@ public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable, De
payload_hashes = try values.decode([String].self, forKey: .payload_hashes)
payload_schemas = try values.decode([String].self, forKey: .payload_schemas)
previous_hashes = try values.decode([String?].self, forKey: .previous_hashes)
query = try values.decode(String?.self, forKey: .query)
self.schema = "network.xyo.boundwitness"
}

Expand All @@ -44,6 +51,9 @@ public class XyoBoundWitnessBodyJson: XyoBoundWitnessBodyProtocol, Encodable, De
try container.encode(payload_hashes, forKey: .payload_hashes)
try container.encode(payload_schemas, forKey: .payload_schemas)
try container.encode(previous_hashes, forKey: .previous_hashes)
if query != nil {
try container.encode(query, forKey: .query)
}
try container.encode(schema, forKey: .schema)
}

Expand Down
39 changes: 26 additions & 13 deletions Sources/XyoClient/BoundWitness/BoundWitnessBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,37 @@ public enum BoundWitnessBuilderError: Error {
}

public class BoundWitnessBuilder {
private var _witnesses: [XyoAddress?] = []
private var _accounts: [AccountInstance] = []
private var _previous_hashes: [String?] = []
private var _payload_hashes: [String] = []
private var _payload_schemas: [String] = []
private var _payloads: [XyoPayload] = []
private var _query: String? = nil

public init() {
}

public func witness(_ address: XyoAddress, _ previousHash: String? = nil) -> BoundWitnessBuilder {
_witnesses.append(address)
public func signer(_ account: AccountInstance, _ previousHash: String? = nil)
-> BoundWitnessBuilder
{
_accounts.append(account)
_previous_hashes.append(previousHash)
return self
}

public func witnesses(_ witnesses: [XyoWitness]) -> BoundWitnessBuilder {
_witnesses.append(contentsOf: witnesses.map { witness in witness.address })
_previous_hashes.append(contentsOf: witnesses.map { witness in witness.previousHash })
public func signers(_ accounts: [AccountInstance]) -> BoundWitnessBuilder {
_accounts.append(contentsOf: accounts)
_previous_hashes.append(contentsOf: accounts.map { account in account.previousHash })
return self
}

private func hashableFields() -> XyoBoundWitnessBodyJson {
return XyoBoundWitnessBodyJson(
_witnesses.map { witness in witness?.addressHex },
_accounts.map { witness in witness.address },
_previous_hashes,
_payload_hashes,
_payload_schemas
_payload_schemas,
_query
)
}

Expand All @@ -50,24 +54,33 @@ public class BoundWitnessBuilder {
return self
}

public func sign(_ hash: String) throws -> [String?] {
return try self._witnesses.map {
try $0?.sign(hash)
public func query(_ payload: XyoPayload) throws -> BoundWitnessBuilder {
self._query = try payload.hash().toHex()
let _ = try self.payload(payload.schema, payload)
return self
}

public func sign(hash: String) throws -> [String?] {
return try self._accounts.map {
try $0.sign(hash: hash)
}
}

public func build(_ previousHash: String? = nil) throws -> (XyoBoundWitnessJson, [XyoPayload]) {
let bw = XyoBoundWitnessJson()
let hashable = hashableFields()
let hash = try BoundWitnessBuilder.hash(hashable)
bw._signatures = try self.sign(hash)
bw._signatures = try self.sign(hash: hash)
bw._hash = hash
bw._client = "swift"
bw._previous_hash = previousHash
bw.addresses = _witnesses.map { witness in witness?.addressHex! }
bw.addresses = _accounts.map { witness in witness.address }
bw.previous_hashes = _previous_hashes
bw.payload_hashes = _payload_hashes
bw.payload_schemas = _payload_schemas
if _query != nil {
bw.query = _query
}
return (bw, _payloads)
}

Expand Down
5 changes: 5 additions & 0 deletions Sources/XyoClient/BoundWitness/BoundWitnessJson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaPr
case payload_hashes
case payload_schemas
case previous_hashes
case query
case schema
}

public var _client: String?
public var _hash: String?
public var _signatures: [String?]?
public var _previous_hash: String?
public var _query: String?

func encodeMetaFields(_ container: inout KeyedEncodingContainer<CodingKeys>) throws {
try container.encode(_client, forKey: ._client)
Expand All @@ -29,6 +31,9 @@ public class XyoBoundWitnessJson: XyoBoundWitnessBodyJson, XyoBoundWitnessMetaPr
try container.encode(payload_hashes, forKey: .payload_hashes)
try container.encode(payload_schemas, forKey: .payload_schemas)
try container.encode(previous_hashes, forKey: .previous_hashes)
if query != nil {
try container.encode(query, forKey: .query)
}
try container.encode(schema, forKey: .schema)
}

Expand Down
20 changes: 20 additions & 0 deletions Sources/XyoClient/Module/AbstractModule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
open class AbstractModule: Module {

private let _account: XyoAddress

public var account: AccountInstance {
_account
}

public var address: String? {
_account.addressHex
}

public var previousHash: String? {
_account.previousHash
}

public init(account: XyoAddress? = nil) {
self._account = account ?? XyoAddress()
}
}
5 changes: 5 additions & 0 deletions Sources/XyoClient/Module/Module.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public protocol Module {
var address: String? { get }
var account: AccountInstance { get }
var previousHash: String? { get }
}
32 changes: 32 additions & 0 deletions Sources/XyoClient/Module/ModuleQueryResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Foundation

public class ModuleQueryResult: Encodable, Decodable {
var bw: XyoBoundWitnessJson
var payloads: [XyoPayload]
var errors: [XyoPayload]
init(bw: XyoBoundWitnessJson, payloads: [XyoPayload] = [], errors: [XyoPayload] = []) {
self.bw = bw
self.payloads = payloads
self.errors = errors
}
public func encode(to encoder: Encoder) throws {
// Create an unkeyed container for array encoding
var container = encoder.unkeyedContainer()
// Encode `bw` as the first element
try container.encode(bw)
// Encode `payloads` as the second element
try container.encode(payloads)
// Encode `errors` as the third element
try container.encode(errors)
}
public required init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
// Decode elements in the expected order from the array
bw = try container.decode(XyoBoundWitnessJson.self)
// TODO: Decodable Payloads
// payloads = try container.decode([XyoPayload].self)
// errors = try container.decode([XyoPayload].self)
payloads = []
errors = []
}
}
Loading

0 comments on commit 5a3852c

Please sign in to comment.