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

Requirements

iOS

iOS 11+ (CoreNFC is required), Xcode 11+ SDK can be imported to iOS 11, but it will work only since iOS 13.

Android

Android with minimal SDK version of 21 and a device with NFC support

Installation

dependencies:
  tangem_sdk: ^0.1.0

Usage

Tangem SDK is a self-sufficient solution that implements a card abstraction model, methods of interaction with the card and interactions with the user via UI.

The easiest way to use the SDK is to call basic methods. The basic method performs one or more operations and, after that, calls completion block with success or error.

Most of functions have the optional cardId argument, if it's passed the operation, it can be performed only with the card with the same card ID. If card is wrong, user will be asked to take the right card. We recommend to set this argument if there is no special need to use any card.

When calling basic methods, there is no need to show the error to the user, since it will be displayed on the NFC popup before it's hidden.

Callback is a simple wrapper for success and error callback functions.

Callback callback = Callback((success) {
    final prettyJson = JsonEncoder.withIndent('  ').convert(success.toJson());
    prettyJson.split("\n").forEach((element) => print(element));
}, (error) {
    if (error is ErrorResponse) {
       print(error.localizedDescription);
    } else {
       print(error);
    }
});

Scan card

Scan card is needed to obtain information from the Tangem card. Optionally, if the card contains a wallet (private and public key pair), it proves that the wallet owns a private key that corresponds to a public one.

TangemSdk.scanCard(callback);

Sign

Allows you to sign one or multiple hashes. The SIGN command will return a corresponding array of signatures.

Arguments:

ParameterDescription
hashesArray of hashes to be signed by card (hex)
cardId(Optional) If cardId is passed, the sign command will be performed only if the card has the same id
TangemSdk.sign(callback, hashes, {TangemSdk.cid: cardId});

Wallet

Create Wallet

Will create a new wallet on the card. A key pair WalletPublicKey / WalletPrivateKey is generated and securely stored in the card.

Arguments:

ParameterDescription
cardId(Optional) If cardId is passed, the createWallet command will be performed only if the card has the same id
TangemSdk.createWallet(callback, {TangemSdk.cid: cardId});
Purge Wallet

Deletes all wallet data.

Arguments:

ParameterDescription
cardId(Optional) If cardId is passed, the purgeWallet command will be performed only if the card has the same id
TangemSdk.purgeWallet(callback, {TangemSdk.cid: cardId});

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.

The issuer has to generate single Issuer Data Key pair Issuer_Data_PublicKey / Issuer_Data_PrivateKey, same for all issuer’s cards. The private key Issuer_Data_PrivateKey is permanently stored in a secure back-end of the issuer (e.g. HSM). The non-secret public key Issuer_Data_PublicKey is stored both in COS (during personalization) and issuer’s host application that will use it to validate Issuer_Data field.

Write issuer data

Writes 512-byte Issuer_Data field to the card.

Arguments:

ParameterDescription
issuerDataData to be written to the card (hex)
issuerDataSignatureIssuer’s signature of issuerData with Issuer_Data_PrivateKey(hex)
issuerDataCounter(Optional) Counter that protect issuer data against replay attack. When flag Protect_Issuer_Data_Against_Replay set in the card configuration then this value is mandatory and must increase on each execution of writeIssuerData command.
cardId(Optional) If cardId is passed, the writeIssuerData command will be performed only if the card has the same id
TangemSdk.writeIssuerData(callback, issuerData, issuerDataSignature, {
      TangemSdk.cid: cardId,
      TangemSdk.issuerDataCounter: issuerDataCounter,
    });
Write issuer extra data

If 512 bytes are not enough, you can use this method to save up to 40 kylobytes.

ParameterDescription
issuerDataData to be written to the card (hex)
startingSignatureIssuer’s signature of SHA256(cardId, Size) or SHA256(cardId, Size, issuerDataCounter) with Issuer_Data_PrivateKey (hex)
finalizingSignatureIssuer’s signature of SHA256(cardId, issuerData) or SHA256(cardId, issuerData, issuerDataCounter) with Issuer_Data_PrivateKey (hex)
issuerDataCounter(Optional) Сounter that protect issuer data against replay attack. When flag Protect_Issuer_Data_Against_Replay set in the card configuration then this value is mandatory and must increase on each execution of writeIssuerData command.
cardId(Optional) If cardId is passed, the writeIssuerExtraData command will be performed only if the card has the same id
TangemSdk.writeIssuerExtraData(
        callback, issuerData, startingSignature, finalizingSignature, {
      TangemSdk.cid: cardId,
      TangemSdk.issuerDataCounter: issuerDataCounter,
    });
Read issuer data

Returns 512-byte Issuer_Data field and its issuer’s signature.

ParameterDescription
cardId(Optional) If cardId is passed, the readIssuerData command will be performed only if the card has the same id
TangemSdk.readIssuerData(callback, {TangemSdk.cid: cardId});
Read issuer extra data

Returns Issuer_Extra_Data field.

ParameterDescription
cardId(Optional) If cardId is passed, the readIssuerExtraData command will be performed only if the card has the same id
TangemSdk.readIssuerExtraData(callback, {TangemSdk.cid: cardId});

User data

Write user data

Write some of User_Data and User_Counter fields. User_Data is never changed or parsed by the executable code the Tangem COS. The App defines purpose of use, format and it's payload. For example, this field may contain cashed information from blockchain to accelerate preparing new transaction.

ParameterDescription
userDataUser data to be written (hex)
userCounter(Optional) Counter, that initial values can be set by App and increased on every signing of new transaction (on SIGN command that calculate new signatures). The App defines purpose of use. For example, this fields may contain blockchain nonce value.
cardId(Optional) If cardId is passed, the writeUserData command will be performed only if the card has the same id
TangemSdk.writeUserData(callback, userData, {
      TangemSdk.cid: cardId,
      TangemSdk.userCounter: userCounter,
    });
Read user data

Returns User Data

ParameterDescription
cardId(Optional) If cardId is passed, the readUserData command will be performed only if the card has the same id
TangemSdk.readUserData(callback, {TangemSdk.cid: cardId});

Pin codes

Access code (PIN1) restricts access to the whole card. App must submit the correct value of Access code in each command.

Passcode (PIN2) is required to sign a transaction or to perform some other commands entailing a change of the card state.

ParameterDescription
cardId(Optional) If cardId is passed, the setPinCode command will be performed only if the card has the same id
TangemSdk.setPinCode(PinType.PIN1, callback, {TangemSdk.cid: cardId});
TangemSdk.setPinCode(PinType.PIN2, callback, {TangemSdk.cid: cardId});

Libraries

card_response
extensions
other_responses
sdk
sdk_plugin
tangem_sdk