Giter Site home page Giter Site logo

prochain / swiftyeos Goto Github PK

View Code? Open in Web Editor NEW
93.0 10.0 23.0 307 KB

SwiftyEOS is an open-source framework for interacting with EOS, written in Swift. Can be used on iOS and macOS.

License: Apache License 2.0

Swift 27.10% Objective-C 0.22% C++ 11.62% C 61.06%
eos swift cryptocurrency blockchain eos-sdk eos-swift eos-ios eos-objective-c

swiftyeos's Introduction

SwiftyEOS

Build Status

SwiftyEOS is an open-source framework for interacting with EOS, written in Swift.

Features

  • 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

How to use it

  1. Copy the Libraries and Sources folders into your project, without main.swift.
  2. Delete Sources/Utils/iOS if not targeted to iOS platform.
  3. Add Libraries/include into Header Search Path.
  4. Set Libraries/include/Bridging-Header.h as Objective-C Bridging Header. If you've got your own bridging header , copy all the import content in that file and paste into your own one.
  5. Compile and pray.

Key Pairs Generation

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 the cleos wallet command cannot import those keys, either.

Generate a random key pair:

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

Import existing key:

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!)

RPC API

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

iOS Key Store

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.

Create new wallet on iOS

In Objective-C:

[SEKeystoreService.sharedInstance newAccountWithPasscode:passcode succeed:^(SELocalAccount *account) {
} failed:^(NSError *error) {
        
}];

Retrieve saved wallet

[SELocalAccount currentAccount];

It will return nil if there's no saved wallet.

Transactions

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.

  1. Currency transfer (2018.08.15)
  2. Push general transactions (2018.08.16)
  3. On-device(offline) wallet lock & unlock on iOS (2018.08.17)
  4. Stake/unstake cpu/net (2018.08.28)
  5. Buy/sell ram (2018.08.28)
  6. Create account (2018.10)
  7. Push transaction with params list (2018.11.05)
  8. Create/import key pairs with mnemonic

Transfer Currency

var transfer = Transfer()
transfer.from = "agoodaccount"
transfer.to = "gq3dinztgage"
transfer.quantity = "1.0000 EOS"
transfer.memo = "eureka"

Currency.transferCurrency(transfer: transfer, code: "eosio.token", 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.")
    }
})

Push General Transactions

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) {
        
}];

On-device(offline) Wallet Lock & Unlock on iOS

We added lock and timedUnlock functions to SELocalAccount.

Cpu/net/ram operations

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
})

Mnemonic

Create a new key pair:

let (pk, pub, mn) = generateRandomKeyPair(enclave: .Secp256k1)

Import existing mnemonic:

let (pk, mn) = PrivateKey(enclave: .Secp256k1, mnemonicString: "your words here")

And we do have iOS helper API with mnemonic for key manangement in SEWallet.swift. Creating and importing mnemonic is possible now, with SEKeystoreService class(or SEKeystore deep level API if you're store it on yourself):

SEKeystoreService.sharedInstance.newAccountAndMnemonic(passcode: "your pass here", succeed: { (account, mnemonic) in

}) { (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.

Thanks

Inspired by:

Built with:

Contributers:

swiftyeos's People

Contributors

croath avatar jingleizhang avatar liunina avatar micahli avatar ysoftware avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftyeos's Issues

AbiJson Type 'AbiJson' does not conform to protocol 'Encodable'

@objcMembers class AbiJson: NSObject, Encodable {
var code: String
var action: String
var args: Dictionary<String, AnyCodable>

init(code: String, action: String, json: String) throws {
    self.code = code
    self.action = action
    
    let decoder = JSONDecoder()
    self.args = try decoder.decode([String: AnyCodable].self, from: json.data(using: .utf8)!)
}

}

Archive compile error

I get this error when trying to archive for App Store upload. Xcode 10

Transaction.swift
static func dataForSignature(chainId: String?, pkt: PackedTransaction) -> Data {
    ...
    writer.pushInt(value: Int(UInt32(pkt.transaction.expiration.timeIntervalSince1970) & 0xFFFFFFFF))
    writer.pushShort(value: pkt.transaction.refBlockNum & 0xFFFF)

    writer.pushInt(value: Int(pkt.transaction.refBlockPrefix & 0xFFFFFFFF))
    // ^ Integer literal '4294967295' overflows when stored into 'Int'
    ...
}

Any suggestions on how to fix this?

README.md

Transfer Currency

Currency.transferCurrency(transfer: transfer, code: "eosio.token", privateKey: privateKey) { (res, err) in
            callback(res,err)
        }

Availability of Currency transfer in objective c

Hello, Thanks for good library.
I have integrated this library into the objective c project. But due to complier limitations it not able to convert the some swift files to objective c compatible. The possible workaround for this one will be as follows -
1. Inherit the Currency class from NSObject
2. Convert the PrivateKey and PublicKey structs to class, so that complier can create respective objective c files in bridging header
If you have any other solution will be appreciated.

Remote account creation

Is it possible to create an account and then push it to remote?

I know that it is possible by performing 3 transactions in a row: "newaccount", "buyrambytes" and finally "delegatebw". Is there shorthand method in SwiftyEOS to achieve it or do I need to create three transactions and payload manually?

Mac project is ok, iOS project is not working...

let importedPk = try PrivateKey(keyString: "5HsaHvRCPrjU3yhapB5rLRyuKHuFTsziidA13Uw6WnQTeJAG3t4")
let importedPub = PublicKey(privateKey: importedPk!)
print("imported private key: \(importedPk!.wif())")
print("imported public key : \(importedPub.wif())")

var transfer = Transfer()
transfer.from = "raoji"
transfer.to = "raojiraoji12"
transfer.quantity = "1.0000 EOS"
transfer.memo = "test"

Currency.transferCurrency(transfer: transfer, code: "eosio.token", 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)")
    }
})

