No description, website, or topics provided.
Clone or download
Pull request Compare This branch is 87 commits ahead of daoka:master.
Latest commit eb0eabe Nov 13, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
NemSwift.xcodeproj
NemSwift fix: #9 Sort mosaics Nov 13, 2018
NemSwiftDemo fix: Some APIs does not work on 32bit environment. Sep 18, 2018
NemSwiftTestHost
NemSwiftTests
.gitignore
.gitmodules
.swift-version feat: Change message type to [UInt8] for setting encrypted message. Aug 13, 2018
.travis.yml chore: fix test script Aug 1, 2018
CHANGELOG.md docs: 0.3.2 Nov 13, 2018
Cartfile refactor: remove Base32 dpendency Jul 18, 2018
Cartfile.resolved fix: Some APIs does not work on 32bit environment. Sep 18, 2018
LICENSE Create LICENSE Jul 18, 2018
NemSwift.podspec docs: 0.3.2 Nov 13, 2018
README.ja.md docs: Add how to use MessageEncryption. Aug 13, 2018
README.md

README.md

Read this in other languages: English, 日本語

nem-swift

nem-swift is a client library for easy use of NEM API.

This library wraps HTTP requests to NIS(NEM Infrastructure Server) and HTTP responses from NIS.

This library also provides crypt related utilities like key pair generation signing and verifying.

Sample

Sample projects are in NemSwiftDemo directory.

Installation

Use Carthage or CocoaPods.

Carthage

  1. Insert github "ryuta46/nem-swift" to your Cartfile.

  2. Run carthage update.

  3. Add "NemSwift.framework" to Linked Frameworks and Libraries
    TARGETS -> YourTarget -> Linked Frameworks and Libraries
    Press "+" -> Add Other... -> Select "NemSwift.framework" in Carthage/Build/iOS

    Link NemSwift.framework

  4. Add Run Script in Build Phases
    Build Phases -> Press "+" -> New Run Script Phase
    Shell /bin/sh
    Script /usr/local/bin/carthage copy-frameworks
    Add "NemSwift.framework", "APIKit.framework", "Result.framework" and "CryptoSwift.framework" to input file

    Copy frameworks

CocoaPods

  1. Insert pod 'NemSwift' to your Podfile
  2. Run pod update
  3. Open generated .xcworkspace file with Xcode.

How to use

Setup

Configure ATS

If you want to access to NIS with HTTP (not HTTPS) protocol, configure ATS (App Transport Security) in Info.plist file.

See ATS Configuration Basics for details.

Setup Library

nem-swift has global configurations in NemSwiftConfiguration class.

import NemSwift
...

// Default URL of NIS
NemSwiftConfiguration.defaultBaseURL = URL(string: "https://nismain.ttechdev.com:7891")!
// Log level
NemSwiftConfiguration.logLevel = .debug

Account generation

'Account' generates a NEM account. Network version is required( for main network or test network).

let account = Account.generateAccount(network: .testnet)

If you have private key already, retrieve the account from the key.

let account = Account.repairAccount(privateKey, network: .testnet)

Getting an account information

To get an account information,

import NemSwift
import APIKit
import Result

...

Session.send(NISAPI.AccountGet(address: account.address.value)) { result in
    switch result {
        case .success(let response):
            print("balance \(response.account.balance)")
        case .failure(let error):
            print(error)
    }
}

NISAPI has classes corresponding to NEM APIs.
You can override NIS URL with baseURL parameter when you create a request.

Session.send(NISAPI.AccountGet(baseURL: URL(string:"http://customnis:7890")!,  address: account.address.value)) { result in
        ....
    }
}

Sending XEM and Mosaics

TransferTransactionHelper is an utility to create transactions which required account signing.

To send XEM,

// Create XEM transfer transaction
let transaction = TransferTransactionHelper.generateTransferRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    recipientAddress: recipient,
    amount: microXem)

// Sign the transaction
let signedTransaction = RequestAnnounce.generateRequestAnnounce(requestAnnounce: transaction, keyPair: account.keyPair)

// Send
Session.send(NISAPI.TransactionAnnounce(data: signedTransaction.data, signature: signedTransaction.signature)) { result in
    switch result {
        case .success(let response):
            print(response)
        case .failure(let error):
            print(error)
    }
}

Note that the amount specified above is micro nem unit. ( 1 XEM = 1,000,000 micro nem)

To send mosaic,

let mosaic = TransferMosaic(namespace: "mosaicNamespaceId",
                            mosaic: "mosaicName",
                            quantity: quantity,
                            supply: mosaicSupply,
                            divisibility: mosaicDivisibility)

