Core Library for XYO Network in Swift.


License
LGPL-3.0
Install
pod try sdk-core-swift

Documentation

logo

sdk-core-swift

Maintainability Test Coverage Carthage compatible

Table of Contents

NOTE The latest version of this SDK includes the objectmodel as previously imported from sdk-objectmodel-swift.

This README.md document is an overview of the common methods that you may need when integrating the XYO Core SDK into your project.

For an easy to use entry integration guide, take a look at our Sample App Guide

A library to preform all core XYO Network functions. This includes creating an origin chain, maintaining an origin chain, negotiations for talking to other nodes, and other basic functionality. The library has heavily abstracted modules so that all operations will work with any crypto, storage, networking, ect.

The XYO protocol for creating origin-blocks is specified in the XYO Yellow Paper. In it, it describes the behavior of how a node on the XYO network should create Bound Witnesses. Note, the behavior is not coupled with any particular technology constraints around transport layers, cryptographic algorithms, or hashing algorithms.

Getting Started

CocoaPods

Note that current CocoaPods support is for iOS only

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.6.0.beta.2+ is required.

To integrate into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'sdk-core-swift', '3.1.7'
end

Then, run the following command:

$ pod install

For a test run

pod try sdk-core-swift

Origin Chain

The most common interface to this library through creating an origin chain creator object. Through an origin chain creator object one can create and maintain an origin chain.

// this object will be used to hash items within the node
let hasher = XyoSha256()

// this is used as a key value store 
let storage = XyoInMemoryStorage()

// this is used as a place to store all of the bound witnesses/origin blocks
let chainRepo = XyoStorageOriginBlockRepository(storage: storage, hasher: hasher)

// this is used to save the state of the node (keys, index, previous hash)
let stateRepo = XyoStorageOriginStateRepository(storage: storage)

// this holds the state and the chain repository together
let configuration = XyoRepositoryConfiguration(originState: stateRepo, originBlock: chainRepo)

// the node to interface with creating an origin chain
let node = XyoOriginChainCreator(hasher: hasher, repositoryConfiguration: configuration)

After creating a node, it is standard to add a signer, and create a genesis block.

// creates a signer with a random private key
let signer = XyoSecp256k1Signer()
    
// adds the signer to the node
node.originState.addSigner(signer: signer)

// creates a origin block with its self (genesis block if this is the first block you make)
try node.selfSignOriginChain()

After creating a genesis block, your origin chain has officially started. Remember, all of the state is stored in the state repository (XyoOriginChainStateRepository) and the block repository (XyoOriginBlockRepository) that are constructed with the node. Both repositories are very high level and can be implemented for one's needs. Out of the box, this library comes with an implementation for key value store databases (XyoStorageOriginBlockRepository) and (XyoStorageOriginChainStateRepository).

The XyoStorageProvider interface defines the methods for a simple key value store. There is a default implementation of an in memory key value store that comes with this library (XyoInMemoryStorage).

Creating Origin Blocks

After a node has been created, it can be used to create origin blocks with other nodes. The process of talking to other nodes has been abstracted through use of a pipe (e.g. tcp, ble, memory) that handles all of the transport logic. This interface is defined as XyoNetworkPipe. This library ships with a memory pipe, and a tcp pipe.

Using a tcp pipe

 // this defines who to create a tcp pipe with
let tcpPeer = XyoTcpPeer(ip: "myarchivist.com", port: 11000)

// prepares a socket tcp to communicate with the other node
let socket = XyoTcpSocket.create(peer: tcpPeer)

// wraps the socket to comply to the pipe interface
let pipe = XyoTcpSocketPipe(socket: socket, initiationData: nil)

// wraps the pipe to preform standard communications
let handler = XyoNetworkHandler(pipe: pipe)

node.boundWitness(handler: handler, procedureCatalogue: XyoProcedureCatalogue) { (boundWitness, error) in
    
}

Using a memory pipe

