SwiftyEOS is an open-source framework for interacting with EOS, written in Swift.
- EOS key pairs generation
- Private key import
- Signature hash
- Basic RPC API(chain/history) query client
- Transaction(EOS token transfer)
- Helper class for handling offline wallet on iOS
- Encrypt/decrypt importing private key on iOS
- Copy the
Libraries
andSources
folders into your project, withoutmain.swift
. - Delete
Sources/Utils/iOS
if not targeted to iOS platform. - Add
Libraries/include
into Header Search Path. - Set
Libraries/include/Bridging-Header.h
as Objective-C Bridging Header. If you've got your own bridging header , copy all theimport
content in that file and paste into your own one. - Compile and pray.
SwiftyEOS now support secp256k1 key pairs.
There are bugs around secp256r1 key pairs generation but I cannot figure out why. Unit tests created from
cleos create key --r1
wouldn't pass. You may not consider secp256r1 as an option since thecleos wallet
command cannot import those keys, either.
let (pk, pub) = generateRandomKeyPair(enclave: .Secp256k1)
Easy, right?
print("private key: \(pk!.wif())")
print("public key : \(pub!.wif())")
// private key: PVT_K1_5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL
// public key : PUB_K1_4yDYdmcVcXxAxeNsUWRG7x9FKQE4HbJZdzgZFv1AYxk6oSVcLd
The PVT_K1_
and the PUB_K1_
prefixes are the parts of standard key presentations. But old styles are also supported in EOS system and SwiftyEOS:
print("private key: \(pk!.rawPrivateKey())")
print("public key : \(pub!.rawPublicKey())")
// private key: 5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL
// public key : EOS4yDYdmcVcXxAxeNsUWRG7x9FKQE4HbJZdzgZFv1AYxk6oSVcLd
let importedPk = try PrivateKey(keyString: "5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL")
let importedPub = PublicKey(privateKey: importedPk!)
With delimiter and prefix:
let importedPk = try PrivateKey(keyString: "PVT_K1_5HxrYTdZX89zodtJhTzCk87MfNZAkiBRfFvSX8kacYjtwaDpTkL")
let importedPub = PublicKey(privateKey: importedPk!)
EOSRPC.sharedInstance.chainInfo { (chainInfo, error) in
if error == nil {
print("Success: \(chainInfo!)")
} else {
print("Error: \(error!.localizedDescription)")
}
}
Currently we have some basic rpc endpoints, you can find it at Sources/SwiftyEOS/Network
We have helpers for iOS offline wallet management at SEWallet.swift
.
With SEWallet.swift
you can easily store AES encrypted key info into file system. The default location is app's sandbox Library.
Multiple wallets management is not supported yet.
In Objective-C:
[SEKeystoreService.sharedInstance newAccountWithPasscode:passcode succeed:^(SELocalAccount *account) {
} failed:^(NSError *error) {
}];
[SELocalAccount currentAccount];
It will return nil if there's no saved wallet.
Transaction behaviors are not fully supported yet, but you still can have a try with sample code at main.swift
.
The related documents will be provided once the whole function is done.
- Currency transfer (2018.08.15)
- Push general transactions (2018.08.16)
- On-device(offline) wallet lock & unlock on iOS (2018.08.17)
- Stake/unstake cpu/net (2018.08.28)
- Buy/sell ram (2018.08.28)
var transfer = Transfer()
transfer.from = "agoodaccount"
transfer.to = "gq3dinztgage"
transfer.quantity = "1.0000 EOS"
transfer.memo = "eureka"
Currency.transferCurrency(transfer: transfer, privateKey: importedPk!, completion: { (result, error) in
if error != nil {
if error is RPCErrorResponse {
print("\((error as! RPCErrorResponse).errorDescription())")
} else {
print("other error: \(String(describing: error?.localizedDescription))")
}
} else {
print("done.")
}
})
In Swift:
let account = "raoji"
let asset = "1.0000 EPRA"
let data = "{\"hey\": {\"account\":\"" + account + "\", \"quantity\":\"" + asset + "\"}}"
let abi = try! AbiJson(code: "prabox1", action: "withdraw", json: data)
TransactionUtil.pushTransaction(abi: abi, account: account, privateKey: importedPk!, completion: { (result, error) in
if error != nil {
if (error! as NSError).code == RPCErrorResponse.ErrorCode {
print("\(((error! as NSError).userInfo[RPCErrorResponse.ErrorKey] as! RPCErrorResponse).errorDescription())")
} else {
print("other error: \(String(describing: error?.localizedDescription))")
}
} else {
print("Ok. Txid: \(result!.transactionId)")
}
})
And also in Objective-C:
AbiJson *your_abi;
[TransactionUtil pushTransactionWithAbi:your_abi
account:@"your_account"
pkString:@"your_private_key"
completion:^(TransactionResult *result, NSError *error) {
}];
We added lock
and timedUnlock
functions to SELocalAccount
.
There's a ResourceUtil.swift
file with ResourceUtil
class including, within which are several methods:
stakeResource
unstakeResource
buyRam
sellRam
Stake resource:
ResourceUtil.stakeResource(account: "raoji", net: 1.0, cpu: 1.0, pkString: "5HsaHvRCPrjU3yhapB5rLRyuKHuFTsziidA13Uw6WnQTeJAG3t4", completion: { (result, error) in
})
We're using NSObject
inhereiting class for all top level API, so calling in Objective-C is the same way without providing additional bridging files.
And in SEWallet.swift
file there are helper methods for iOS, too.
Inspired by:
- https://github.com/EOSIO/eos
- https://github.com/EOSIO/fc
- https://github.com/bitcoin/bitcoin
- https://github.com/bitcoin/libbase58
- https://github.com/OracleChain/chainkit
- https://github.com/OracleChain/PocketEOS-IOS
Built with:
Contributers: