Integrating Storage and Wallet Functionalities

The page provides instructions on how to integrate storage and wallet functionalities to home page of your App.

Home Directories

The following directories lies inside the xcode project. Here is the xcode screenshot for example:

Description for the directories and files are provided below:

--Home(directory)
--App(directory)
    --ZusExampleApp.swift(file)
    --CreateWalletView.swift(file)
    --HomeView.swift(file)
    --AllocationDetailsView.swift(file)
    --Launch.storyboard(file)
    --WalletDetailsView.swift(file)
    --NetworkDetails.swift(file)
--Model(directory)
    --NetworkConfig.swift(file)
--ViewModel(directory)
    --ZcnCoreManager.swift(file)
    --HomeViewModel.swift(file)
Home/App/ZusExampleApp.swift

//  ZusExampleApp.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 28/12/22.
//

import SwiftUI

@main
struct ZusExampleApp: App {
    @AppStorage(Utils.UserDefaultsKey.walletJSON.rawValue) var wallet: String = ""
    @AppStorage(Utils.UserDefaultsKey.allocationID.rawValue) var allocation: String = ""

    @StateObject var zcncoreVM: ZcncoreManager = ZcncoreManager.shared
    
    init() {
        zcncoreVM.initialize()
    }
    
    var body: some Scene {
        WindowGroup {
            Group {
                if wallet.isEmpty || allocation.isEmpty {
                    CreateWalletView(zcncoreVM: zcncoreVM)
                } else {
                    HomeView()
                }
            }
            .environmentObject(zcncoreVM)
        }
    }
}code

Describing Code :

  • Line 8 import SwiftUI gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.

  • Line 11 defines a ZusExampleApp structure that defines the following fields for building Views for the app.

    • (Line 12 and 13)A wallet and allocation variable for holding wallet and allocation information. The values are retrieved from Utils.swift methods via AppStorage property wrapper which effectively watches a key in UserDefaults, and will refresh your UI if that key changes.

    • (Line 15) A variable zcncoreVM for holding Zcncore library instance to utilize Zncore functions.

  • Line 17 to 19 initializes a zcncoreVM instance

  • Line 21 and 22 defines view that presents a group of identically structured windows.

  • Line 24 invokes an if statement in cases when variable holding wallet and allocation information are empty it creates a wallet view via CreateWalletView. swift

  • (Line 27) If this is not the case invoke HomeView in HomeView.swift

  • Line 30 zcncoreVM is passed in @EnvironmentObject* property wrapper to create views that rely on shared data, across an entire SwiftUI app.

Home/App/CreateWalletView.swift
//
//  ContentView.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 28/12/22.
//

import SwiftUI

struct CreateWalletView: View {
    @ObservedObject var zcncoreVM: ZcncoreManager
    
    var body: some View {
        GeometryReader { gr in
            ZStack(alignment: .center) {
                Spacer()
                Image("zus")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: gr.size.width * 0.5)
                    .offset(y:-150)
                    Button(action: zcncoreVM.createWallet) {
                        ZStack(alignment: .trailing) {
                            Text("Create Wallet")
                                .padding()
                                .frame(maxWidth: .infinity)
                                .background(.blue)
                                .foregroundColor(.white)
                                .cornerRadius(12)
                                .bold()
                                .disabled(zcncoreVM.processing)
                                .opacity(zcncoreVM.processing ? 0.5 : 1)
                        }
                    }
                    .offset(y:100)
                
                if zcncoreVM.processing {
                    ZCNToast(type: zcncoreVM.toast, presented: $zcncoreVM.processing,autoDismiss: false)
                        .frame(maxHeight: .infinity,alignment: .bottom)
                        .padding(.vertical,50)
                        .animation(.easeIn,value: 10)
                }
            }
            .padding(20)
            .frame(maxWidth: .infinity,maxHeight: .infinity)
            .edgesIgnoringSafeArea(.all)
        }
    }
}

struct CreateWalletView_Previews: PreviewProvider {
    static var previews: some View {
        CreateWalletView(zcncoreVM: .shared)
    }
}