Mac project is ok. iOS project can be signed but failed to pushTransaction.

I'm sure the privateKey and transfer is correct.

error: RPCError(code: 3040000, name: "transaction_exception", what: "Transaction exception", details: [])

AnyCodable

The file for this folder 【AnyCodable】 has not been uploaded

PublicKey from string

I'm trying to implement some custom features requested at my job and for that I would need to know how to restore a PublicKey object from a public key string?

Is that even possible?

Thx

Transactions signing crash

Hello. I'm running SwiftyEOS in Xcode 10 (Swift 4.2)
I had compilation errors, so I added some force unwrapping, hoping it would be all ok.
It wasn't.

While trying to push currency transfer transaction:

let privateKey = try! PrivateKey(keyString: "5JsK462V1twPZHXW2iBPNoncRT8XBC7NwUHkKS1FDgZNCTGZNZV")!

let transfer = Transfer()
transfer.from = "default"
transfer.to = "username"
transfer.quantity = "1.0 EOS"
transfer.memo = "test"

Currency.transferCurrency(transfer: transfer,
			code: "eosio.token",
			privateKey: privateKey) { result, error in
}
Transaction.swift
mutating func sign(pk: PrivateKey, chainId: String) {
        let packedBytes: [UInt8] = [UInt8](DataWriter.dataForSignature(chainId: chainId, pkt: self))
        
        let digest = Data(bytes: packedBytes, count: packedBytes.count).sha256()
        let packedSha256 = [UInt8](digest)! // ← added this exclamation mark
        ...

"Unexpectedly found nil while unwrapping an Optional value"
and also this message:

decodable init: dataCorrupted(Swift.DecodingError.Context(codingPath: [], 
debugDescription: "The given data was not valid JSON.", 
underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})))

Similar problem appears when I try to create public key out of a private key object.

uECC.c
uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
                                         const uint8_t *bytes,
                                         int num_bytes) {
    wordcount_t i;
    uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
	for (i = 0; i < num_bytes; ++i) {
		unsigned b = num_bytes - 1 - i;
		native[b / uECC_WORD_SIZE] |=
		(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); // ← EXC_BAD_ACCESS (code=1, address=0x0)
	}
}

Tried it with PrivateKey.randomPrivateKey()! and a key generated by cleos/keosd.

iOS 12.0.1, Xcode 10
Can you please guide me to the answer?
Thank you.

crash when i import by mnemonic

i test import by mnemonic , use "pistol used giant brick copper reward vicious lecture when true bargain push" crash when i print the rawPrivateKey

在OC中无法使用Currency.transferCurrency方法,有没有什么办法可以解决

Describe the bug or issue
A clear and concise description of what the bug is, or what do you want to do.

Answer the question
Did you read the readme file?
If NO, close this page and go back to the readme file.

To Reproduce or What you have tried
Steps to reproduce the behavior:

  1. Write some code '...'
  2. Compile '....'
  3. Run '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Traget (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]

Additional context
Add any other context about the problem here.

Questions

Hello, this library looks very interesting and useful!
Thank you for the work.

I have several questions about how it works.

  1. Does it fully work without downloading nodes? If so, how can it work without syncing nodes?
  2. Can I use this library using Cocoa Pods? I dont see any installation guides.

购买资源接口报500,接口参数貌似错了

Describe the bug or issue
A clear and concise description of what the bug is, or what do you want to do.

Answer the question
Did you read the readme file?
If NO, close this page and go back to the readme file.

To Reproduce or What you have tried
Steps to reproduce the behavior:

  1. Write some code '...'
  2. Compile '....'
  3. Run '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Traget (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]

Additional context
Add any other context about the problem here.

"The operation couldn’t be completed. (SwiftyEOSErrorDomain error 80000.)"

转账 私钥 账号 都没问题
报这个错 可能什么原因呢?

在 pushTransaction 这一步 报错

 let transfer = Transfer()
        transfer.from = "eoseoseoseos"
        transfer.to = "soesoesoesoe"
        transfer.quantity = "0.0001 EOS"
        transfer.memo = "test"
        
        Currency.transferCurrency(transfer: transfer, code: "eosio.token", 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.")
            }
        })

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.