Awesome
title: "uPort Android SDK" index: 1 category: "android-sdk" type: "content"
uPort Android SDK
Identity for your Android dApps.
This is a preview version of the uPort android SDK. Many intended features are still missing, and the ones already present are under heavy development. Expect some breaking changes
Development planning is done at https://www.pivotaltracker.com/n/projects/2198688
Installation
This SDK is available through jitpack
In your main build.gradle
file, add:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
//...
}
}
In your application build.gradle
file, add:
def uport_sdk_version = "0.5.1"
dependencies {
//...
// core SDK
implementation "com.github.uport-project.uport-android-sdk:sdk:$uport_sdk_version"
}
Usage
Configure uPort in your Application class
override fun onCreate() {
val config = Uport.Configuration()
.setApplicationContext(this)
Uport.initialize(config)
}
defaultAccount
This preview version of the SDK has the concept of defaultAccount
as a nullable field in the
Uport
object.
If there is no default account when a new one is created, it becomes the default.
Uport.defaultAccount?.address // Returns the mnid address of the default account
Uport.defaultAccount?.publicAddress // Returns the hex address of the default account
Uport.defaultAccount?.network // Returns the network id of the default account
//returns the ETH balance of the deviceAddress (measured in wei)
Uport.defaultAccount?.getBalance() { err, balance ->
// do something with balance or respond to err
}
//or as a coroutine:
val balanceInWei = Uport.defaultAccount?.getBalance()
Account Creation
if (Uport.defaultAccount == null) {
Uport.createAccount(network = Networks.rinkeby) { err, account ->
// update UI to reflect the existence of a defaultAccount
}
}
In case the app gets killed during the account creation process, the createAccount
method will
try to resume the process where it left off. It can be instructed to start from scratch, but that
may cost additional fuel.
Account management
Account
objects have a handle
field that can be used to refer to them in the future.
The handle right now is an ethereum address but it should be treated as an opaque string,
as it will change in a future release. You should not send funds to that address.
Key management
The signer
library is used to create and manage keys for uport accounts.
Read full details in key management documentation
Ethereum interaction
uPort SDK lets you create, sign, and submit Ethereum transactions.
This SDK preview version uses simple KeyPair accounts which require self-funding. There is also support for proxy-contract accounts and metaTransactions but it is not used by default any more.
//transfer value
val destination: String = "0x010101...."
val amountInWei = BigInteger.valueOf(1_000_000_000)
Uport.defaultAccount?.send(activity, destination, amountInWei) { err, txHash ->
// Update UI to indicate that transaction has been sent and is confirming
Networks.rinkeby.awaitConfirmation(txHash) { err, receipt ->
// Complete operation in UX
}
}
//`send` can also be used in coroutines
//call contract
val contractAddress = "0x010101..."
val data : ByteArray = <ABI encoded contract method call>
val txHash : String = Uport.defaultAccount?.send(activity, contractAddress, data)
val receipt = Networks.rinkeby.awaitConfirmation(txHash)
off-chain interaction
Off-chain interaction is essentially signing and verifying JWTs using specific JWT algorithms.
Verification of such tokens implies resolving a
Decentralized Identity (DID) document
that will contain the keys or address that should match a JWT signature.
To obtain a DIDDocument
one needs to use a DIDResolver
.
The UniversalDID
is a global registry of DIDResolver
s for apps using the SDK.
During SDK initialization this registry gets populated with default resolvers for
uport-did,
ethr-did
and https-did
You can register your own resolver(s) using UniversalDID.registerResolver(resolver)
Registering a new resolver that resolves the same DID method will override the previous one.
These DIDDocument
s are used during verification of compatible JWT tokens.
verify a JWT token
//in a coroutine context:
val tokenPayload : JWTPayload? = JWTTools().verify(token)
if (tokenPayload != null) {
//verified
} else {
//token cannot be verified
}
create a JWT token
val payload = mapOf( "claims" to mapOf( "name" to "R Daneel Olivaw" ) )
val signer = KPSigner("0x1234")
val issuer = "did:ethr:0x${signer.getAddress()}"
//in a coroutine context
val jwt : String = JWTTools().create(payload, issuer, signer)
Encrypted messaging
//compute an encryption publicKey starting from a private key (can be an ethereum private key)
val publicKey = Crypto.getEncryptionPublicKey(privateKeyBytes)
//encrypt a message with an intended recipient
val encryptedBundle = Crypto.encrypt("hello world", recipientPublicKeyBase64)
val serializedMessage = encryptedBundle.toJson()
//decrypt a message
val receivedBundle = EncryptedMessage.fromJson(serializedMessage)
val decryptedMessage = Crypto.decrypt(receivedBundle, recipientSecretKey)
Dependencies
- These libraries use KEthereum for a lot of the ethereum related work.
- The smart-contract binding code is generated using bivrost-kotlin
- The off-chain/JWT interactions rely on kotlin-did-jwt
- Protected Key management is done by uport-android-signer
Currently there is a transient dependency on spongycastle but that may be removed when pure kotlin implementations of the required cryptographic primitives become available.
Contributing
Want to contribute to uport-android-sdk? Cool, please read our contribution guidelines to get an understanding of the process we use for making changes to this repo.
Changelog
see CHANGELOG.md