Describing Code

  • Line 8 import SwiftUI gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.

  • Line 11 defines a CreateWalletView structure that helps us build the UI for creating wallet in sample app

  • Line 11 defines a variable zcncoreVM for holding ZcncoreManger instance declared in ZcncoreManager.swift.@ObservedObject property wrapper ensures property is watched closely so that important changes will reload any views using it.

  • Line 13 defines the variable bodyfor holding the main view of CreateWallet screen.

  • Line 14 utilizes GeometryReader from SwiftUI library imported above to calculate screen position and size information .

  • Line 15 to 49 builds app layouts with stack views. Individually, HStack positions views in a horizontal line, VStack positions them in a vertical line, and ZStack overlays views on top of one another.

    a)According to code, ZStack has its views aligned at the center. Inside ZStack ,

    b) Line 16: Spacer() implements a flexible space that expands along the major axis of its containing stack layout, or on both axes if not contained in a stack.

    c) Line 17 to 21 implements view that displays an zus image with resizable and specific frame size.

    d) Line 22 creates a button with createwallet action.

    e) Line 24 to 32 defines text for the button with a defined layout

  • Line 51 to 55 defines a Previewprovider type that produces view for the CreateWalletView structure .

    a) Here we will pass our CreateWalletView structure with zcncoreVM(a ZcnCoreManager instance) to utilize functionality listed in ZcnCoreManager.swift(Line 53)

Home/App/HomeView.swift
//  AppSelectionView.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 28/12/22.
//

import SwiftUI

struct HomeView: View {
    @State var presentWalletDetails : Bool = false
    @State var presentVultHome: Bool = false
    
    @Environment(\.colorScheme) var colorScheme
    @StateObject var boltVM: BoltViewModel = BoltViewModel()
    @StateObject var vultVM: VultViewModel = VultViewModel()
    @StateObject var homeVM: HomeViewModel = HomeViewModel()
    
    var body: some View {
        NavigationView {
            GeometryReader { gr in
                VStack(alignment: .center,spacing: 50) {
                    HStack(spacing: 15) {
                        WalletActionBlock(icon: "wallet", title: "Wallet Details")
                            .onTapGesture {
                                homeVM.presentWalletDetails()
                            }
                        WalletActionBlock(icon: "allocation", title: "Allocation Details")
                            .onTapGesture {
                                homeVM.presentAllocationDetails()
                            }
                        
                        WalletActionBlock(icon: "network", title: "Network Details")
                            .onTapGesture {
                                homeVM.presentNetworkDetails()
                            }
                    }
                    .aspectRatio(2.5, contentMode: .fit)
                    .shadow(color:Color(white: 0.9),radius: 25)
                

                    HStack {
                        AppSelectionBox(icon: "bolt",width: gr.size.width * 0.7)
                            .destination(destination: BoltHome().environmentObject(boltVM))
                        
                        AppSelectionBox(icon: "vult",width: gr.size.width * 0.7)
                            .destination(destination: VultHome().environmentObject(vultVM))
                    }
                    
                    Spacer()
                    
                    Text(Bundle.main.applicationVersion)
                }
                .frame(maxWidth: .infinity)
                .padding(gr.size.width/15)
                .sheet(isPresented: $homeVM.pushAllocationDetails) { AllocationDetailsView(allocation: vultVM.allocation) }
                .sheet(isPresented: $homeVM.pushWalletDetails) { WalletDetailsView() }
                .sheet(isPresented: $homeVM.pushNetworkDetails) { NetworkDetails() }
                .onAppear(perform: vultVM.getAllocation)
            }
            .navigationTitle("Hello World!")
        }
    }
    
    @ViewBuilder func AppSelectionBox(icon: String,width:CGFloat) -> some View {
        Image(icon)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .padding(width/10)
            .frame(maxWidth: .infinity)
            .background(Color.tertiarySystemBackground)
            .clipShape(RoundedRectangle(cornerRadius: 16)).shadow(color:Color(white: 0.9),radius: 25)
    }
    
    
    @ViewBuilder func WalletDetailsBlock(wallet: Wallet,width:CGFloat) -> some View  {
        
        VStack(alignment: .leading,spacing: 20) {
            HStack {
                Text("Wallet Details")
                    .font(.title)
                    .bold()
                Spacer()
                Image(systemName: "chevron.right")
                    .rotationEffect(.degrees(presentWalletDetails ? 90.0 : 0.0))
            }
            if presentWalletDetails {
                ScrollView(.horizontal, showsIndicators: false) {
                    VStack(alignment: .leading,spacing: 10) {
                        self.row(title: "Client ID: ", text: wallet.client_id)
                        self.row(title: "Client Key: ", text: wallet.client_key)
                        self.row(title: "Private Key: ", text: wallet.keys.first?.private_key ?? "")
                        self.row(title: "Public Key: ", text: wallet.keys.first?.public_key ?? "")
                        self.row(title: "Mnemonics: ", text: wallet.mnemonics)
                    }
                }
            }
        }
        .padding(width/10)
        .background(RoundedRectangle(cornerRadius: 16).fill(.background).shadow(radius: 5))
        .onTapGesture {
            withAnimation {
                self.presentWalletDetails.toggle()
            }
        }
    }
    
