Skip to content
This repository has been archived by the owner on Aug 13, 2021. It is now read-only.

Commit

Permalink
Implement transfer operation (#22)
Browse files Browse the repository at this point in the history
* Implement transfer operation

* fix README.md

* Add demo

* set gif size

* set gif size

* Format gifs

* rename link

* fixes on comments

* add sugar

* Fix docs

* Add test coverage

* Add action
  • Loading branch information
vcoolish authored Oct 10, 2020
1 parent 521ff51 commit c6bc725
Show file tree
Hide file tree
Showing 20 changed files with 526 additions and 61 deletions.
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

## Getting started

The TrustSDK lets you sign Ethereum transactions and messages so that you can bulid a native DApp without having to worry about keys or wallets. Follow these instructions to integrate TrustSDK in your native DApp.
The TrustSDK lets you sign Ethereum transactions and messages so that you can build a native DApp without having to worry about keys or wallets. Follow these instructions to integrate TrustSDK in your native DApp.

## Demo
Get accounts|Sign transaction|Send transaction
-|-|-
![Accounts](docs/accounts.gif)|![Sign](docs/sign.gif)|![Send](docs/send.gif)

## Add dependency

Expand All @@ -28,7 +31,7 @@ dependencies {

## Handle Trust callbacks

In your signing activity `Trust`.
### Deprecated method used now only for *get accounts* request:

Override `onActivityResult` to obtain the signing result. Handle the response data and pass onSuccessListener and onFailureListener.

Expand All @@ -46,14 +49,61 @@ Override `onActivityResult` to obtain the signing result. Handle the response da
}
```

### Sign a transaction
### For all other requests

Add deep link intent filter to your `AndroidManifest.xml`:
```xml
<activity
...
<intent-filter android:autoVerify="true">
...
<action android:name="android.intent.action.VIEW" />
<data android:scheme="app_scheme" android:host="tx_callback" />
```

Override 'onNewIntent' if your activity is singleTask or 'onCreate' if not, and handle sdk request callback:
```kotlin
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val txCallback = Trust.handleTransferResult(intent)
txCallback?.signature // Signed transaction in hex format if you requested sign
txCallback?.hash // Hash id of transferred transaction
txCallback?.isCancelled // User has cancelled your transaction request
}
```

## Build a request

### Get Accounts

To get accounts use this code:

```kotlin
getAccountsCall = Trust.execute(this, AccountsRequest(Coin.ETHEREUM, Coin.WAVES, Coin.ALGORAND, Coin.ATOM, Coin.BINANCE, Coin.BITCOINCASH))
```

### Sign a transaction

To sign or send a transaction use this code:

```kotlin
val operation = TransferOperation.Builder()
.action(ActionType.SIGN) // ActionType - Send or Sign transaction request
.callback(Uri.parse("app_scheme://tx_callback")) // callback deep link Uri to app initialized request.
.coin(60) // Slip44 index
.tokenId("0x6B175474E89094C44Da98b954EedeAC495271d0F") // token (optional), following standard of unique identifier on the blockhain as smart contract address or asset ID
.to("0xF36f148D6FdEaCD6c765F8f59D4074109E311f0c") // Recipient address
.amount(BigDecimal("1")) // Transaction amount in human-readable (unit) format
.feeLimit(21000L) // (Optional) You can set your custom fee limit in subunit format
.feePrice(BigInteger("100000000000")) // (Optional) You can set your custom fee price in subunit format
.nonce(2) // (Optional) You can set your custom nonce or sequence
.meta("0xa9059cbb0000000000000000000000000F36f148D6FdEaCD6c765F8f59D4074109E311f0c0000000000000000000000000000000000000000000000000000000000000001") // (Optional) Transaction data in hex format, Memo or Destination tag
.build()
Trust.execute(this, operation)
```

You can find more documentation in [TransferOperation](https://github.com/trustwallet/TrustSDK-Android/blob/master/trust-sdk-client/src/main/java/trust/TransferOperation.kt)

## Example

Trust SDK includes an example project with the above code. To run the example project clone the repo and build the project with Android Studio. Run the app on your emulator or device. Make sure that you have Trust Wallet installed on the device or simulator to test the full callback flow.
Expand Down
16 changes: 8 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 29
compileSdkVersion 30
defaultConfig {
applicationId "com.trustwallet.sdk"
minSdkVersion 21
targetSdkVersion 29
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
Expand All @@ -25,10 +25,10 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
implementation project(':trust-sdk-client')
}
10 changes: 8 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.trustwallet.sdk"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
Expand All @@ -12,12 +12,18 @@
<activity
android:name=".MainActivity"
android:configChanges="orientation"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="app_scheme" android:host="tx_callback" />
</intent-filter>
</activity>
</application>

Expand Down
60 changes: 40 additions & 20 deletions app/src/main/java/com/trustwallet/sdk/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.trustwallet.sdk

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import trust.*
import java.math.BigDecimal
import java.math.BigInteger

class MainActivity : AppCompatActivity() {
private var getAccountsCall: Call<Array<Account>, AccountsRequest>? = null
private var sdkGetAccountsCall: Call<Array<Account>, GetAccountsRequest>? = null
private lateinit var resultText: TextView

Expand All @@ -19,28 +21,53 @@ class MainActivity : AppCompatActivity() {

resultText = findViewById(R.id.result_out)

findViewById<Button>(R.id.get_accounts).setOnClickListener {
getAccountsCall = Trust.execute(this, AccountsRequest(Coin.ETHEREUM, Coin.WAVES, Coin.ALGORAND, Coin.ATOM, Coin.BINANCE, Coin.BITCOINCASH))
}
findViewById<Button>(R.id.sdk_get_accounts).setOnClickListener {
sdkGetAccountsCall = Trust.execute(this, GetAccountsRequest(Coin.ETHEREUM, Coin.WAVES, Coin.ALGORAND, Coin.ATOM, Coin.BINANCE, Coin.BITCOINCASH))
}
findViewById<Button>(R.id.send_transaction).setOnClickListener {
val operation = TransferOperation.Builder()
.action(ActionType.SEND)
.callback(Uri.parse("app_scheme://tx_callback"))
.coin(714)
.to("bnb1sh6nuztt3dcevy4ngmztkpapnvxqy7je0t0udr")
.amount(BigDecimal("0.0001"))
.meta("memo")
.build()
Trust.execute(this, operation)
}
findViewById<Button>(R.id.sign_transaction).setOnClickListener {
val operation = TransferOperation.Builder()
.action(ActionType.SIGN)
.callback(Uri.parse("app_scheme://tx_callback"))
.coin(60)
.tokenId("0x6B175474E89094C44Da98b954EedeAC495271d0F")
.to("0xF36f148D6FdEaCD6c765F8f59D4074109E311f0c")
.amount(BigDecimal("1"))
.feeLimit(21000L)
.feePrice(BigInteger("100000000000"))
.nonce(2)
.meta("0xa9059cbb0000000000000000000000000F36f148D6FdEaCD6c765F8f59D4074109E311f0c0000000000000000000000000000000000000000000000000000000000000001")
.build()
Trust.execute(this, operation)
}
}

if (savedInstanceState != null) {
getAccountsCall = savedInstanceState.getParcelable("get_accounts_call")
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val txCallback = Trust.handleTransferResult(intent)
val result = when {
!txCallback?.hash.isNullOrEmpty() -> txCallback?.hash
!txCallback?.signature.isNullOrEmpty() -> txCallback?.signature
txCallback?.isCancelled == true -> "Cancelled"
else -> throw IllegalStateException()
}
resultText.text = result
Log.d("CALLBACK_RESULT", result!!)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

getAccountsCall?.let {
it.onActivityResult(requestCode, resultCode, data, OnCompleteListener<Array<Account>> { response ->
val result = response.result?.joinToString("\n") { account -> "${account.address.data} ${account.coin.name}" }
resultText.text = result
Log.d("GET_ACCOUNTS", result ?: "")
})
}
sdkGetAccountsCall?.let {
it.onActivityResult(requestCode, resultCode, data, OnCompleteListener<Array<Account>> { response ->
val result = response.result?.joinToString("\n") { account -> "${account.address.data} ${account.coin.name}" }
Expand All @@ -49,11 +76,4 @@ class MainActivity : AppCompatActivity() {
})
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
getAccountsCall.let {
outState.putParcelable("get_accounts_call", getAccountsCall)
}
}
}
14 changes: 10 additions & 4 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
android:layout_height="300dp"
/>
<Button
android:id="@+id/get_accounts"
android:text="@string/get_accounts_deprecated"
android:id="@+id/sdk_get_accounts"
android:text="@string/get_accounts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/sdk_get_accounts"
android:text="@string/get_accounts"
android:id="@+id/send_transaction"
android:text="@string/send_transaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/sign_transaction"
android:text="@string/sign_transaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
<string name="app_name">TrustSdk</string>
<string name="get_accounts">Get Accounts</string>
<string name="get_accounts_deprecated">Get Accounts (Deprecated)</string>
<string name="send_transaction">Send Transaction</string>
<string name="sign_transaction">Sign Transaction</string>
</resources>
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.72'
ext.kotlin_version = '1.4.10'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
}

Expand Down
Binary file added docs/accounts.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/send.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/sign.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useAndroidX=true
android.useAndroidX=true
android.enableJetifier=true
7 changes: 4 additions & 3 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#Tue Apr 21 12:55:32 GMT+07:00 2020
#Sat Oct 10 14:55:23 EEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
android.useAndroidX=true
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
android.useAndroidX=true
android.enableJetifier=true
22 changes: 16 additions & 6 deletions trust-sdk-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ apply plugin: 'com.github.dcendents.android-maven'
group='trust'

android {
compileSdkVersion 29
compileSdkVersion 30

defaultConfig {
minSdkVersion 21
targetSdkVersion 27
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

}

Expand All @@ -33,6 +33,13 @@ android {
artifacts {
archives androidSourcesJar
}

testOptions {
unitTests {
returnDefaultValues = true
includeAndroidResources = true
}
}
}

project.ext {
Expand All @@ -42,9 +49,12 @@ project.ext {
}

dependencies {
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'org.mockito:mockito-android:3.4.6'
testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
repositories {
Expand Down
Loading

0 comments on commit c6bc725

Please sign in to comment.