Skip to content

Commit

Permalink
Merge branch 'develop' into CSS-127
Browse files Browse the repository at this point in the history
  • Loading branch information
lazutkin-andrey authored Apr 10, 2021
2 parents 6628990 + 8896265 commit 818e171
Show file tree
Hide file tree
Showing 18 changed files with 478 additions and 485 deletions.
168 changes: 85 additions & 83 deletions Example/TangemSdkExample/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

115 changes: 36 additions & 79 deletions Example/TangemSdkExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ViewController: UIViewController {
@IBOutlet weak var walletIndexLabel: UILabel!
@IBOutlet weak var walletMaxIndexLabel: UILabel!
@IBOutlet weak var walletIndexSlider: UISlider!
@IBOutlet weak var isReusableSwitch: UISwitch!
@IBOutlet weak var prohibitPurgeWalletSwitch: UISwitch!

lazy var tangemSdk: TangemSdk = {
Expand All @@ -34,6 +35,7 @@ class ViewController: UIViewController {
var savedFiles: [File]?
var filesDataCounter: Int?
var prohibitPurgeWallet: Bool = false
var isReusableWallet: Bool = true

var walletIndex: Int = 0
var walIn: WalletIndex {
Expand All @@ -58,6 +60,7 @@ class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
prohibitPurgeWalletSwitch.isOn = prohibitPurgeWallet
isReusableSwitch.isOn = isReusableWallet
}

private func updateWalletIndex(to index: Int) {
Expand All @@ -69,6 +72,10 @@ class ViewController: UIViewController {
prohibitPurgeWallet = sender.isOn
}

@IBAction func isReusableSwitchChanged(_ sender: UISwitch) {
isReusableWallet = sender.isOn
}

@IBAction func walletIndexUpdate(_ sender: UISlider) {
let step: Float = 1
let roundedValue = round(sender.value / step) * step
Expand All @@ -79,7 +86,7 @@ class ViewController: UIViewController {
@IBAction func scanCardTapped(_ sender: UIButton) {
sender.showActivityIndicator()
timer.start()
tangemSdk.scanCard(onlineVerification: false) {[unowned self] result in
tangemSdk.scanCard { [unowned self] result in
switch result {
case .success(let card):
self.card = card
Expand All @@ -98,68 +105,35 @@ class ViewController: UIViewController {
}
}

@IBAction func scanWalletByIndexTapped(_ sender: UIButton) {
guard card != nil else {
self.log("Please, scan card before")
return
}

sender.showActivityIndicator()
timer.start()
tangemSdk.scanCard(onlineVerification: false, walletIndex: walIn) { [unowned self] (result) in
switch result {
case .success(let card):
let maxWalletIndex = (card.walletsCount ?? 1) - 1
self.walletIndexSlider.maximumValue = Float(maxWalletIndex)
self.walletMaxIndexLabel.text = "\(maxWalletIndex)"
self.logView.text = ""
self.timer.stop()
self.log("read result: \(card)")
case .failure(let error):
self.handle(error)
}
sender.hideActivityIndicator()
}
}

@IBAction func scanWalletByPubKeyTapped(_ sender: UIButton) {
guard card != nil else {
@IBAction func signHashTapped(_ sender: UIButton) {
let hash = getRandomHash()
guard let cardId = card?.cardId else {
self.log("Please, scan card before")
return
}

guard let pubkey = walletPublicKey else {
return
}
guard let publicKey = walletPublicKey else { return }

sender.showActivityIndicator()
timer.start()
tangemSdk.scanCard(onlineVerification: false, walletIndex: .publicKey(pubkey)) { [unowned self] (result) in
tangemSdk.sign(hash: hash, walletPublicKey: publicKey, cardId: cardId, initialMessage: Message(header: "Signing hashes", body: "Signing hashes with wallet with pubkey: \(publicKey.asHexString())")) { [unowned self] result in
switch result {
case .success(let card):
let maxWalletIndex = (card.walletsCount ?? 1) - 1
self.walletIndexSlider.maximumValue = Float(maxWalletIndex)
self.walletMaxIndexLabel.text = "\(maxWalletIndex)"
self.logView.text = ""
self.timer.stop()
self.log("read result: \(card)")
case .success(let signResponse):
self.log(signResponse)
case .failure(let error):
self.handle(error)
}
sender.hideActivityIndicator()
}
}

@IBAction func signHashesTapped(_ sender: Any) {
let hashes = (0..<1).map {_ -> Data in getRandomHash()}
let hashes = (0..<5).map {_ -> Data in getRandomHash()}
guard let cardId = card?.cardId else {
self.log("Please, scan card before")
return
}

guard let publicKey = walletPublicKey else { return }

tangemSdk.sign(hashes: hashes, cardId: cardId, walletPublicKey: publicKey, initialMessage: Message(header: "Signing hashes", body: "Signing hashes with wallet with pubkey: \(publicKey.asHexString())")) { [unowned self] result in
tangemSdk.sign(hashes: hashes, walletPublicKey: publicKey, cardId: cardId, initialMessage: Message(header: "Signing hashes", body: "Signing hashes with wallet with pubkey: \(publicKey.asHexString())")) { [unowned self] result in
switch result {
case .success(let signResponse):
self.log(signResponse)
Expand Down Expand Up @@ -202,10 +176,10 @@ class ViewController: UIViewController {
let issuerKey = Data(hexString: "")
let sig = Secp256k1Utils.sign(Data(hexString: cardId) + sampleData + newCounter.bytes4, with: issuerKey)!

tangemSdk.writeIssuerData(cardId: cardId,
issuerData: sampleData,
tangemSdk.writeIssuerData(issuerData: sampleData,
issuerDataSignature: sig,
issuerDataCounter: newCounter) { [unowned self] result in
issuerDataCounter: newCounter,
cardId: cardId) { [unowned self] result in
switch result {
case .success(let issuerDataResponse):
self.log(issuerDataResponse)
Expand Down Expand Up @@ -251,11 +225,11 @@ class ViewController: UIViewController {
let startSig = Secp256k1Utils.sign(Data(hexString: cardId) + newCounter.bytes4 + sampleData.count.bytes2, with: issuerKey)!
let finalSig = Secp256k1Utils.sign(Data(hexString: cardId) + sampleData + newCounter.bytes4, with: issuerKey)!

tangemSdk.writeIssuerExtraData(cardId: cardId,
issuerData: sampleData,
tangemSdk.writeIssuerExtraData(issuerData: sampleData,
startingSignature: startSig,
finalizingSignature: finalSig,
issuerDataCounter: newCounter) { [unowned self] result in
issuerDataCounter: newCounter,
cardId: cardId) { [unowned self] result in
switch result {
case .success(let writeResponse):
self.log(writeResponse)
Expand Down Expand Up @@ -284,10 +258,10 @@ class ViewController: UIViewController {
default:
curve = .secp256k1
}
walletConfig = WalletConfig(isReusable: true, prohibitPurgeWallet: prohibitPurgeWallet, curveId: curve, signingMethods: .signHash)
walletConfig = WalletConfig(isReusable: isReusableWallet, prohibitPurgeWallet: prohibitPurgeWallet, curveId: curve, signingMethods: .signHash)
}

tangemSdk.createWallet(cardId: cardId, config: walletConfig) { [unowned self] result in
tangemSdk.createWallet(config: walletConfig, cardId: cardId) { [unowned self] result in
switch result {
case .success(let response):
self.log(response)
Expand All @@ -299,23 +273,6 @@ class ViewController: UIViewController {

}

@IBAction func purgeWalletTapped(_ sender: Any) {
guard let cardId = card?.cardId else {
self.log("Please, scan card before")
return
}

tangemSdk.purgeWallet(cardId: cardId, walletIndex: walIn) { [unowned self] result in
switch result {
case .success(let response):
self.log(response)
case .failure(let error):
self.handle(error)
//handle completion. Unlock UI, etc.
}
}
}

@IBAction func purgeWalletByPubkeyTapped(_ sender: Any) {
guard let cardId = card?.cardId else {
self.log("Please, scan card before")
Expand All @@ -326,7 +283,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.purgeWallet(cardId: cardId, walletIndex: .publicKey(publicKey)) { [unowned self] result in
tangemSdk.purgeWallet(walletPublicKey: publicKey, cardId: cardId) { [unowned self] result in
switch result {
case .success(let response):
self.log(response)
Expand Down Expand Up @@ -362,7 +319,7 @@ class ViewController: UIViewController {
}
let userData = Data(hexString: "0102030405060708")

tangemSdk.writeUserData(cardId: cardId, userData: userData, userCounter: 2){ [unowned self] result in
tangemSdk.writeUserData(userData: userData, userCounter: 2, cardId: cardId){ [unowned self] result in
switch result {
case .success(let response):
self.log(response)
Expand All @@ -380,7 +337,7 @@ class ViewController: UIViewController {
}
let userData = Data(hexString: "01010101010101")

tangemSdk.writeUserProtectedData(cardId: cardId, userProtectedData: userData, userProtectedCounter: 1 ){ [unowned self] result in
tangemSdk.writeUserProtectedData(userProtectedData: userData, userProtectedCounter: 1, cardId: cardId){ [unowned self] result in
switch result {
case .success(let response):
self.log(response)
Expand Down Expand Up @@ -437,7 +394,7 @@ class ViewController: UIViewController {
return
}
(sender as! UIButton).showActivityIndicator()
tangemSdk.verify(cardId: cardId, online: true) { result in
tangemSdk.verify(online: true, cardId: cardId) { result in
switch result {
case .success(let response):
self.log(response)
Expand All @@ -454,7 +411,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.changePin1(cardId: cardId, pin: nil) { result in
tangemSdk.changePin1(pin: nil, cardId: cardId) { result in
switch result {
case .success(let response):
self.log(response)
Expand All @@ -470,7 +427,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.changePin2(cardId: cardId, pin: nil) { result in
tangemSdk.changePin2(pin: nil, cardId: cardId) { result in
switch result {
case .success(let response):
self.log(response)
Expand Down Expand Up @@ -503,7 +460,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.readFiles(cardId: cardId, readSettings: ReadFilesTaskSettings(readPrivateFiles: false)) { (result) in
tangemSdk.readFiles(readPrivateFiles: false, cardId: cardId) { (result) in
switch result {
case .success(let response):
self.savedFiles = response.files
Expand Down Expand Up @@ -600,7 +557,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.deleteFiles(cardId: cardId, indicesToDelete: [savedFiles[0].fileIndex]) { (result) in
tangemSdk.deleteFiles(indicesToDelete: [savedFiles[0].fileIndex], cardId: cardId) { (result) in
switch result {
case .success:
self.savedFiles = nil
Expand All @@ -627,7 +584,7 @@ class ViewController: UIViewController {
return
}

tangemSdk.deleteFiles(cardId: cardId, indicesToDelete: nil) { (result) in
tangemSdk.deleteFiles(indicesToDelete: nil, cardId: cardId) { (result) in
switch result {
case .success:
self.savedFiles = nil
Expand Down Expand Up @@ -655,8 +612,8 @@ class ViewController: UIViewController {
}

let file = savedFiles[0]
file.fileSettings = file.fileSettings == .public ? .private : .public
tangemSdk.changeFilesSettings(cardId: cardId, files: [file]) { (result) in
let newSettings: FileSettings = file.fileSettings == .public ? .private : .public
tangemSdk.changeFilesSettings(changes: [FileSettingsChange(fileIndex: file.fileIndex, settings: newSettings)], cardId: cardId) { (result) in
switch result {
case .success:
self.savedFiles = nil
Expand Down
61 changes: 46 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

[![Version](https://img.shields.io/cocoapods/v/TangemSdk.svg?style=flat)](https://cocoapods.org/pods/TangemSdk)
[![License](https://img.shields.io/cocoapods/l/TangemSdk.svg?style=flat)](https://cocoapods.org/pods/TangemSdk)
[![Platform](https://img.shields.io/cocoapods/p/TangemSdk.svg?style=flat)](https://cocoapods.org/pods/TangemSdk)
Expand All @@ -8,19 +9,20 @@
The Tangem card is a self-custodial hardware wallet for blockchain assets. The main functions of Tangem cards are to securely create and store a private key from a blockchain wallet and sign blockchain transactions. The Tangem card does not allow users to import/export, backup/restore private keys, thereby guaranteeing that the wallet is unique and unclonable.

- [Getting Started](#getting-started)
- [Requirements](#requirements)
- [Installation](#installation)
- [CocoaPods](#cocoapods)
- [Requirements](#requirements)
- [Installation](#installation)
- [CocoaPods](#cocoapods)
- [Usage](#usage)
- [Initialization](#initialization)
- [Basic usage](#basic-usage)
- [Scan card](#scan-card)
- [Sign](#sign-hashes)
- [Advanced usage](#advanced-usage)
- [Starting custom session](#starting-custom-session)
- [Initialization](#initialization)
- [Basic usage](#basic-usage)
- [Scan card](#scan-card)
- [Sign hash](#sign-hash)
- [Sign hashes](#sign-hashes)
- [Advanced usage](#advanced-usage)
- [Starting custom session](#starting-custom-session)
- [Customization](#customization)
- [UI](#ui)
- [Localization](#localization)
- [UI](#ui)
- [Localization](#localization)


## Getting Started
Expand All @@ -34,7 +36,8 @@ SDK can be imported to iOS 11, but it will work only since iOS 13.

1) Configure your app to detect NFC tags. Turn on Near Field Communication Tag Reading under the Capabilities tab for the project’s target (see [Add a capability to a target](https://help.apple.com/xcode/mac/current/#/dev88ff319e7)).

2) Add the [NFCReaderUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nfcreaderusagedescription) key as a string item to the Info.plist file. For the value, enter a string that describes the reason the app needs access to the device’s NFC reader:

2) Add the [NFCReaderUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nfcreaderusagedescription) key as a string item to the Info.plist file. For the value, enter a string that describes the reason the app needs access to the device’s NFC reader:

```xml
<key>NFCReaderUsageDescription</key>
<string>Some reason</string>
Expand Down Expand Up @@ -114,17 +117,45 @@ tangemSdk.scanCard { result in
}
```

#### Sign
Method `sign(hashes: hashes, cardId: cardId)` allows you to sign one or multiple hashes. The SIGN command will return a corresponding array of signatures.
#### Sign hash
Method `sign(hash: hash, cardId: cardId)` allows you to sign single hash. The SIGN command will return a corresponding signature.

**Arguments:**

| Parameter | Description |
| ------------ | ------------ |
| hash | Hash to be signed by card |
| cardId | *(Optional)* If cardId is passed, the sign command will be performed only if the card |


Example:
```swift
// Creates random hash with length = 32
let hash = Data((0..<32).map { _ in UInt8(arc4random_uniform(255)) })
let cardId = ...

tangemSdk.sign(hash: hash, cardId: cardId) { result in
switch result {
case .success(let signResponse):
print("Result: \(signResponse)")
case .failure(let error):
print("Completed with error: \(error.localizedDescription), details: \(error)")
}
}
```

#### Sign hashes
Method `sign(hashes: hashes, cardId: cardId)` allows you to sign multiple hashes. The SIGN command will return a corresponding array of signatures.

**Arguments:**

| Parameter | Description |
| ------------ | ------------ |
| hashes | Array of hashes to be signed by card |
| cardId | *(Optional)* If cardId is passed, the sign command will be performed only if the card |


Example:
```swift
let hashes = [hash1, hash2]
let cardId = ...
Expand All @@ -144,7 +175,7 @@ tangemSdk.sign(hashes: hashes, cardId: cardId) { result in
Method `tangemSdk.createWallet(cardId: cardId)` will create a new wallet on the card. A key pair `WalletPublicKey` / `WalletPrivateKey` is generated and securely stored in the card.

##### Purge Wallet
Method `tangemSdk.purgeWallet(cardId: cardId)` deletes all wallet data.
Method `tangemSdk.purgeWallet(walletPublicKey: Data, cardId: cardId)` searching wallet with specified `WalletPublicKey` and deletes all information related to this wallet.

#### Issuer data
Card has a special 512-byte memory block to securely store and update information in COS. For example, this mechanism could be employed for enabling off-line validation of the wallet balance and attesting of cards by the issuer (in addition to Tangem’s attestation). The issuer should define the purpose of use, payload, and format of Issuer Data field. Note that Issuer_Data is never changed or parsed by the executable code the Tangem COS.
Expand Down
Loading

0 comments on commit 818e171

Please sign in to comment.