let pipeOne = XyoMemoryPipe()
let pipeTwo = XyoMemoryPipe()

pipeOne.other = pipeTwo
pipeTwo.other = pipeOne

let handlerOne = XyoNetworkHandler(pipe: pipeOne)
let handlerTwo = XyoNetworkHandler(pipe: pipeTwo)

nodeOne.boundWitness(handler: handlerOne, procedureCatalogue: TestInteractionCatalogueCaseOne()) { (result, error) in
    // this should complete first
}

nodeTwo.boundWitness(handler: handlerTwo, procedureCatalogue: TestInteractionCatalogueCaseOne()) { (result, error) in
    // this should complete second
}

More example and bridge interactions can be found here

Bluetooth

Bluetooth swift pipes for client and server can be found here.

Other

Other network pipes can be implemented as long as they follow the interface defined here.

Bound Witness

Adding custom data to bound witnesses.

To add custom data to a bound witnesses, a XyoHeuristicGetter can be created:

public struct MyCustomData: XyoHeuristicGetter {
    public func getHeuristic() -> XyoObjectStructure? {
        if (conditionIsMet) {
            let myData = getDataSomehow()
            return myData
        }
        
        return nil
    }
}

After the getter has been created, it can be added to a node by calling:

 let myDataForBoundWitness = MyCustomData()
 node.addHeuristic (key: "MyData", getter : myDataForBoundWitness)

Node Listener

Adding a listener to a node

 struct MyListener : XyoNodeListener {
    /// This function will be called every time a bound witness has started
    func onBoundWitnessStart() {
        // update UI
    }
    
    /// This function is called when a bound witness starts, but fails due to an error
    func onBoundWitnessEndFailure() {
        // update UI
    }
    
    /// This function is called when the node discovers a new origin block, this is typicaly its new blocks
    /// that it is creating, but will be called when a bridge discovers new blocks.
    /// - Parameter boundWitness: The boundwitness just discovered
    func onBoundWitnessDiscovered(boundWitness : XyoBoundWitness) {
        // update UI
    }
    
    /// This function is called every time a bound witness starts and complets successfully.
    /// - Parameter boundWitness: The boundwitness just completed
    func onBoundWitnessEndSuccess(boundWitness : XyoBoundWitness) {
        // update UI
    }
}

You may add a listener to a node by adding the following:

  let listener = MyListener()
  myNode.addListener(key: "MyListener", listener : listener)
  

TCP Node

TCP Node Example

The following code is an example of a node that bound witnesses with a server 10 times.

let storage = XyoInMemoryStorage()
let blocks = XyoStrageProviderOriginBlockRepository(storageProvider: storage,
                                                    hasher: XyoSha256())
let state = XyoStorageOriginChainStateRepository(storage: storage)
let conf = XyoRepositoryConfiguration(originState: state, originBlock: blocks)
let node = XyoRelayNode(hasher: XyoSha256(),
                        repositoryConfiguration: conf,
                        queueRepository: XyoStorageBridgeQueueRepository(storage: storage))

node.originState.addSigner(signer: XyoSecp256k1Signer())

for i in 0..9 {
    let peer = XyoTcpPeer(ip: "alpha-peers.xyo.network", port: 11000)
    let socket = XyoTcpSocket.create(peer: peer)
    let pipe = XyoTcpSocketPipe(socket: socket, initiationData: nil)
    let handler = XyoNetworkHandler(pipe: pipe)

    let data = UInt32(XyoProcedureCatalogueFlags.TAKE_ORIGIN_CHAIN | XyoProcedureCatalogueFlags.GIVE_ORIGIN_CHAIN)
    node.boundWitness(handler: handler, procedureCatalogue: XyoFlagProcedureCatalogue(forOther: data, withOther: data)) { (result, error) in

    }
}

Maintainers

  • Carter Harrison
  • Arie Trouw
  • Kevin Weiler

License

See the LICENSE file for license details.

Credits

Made with 🔥and ❄️ by XYO