    @ViewBuilder func row(title:String,text:String) -> some View {
        HStack {
            Text(title)
            Text(text)
        }
    }
}

struct AppSelectionView_Previews: PreviewProvider {
    static var previews: some View {
        let previewDefaults: UserDefaults = {
            let defaults = UserDefaults.standard
            let wallet = Wallet.init(client_id: "8378938937893893639", client_key: "397397639837", keys: [], mnemonics: "", version: "")
            let data = try? JSONEncoder().encode(wallet)
            defaults.set(data, forKey: Utils.UserDefaultsKey.wallet.rawValue)
            defaults.set("", forKey: Utils.UserDefaultsKey.allocationID.rawValue)
            return defaults
        }()
        
        HomeView()
            .defaultAppStorage(previewDefaults)
    }
} Some code
  • Line 8 import SwiftUI gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.

  • Line 10 defines a HomeView structure that helps us build the UI for home page of a sample app

  • Line 15 to 17 define variables for holding ViewModel instances to get access to their functionalities.

    BoltViewModel : For linking wallet functions to app. VultViewModel : For linking storage functions to app. HomeViewModel : For linking functions required for home screen of app.

  • Line 20 defines NavigationView : a view for presenting a stack of views that represents a visible path in a navigation hierarchy.

  • Line 22 builds app layouts with stack views. Individually, HStack positions views in a horizontal line, VStack positions them in a vertical line, and ZStack overlays views on top of one another.

    a) According to code, VStack has its views aligned at center with HStack defined inside it.

    b) (Line 25 to 31)In HStack, WalletAction Block is defined with .onTapGesture action which present wallet and allocation details when this view recognizes a tap gesture. c) Line 33 also defines another WalletAction Block which present network details when this view recognizes a tap gesture. <insert_image here>

    d) Line 38 defines aspect ratio that fits the content in HStack.

    e) Line 39 adds a white shadow to this HStack view.

  • Line 43 and 46 defines another Horizontally Stacked View with bolt and vult application boxes list horizontally to each other. <insert_image_here>

  • Line 44 and 47 creates a link to destination view which are root view of Bolt and Vult app.

  • Line 50 defines a spacer which creates an adaptive view with no content that expands as much as it can.

  • Line 52 defines a view that displays the version and build information with swift.

  • Line 54 defines view within an invisible frame with the specified size.

  • Line 55 defines padding by the specified amount(1/15 of the container size) on the specified edges.

  • Line 56 to 59 present home screen views by fetching allocation,wallet and network details.

  • Line 59 adds an action to perform(get allocation) before the view appears

  • Line 61 configures the view’s title (Hello World) using a localized string.

  • Line 65 creates AppSelectionBox function for defining the layout of selecting App(Wallet App(Bolt) or Storage App(Vult) ). The @ViewBuilder attribute is defined with AppSelectionBox to create child views for a specific SwiftUI view in a readable way without having to use any return keywords..

  • Line 76 creates WalletDetailsBlock function for defining the block that present wallet details

  • Line 78 builds app layouts with stack views. Individually, VStack positions them in a vertical line while HStack positions views in a horizontal line. Inside HStack:

  • (Line 80)Defines Text(Wallet Details) inside a view .

  • Line 81 and 82 make the text bold and give the font the title text style.

  • Line 83 defines a spacer which creates an adaptive view with no content that expands as much as it can.

  • Line 84 and 85 defines view for the wallet details symbol icon and make use of the rotationEffect() modifier lets us rotate views freely, using either degrees or radians.

  • (Line 87 to 98)defines action when tapped on the wallet details icon,present the wallet details as a scrollable view in a vertical line(VStack) as rows.

  • Line 99 and 100 defines padding and background for the wallet details block.

  • Line 101 to 103 defines ontap gesture action which is present wallet details when tapped.

  • Line 108 to 114 defines how rows should be impmented for blocks. The rows has the following fields(Title and Text) horizontally stacked.

  • Line 116 defines a Previewprovider type that produces view for the HomeView structure .

    a) Line 118 to 124 set the wallet and allocation details before the Previews gets provided.

    b) Line 127 passes the HomeView() instance with wallet and allocation defaults.