// Create transfer transaction
let transaction = TransferTransactionHelper.generateMosaicTransferRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    recipientAddress: recipient,
    mosaics: [mosaic])

Mosaic's supply and divisibility are used to calculate minimum transaction fee.

You can get these parameters of mosaic with 'namespaceMosaicDefinitionPage' if you don't know them.

Session.send(NISAPI.NamespaceMosaicDefintionPage(namespace: "mosaicNameSpaceId")) { result in
    switch result {
        case .success(let response):
            for mosaicDefinition in response.data {
                if (mosaicDefinition.mosaic.id.name == "mosaicName") {
                    // supply =  mosaicDefinition.mosaic.initialSupply
                    // divisibility = mosaicDefinition.mosaic.divisibility
                }
            }

Sending and Receiving message.

To send XEM with a plain text message,

let message = Array("message".utf8)

let transaction = TransferTransactionHelper.generateTransferRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    recipientAddress: recipient,
    amount: microXem,
    messageType: .plain,
    message: message)

With a encrypted message,

let message = Array("message".utf8)

let encryptedMessage = MessageEncryption.encrypt(
    senderKeys: account.keyPair, 
    receiverPublicKey: receiverPublicKey,
    message: message)

let transaction = TransferTransactionHelper.generateTransferRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    recipientAddress: recipient,
    amount: microXem,
    messageType: .secure,
    message: message)

You can read message from a transaction as follows

guard let payload = transaction?.transaction.message?.payload,
    let type = transaction?.transaction.message?.type {
    return
}

let messageBytes = ConvertUtil.toByteArray(payload)

let message: String
if (type == TransferTransactionHelper.MessageType.plain.rawValue) {
    message = String(bytes: messageBytes, encoding: .utf8)!
} else {
    let decryptedBytes = try MessageEncryption.decrypt(
        receiverKeys: account.keyPair,
        senderPublicKey: senderPublicKey,
        mergedEncryptedMessage: messageBytes)

    message = String(bytes: decryptedBytes, encoding: .utf8)!
}

Multisig Related Transactions

Multisig related transactions(MultisigTransaction, MultisigSignatureTransaction, MultisigAggreageModificationTransaction) are created by MultisigTransactionHelper.

To change an account to multisig account,

let modificationRequest = MultisigTransactionHelper.generateAggregateModificationRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    modifications: [MultisigCosignatoryModification(modificationType: .add, cosignatoryAccount: signer.keyPair.publicKeyHexString())],
    minCosignatoriesRelativeChange: 1)

Session.send(NISAPI.TransactionAnnounce(requestAnnounce: modificationRequest, keyPair: account.keyPair)) { result in
    switch result {
        case .success(let response):
            print(response)
        case .failure(let error):
            print(error)
    }
}

To send XEM from multisig account,

// Create inner transaction of which transfers XEM
let transferTransaction = TransferTransactionHelper.generateTransfer(
    publicKey: MULTISIG_ACCOUNT_PUBLIC_KEY,
    network: .testnet,
    recipientAddress: recipientAddress,
    amount: 10
)
        
    
// Create multisig transaction
let multisigRequest = MultisigTransactionHelper.generateMultisigRequestAnnounce(
    publicKey: account.keyPair.publicKey,
    network: .testnet,
    innerTransaction: transferTransaction)


Session.send(NISAPI.TransactionAnnounce(requestAnnounce: multisigRequest, keyPair: account.keyPair)) { result in
    switch result {
        case .success(let response):
            print(response)
        case .failure(let error):
            print(error)
    }
}

And to sign the transaction,

// Get hash of the transaction to be signed.
Session.send(NISAPI.AccountUnconfirmedTransactions(address: signer.address.value)) { [weak self] result in
    switch result {
        case .success(let response):
            self?.unconfirmedTransactions = response
        case .failure(let error):
            print(error)
        }
    }
}

...
        
guard let hash = self.unconfirmedTransactions?.data.first?.meta.data else {
    return
}
    
// Sign the transaction
let signatureRequest = MultisigTransactionHelper.generateSignatureRequestAnnounce(
    publicKey: signer.keyPair.publicKey,
    network: .testnet,
    otherHash: hash,
    otherAccount: MULTISIG_ACCOUNT_ADDRESS)
    

Session.send(NISAPI.TransactionAnnounce(requestAnnounce: signatureRequest, keyPair: signer.keyPair)) { result in
    switch result {
        case .success(let response):
            print(response)
        case .failure(let error):
            print(error)
    }
}