Home/App/AllocationDetailsView.swift
//
//  AllocationDetailsView.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 03/01/23.
//

import SwiftUI

struct AllocationDetailsView: View {
    let allocation: Allocation
    var body: some View {
        NavigationStack {
            List {
                Section("details") {
                    ListRow(title: "Allocation ID:", body: allocation.id)
                    ListRow(title: "Name:", body: allocation.name)
                    ListRow(title: "Expiration Date:", body: allocation.expirationDate?.formattedUNIX)
                    ListRow(title: "Size:", body: allocation.size?.formattedByteCount)
                    ListRow(title: "Used Size:", body: allocation.usedSize?.formattedByteCount)
                }
                
                Section("shards and challenges") {
                    ListRow(title: "Data Shards:", body: allocation.dataShards?.stringValue)
                    ListRow(title: "Parity Shards:", body: allocation.parityShards?.stringValue)
                    ListRow(title: "Number Of Writes:", body: allocation.id)
                    ListRow(title: "Number Of Reads:", body: allocation.id)
                    ListRow(title: "Number Of Failed challenges:", body: allocation.numFailedChallenges?.stringValue)
                    ListRow(title: "Latest Closed Challenge:", body: allocation.latestClosedChallenge)
                }
            }
            .navigationTitle(Text("Allocation Details"))
        }
    }
    
    @ViewBuilder func ListRow(title: String, body: String?) -> some View {
        HStack {
            Text(title)
            Text(body ?? "~")
        }
    }
}

Describing Code:

  • Line 8 import SwiftUI gives you access to iOS UI-specific functionality . If you are writing SwiftUi View you need to import SwiftUI.

  • Line 10 defines a structure AllocationDetailsView which contains various properties and fields for creating view for Allocation details.

  • Line 11 defines a variable allocation that points to Allocation Structure.

  • Line 12 defines the variable bodyfor holding the main view of Allocation Details

  • Line 13 defines a NavigationStack which provides a view that displays a root view and enables you to present additional views over the root view.

  • Line 14 defines a List for displaying a collection of data

  • Inside the list at line 15 ,to add a section around some cells, a Section statement with title is added.

  • Line 15 to 29 will create rows under the list that holds Allocation data(Allocation ID ,Name , Expiration Date,Size,Used Size,Data Shards, Parity Shards, Number of Writes,Number of Writes,Reads ,Number of Failed Challenges and Latest Closed Challenge )

  • Line 32 defines a title for the navigation stack at line 13.

  • Line 36 defines a layout for List via ListRow method . The @ViewBuilder attribute is used with the function to create child views under the parent view(Home View).

  • HStack positions the following views(NavigationStackTitle and body: Allocation Details ) in a horizontal line(Line 38 and 39)

Launch.storyboard

A launch screen storyboard contains basic UIKit views, and uses size classes and Auto Layout constraints to support different device sizes and resolutions.

Home/App/WalletDetailsView.swift
//
//  WalletDetailsView.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 07/01/23.
//

import SwiftUI

struct WalletDetailsView: View {
    let wallet: Wallet?
    
    init() {
        self.wallet = Utils.wallet
    }
    
    var body: some View {
        NavigationStack {
            List {
                Section("details") {
                    ListRow(title: "Client ID:", body: wallet?.client_id)
                    ListRow(title: "Private Key:", body: wallet?.keys.first?.private_key ?? "")
                    ListRow(title: "Public Key:", body: wallet?.keys.first?.public_key ?? "")
                    ListRow(title: "Mnemonics:", body: wallet?.mnemonics)
                }
            }
            .navigationTitle(Text("Wallet Details"))
        }
    }
    
    @ViewBuilder func ListRow(title: String, body: String?) -> some View {
        HStack {
            Text(title)
            Text(body ?? "~")
        }
    }
}


struct WalletDetailsView_Previews: PreviewProvider {
    static var previews: some View {
        WalletDetailsView()
    }
}

Describing Code:

  • Line 8 import SwiftUI gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.

  • Line 10 defines a WalletDetailsView structure that helps us define the following fields for building WalletDetailsView.

    • A Wallet Instance to access Wallet functions for information.

  • Line 14 initializes the WalletDetailsView instance.

  • Line 16 defines view for the WalletDetailsView.

  • Line 18 implements a NavigationStack() that displays a root view and enables you to present additional views over the root view.

  • Line inside the root view ,a list containing section for Wallet details(ClientID,Private Key, Public Key , Wallet Mnemonics)

  • Line 27 defines title for the WalletDetails Navigation Stack.

  • Line 31 defines function for how rows should be implemented for WalletDetailsView. The rows has the following fields(Title and Body) horizontally stacked.(HStack)

  • Line 40 to 44 defines a Previewprovider type that produces view for the WalletDetailsView structure .A WalletDetailsView instance is passed as a view to be produced .

Home/App/NetworkDetails.swift
// 
//  NetworkDetails.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 09/01/23.
//

import SwiftUI

struct NetworkDetails: View {
    @State var config : NetworkConfig = Network.demoZus.config
    @State var network: Network = Network.demoZus
    @State var changeNetwork: Network = Network.demoZus
    @State var presentAlert: Bool = false

    init() {
        if let network = Utils.get(key: .network) as? String, let config = Network(rawValue: network) {
            self.config = config.config
            self.network = config
            self.changeNetwork = config
        }
    }
    
    var body: some View {
        NavigationStack {
            
            List {
                Section("Details") {
                    ListRow(title: "Name: ", value: String(describing: network) + " Network")
                    ListRow(title: "Url: ",value: config.host)
                    ListRow(title: "0Box Url:",value: config.zboxURL)
                }
                
                Section {
                    Link(destination: URL(string: config.blockWorker)!) {
                        Text(config.blockWorker)
                    }
                }
                  
            }
            .alert("Are you sure?", isPresented: $presentAlert) {
                Button {
                    
                } label: {
                    Text("No")
                }
                
                Button {
                    Utils.delete(key: .walletJSON)
                    Utils.delete(key: .allocationID)
                    Utils.set(changeNetwork.rawValue, for: .network)
                } label: {
                    Text("Yes, Change network")
                }
            } message: {
                Text("You will be logged out and will have to create a new wallet")
            }
            .navigationTitle(Text("Network Details"))
        }
    }
}

struct NetworkDetails_Previews: PreviewProvider {
    static var previews: some View {
        NetworkDetails()
    }
}code
  • Line 8 import SwiftUI gives you access to SwiftUI-specific functionality . If you are writing UI Views you need to import SwiftUI.

  • Line 10 defines a NetworkDetails structure that helps us define fields for building NetworkDetails layout of a sample app.

  • Line 11 to 14 defines the following variable for holding network details.

    NetworkConfig : Holding Network Configuration

    Network : Holding Network URL

    changeNetwork : Holding Changed Network State

    presentAlert: A boolean for holding Network Alerts

  • Line 16 to Line 22 intializes a NetworkDetails instance with defined network fields

  • Line 24 defines view for network Details.

  • Line 25 implements a NavigationStack() that displays a root view and enables you to present additional views over the root view.

  • In root view a section pretaining to networkdetails is listed in rows .

  • (Line 34 to 38) Another section is listed which defines Text field inside a view with a block worker field.

  • Line 41 defines additional view in case change network is clicked. An alert message 'Are you sure? ' is displayed with two options 'Yes' or 'No'.

  • In case Yes is pressed the current wallet and allocationID is deleted and the following message is displayed. "You will be logged out and will have to create a new wallet"

  • Line 76 defines title for the Network Details Navigation Stack

  • Line 81 defines a Previewprovider type that produces view for the HomeView structure by passing NetworkDetails instance .

Home/Model/NetworkConfig.swift
//
//  NetworkConfig.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 28/12/22.
//

import Foundation

struct NetworkConfig: Codable {
    
    let signatureScheme: String
    let confirmationChainLength: Int
    let blockWorker, zboxURL: String
    
    enum CodingKeys: String, CodingKey {
        case signatureScheme = "signature_scheme"
        case confirmationChainLength = "confirmation_chain_length"
        case blockWorker = "block_worker"
        case zboxURL
    }
    
    internal init(signatureScheme: String = "bls0chain",
                  confirmationChainLength: Int = 3,
                  blockWorker: String, zboxURL: String) {
        self.signatureScheme = signatureScheme
        self.confirmationChainLength = confirmationChainLength
        self.blockWorker = blockWorker
        self.zboxURL = zboxURL
    }
    
    internal init(scheme: String) {
        let blockWorker = "https://" + scheme + "/dns"
        let zboxURL = "https://0box." + scheme
        self.init(blockWorker: blockWorker, zboxURL: zboxURL)
    }
    
    var host: String {
        return URLComponents(string: blockWorker)?.host ?? ""
    }
    
}

enum Network: String,CaseIterable {
    case demoZus = "demo.zus.network"
    case bcv1 = "bcv1.devnet-0chain.net"
    case demo = "demo.0chain.net"
    case potato = "potato.devnet-0chain.net"
    case test = "test.0chain.net"
    
    var config: NetworkConfig {
        return NetworkConfig(scheme: self.rawValue)
    }
}
  • Line 8 import Foundation framework provides a base layer of functionality for apps and frameworks, including data storage and persistence, text processing, date and time calculations, sorting and filtering, and networking.

  • Line 12 defines NetworkConfig structure with the following variables: signatureScheme : Holding a signature scheme .confirmationChainLength: Holding Chain confirmation length blockworker : Holding blockworker URL.

  • Line 44 to 54 defines cases in case of network change via App. Particular case is executed when a particular network is chosen.

Home/ViewModel/ZcnCoreManager.swift
//
//  ZcncoreManager.swift
//  ZusExample
//
//  Created by Aaryan Kothari on 28/12/22.
//

import Foundation
import Zcncore
import Photos


class ZcncoreManager: NSObject, ObservableObject {
    
    static let shared = ZcncoreManager()

    private static var network: NetworkConfig = Network.demo.config
    static var zboxStorageSDKHandle : SdkStorageSDK? = nil
    
    @Published var processing: Bool = false
    @Published var toast: ZCNToast.ZCNToastType = .progress("Creating Wallet...")

    func initialize() {
        do {
            if let networkScheme = Utils.get(key: .network) as? String, let network = Network(rawValue: networkScheme) {
                ZcncoreManager.network = network.config
            }
            try initialiseSDK()
            setWalletInfo()
        } catch let error {
            print(error.localizedDescription)
        }
    }
    
    class func configString() throws -> String? {
        let encoder: JSONEncoder = JSONEncoder()
        let data = try encoder.encode(self.network)
        return String(data: data, encoding: .utf8)
    }
    
    func initialiseSDK() throws {
        var error: NSError? = nil
        let logPath = Utils.logPath()
        ZcncoreSetLogFile(logPath.path, true)
        
        let jsonData = try JSONEncoder().encode(ZcncoreManager.network)
        let configString = String(data: jsonData, encoding: .utf8)!
        let wallet = Utils.get(key: .walletJSON) as? String
        
        ZcncoreInit(configString, &error)
        
        ZcncoreManager.zboxStorageSDKHandle = SdkInitStorageSDK(wallet, configString, &error)
        
        if let error = error {
            throw error
        }
    }
    
    func createWallet() {
        self.toast = .progress("Creating Wallet ...")
        self.processing = true
        
        var error: NSError? = nil
        ZcncoreCreateWallet(self, &error)
        
        if let error = error {
            self.onWalletCreateFailed(error: error.localizedDescription)
        }
    }
    
    func createAllocation() {
        DispatchQueue.global().async {
            do {
                let allocation = try ZcncoreManager.zboxStorageSDKHandle?.createAllocation("Allocation", datashards: 2, parityshards: 2, size: 214748364, expiration: Int64(Date().timeIntervalSince1970 + 2592000), lock: "10000000000")
               // VultViewModel.zboxAllocationHandle = allocation
                DispatchQueue.main.async {
                    self.toast = .success("Allocation Created Successfully")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                    if let allocationId = allocation?.id_ {
                        Utils.set(allocationId, for: .allocationID)
                        self.requestPhotoAuth()

                    }
                }
            } catch let error {
                print(error)
                DispatchQueue.main.async {
                    self.toast = .error("Error creating allocation")
                    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                        self.processing = false
                    }
                }
            }
        }
    }
    
    
    func setWalletInfo() {
        var error: NSError? = nil
        let wallet = Utils.get(key: .walletJSON) as? String
        ZcncoreSetWalletInfo(wallet, false,&error)
        if let error = error {
            print(error.localizedDescription)
        }
    }
    
    
    func onWalletCreateComplete(wallet: Wallet) {
        DispatchQueue.main.async {
            self.toast = .progress("Creating Allocation ...")
        }
        BoltViewModel().receiveFaucet()
        self.createAllocation()
    }
    
    func onWalletCreateFailed(error: String) {
         self.toast = .error(error)
    }
    func requestPhotoAuth() {
        PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in }
    }
}

extension ZcncoreManager: ZcncoreWalletCallbackProtocol {
    func onWalletCreateComplete(_ status: Int, wallet: String?, err: String?) {
        DispatchQueue.main.async {
            guard status == ZcncoreStatusSuccess,
                  err == "",
                  let walletJSON = wallet,
                  let w = try? JSONDecoder().decode(Wallet.self, from: Data(walletJSON.utf8)) else {
                self.onWalletCreateFailed(error: err ?? "Something went wrong :(")
                return
            }
            
            print(w.debugDescription())
            Utils.set(walletJSON, for: .walletJSON)
            Utils.wallet = w
            
            self.setWalletInfo()
            try? self.initialiseSDK()
            self.onWalletCreateComplete(wallet: w)
        }
    }
}
  • Line 8 import Foundation is required to provide a base layer of functionality for apps and frameworks, including data storage and persistence, text processing, date and time calculations, sorting and filtering, and networking.

  • Line 9 import Zcncore is required to access Gosdk functions.

  • Line 11 defines a ZcncoreManager structure that defines the following fields for utilizing and handling zcncore libraries.

    • Line 13 defines a static variable for holding ZcncoreManager instance.

    • Line 15 defines a private static network variable that points to NetworkConfig and demo network.

    • Line 16 defines another variable for handling zboxStorageSDK functions.

    • Line 18 defines a boolean processing variable with@Published property wrappers allowing to create objects that automatically announce when changes occur.

    • Line 19 defines a boolean toast variable that holds access to ZCNToastType for managing zcn operations . The variable is also wrapped with @Published property wrapper allowing to create objects that automatically announce when changes occur.

  • Line 21 defines func initialize() which does the following operations

    • Sets the network scheme to connect to when doing storage operations.(Line 23 and 24)

    • Intialize the SDK to leverage all the dstorage functionalities(Line 26).Calls the function at line 39.

    • SetsWalletInfo before starting the app. Calls the function at line 95.

    • Line 28 and 29 catch statement throws errors if any of the above situations doesnot work as expected.

  • Line 33 to 37 defines a function configString() for handling string encoding and returning an encoded string.

  • Line 39 defines functionality for intializing the SDK via initialiseSDK() function.

    • line 40 to 42 defines varibles for catching errors and setting log file path for storing logs.

    • Line 44 to 46 defines the following variables:

      jsonData: Holding the encoded network configuration

      configString: Holding the configurationstring that is required by gosdk Zcncoreinit function to initialize the sdk.

      Wallet : Fetches Wallet Key via [Utils] and holds it.

  • Line 48 calls ZcncoreInit function and passes the network configuration(configString) to perform storage operations.

  • Line 50 assigns zboxStorageSDKHandle variable the SDKInitStorageSDK(wallet,configString) which intializes all the gosdk storage functions for use.

  • Line 52 and 53 statements handles error in case any any gosdk functions failed to intialize.

  • Line 57 to 117 defines the following functions for the VultApp to interface with gosdk :

    • (Line 57 to 67)createWallet() : Creates Wallet for performing operations on dStorage network.

    • (Line 69 to 92) createAllocation(): Creates Allocation for storing data on dStorage network.

    • (Line 95 to 102) setWalletInfo(): Sets Wallet Information

    • (Line 105 to 111) onWalletCreateComplete(): This function fills the wallet with ZCN Tokens and creates allocation automatically if the wallet is successfully created.

    • (Line 120 to 123) requestPhotoAuth(): Function requests the user’s authorization to allow access to your photo library for your app.

  • Line 119 to 137 defines additional functionality as a callback function in the ZcncoreManager class.