Skip to content

Commit

Permalink
ethereum and tezos transaction signing complete for android
Browse files Browse the repository at this point in the history
  • Loading branch information
Baah Kusi committed Sep 20, 2021
1 parent 38becc7 commit 8725ccc
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 12 deletions.
38 changes: 34 additions & 4 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ rootProject.allprojects {
repositories {
google()
jcenter()
maven {
url = uri("https://maven.pkg.github.com/trustwallet/wallet-core")
credentials {
username = "baahkusi"//System.getenv("GITHUB_USER")
password = "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" //System.getenv("GITHUB_TOKEN")
}
}
}
}

Expand All @@ -35,10 +42,13 @@ android {
}

dependencies {
implementation "com.trustwallet:wallet-core:0.12.31"
implementation "com.trustwallet:wallet-core:2.6.25"
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
54 changes: 50 additions & 4 deletions android/src/main/kotlin/africa/ejara/trustdart/TrustdartPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package africa.ejara.trustdart

import androidx.annotation.NonNull
import org.json.JSONObject

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
Expand All @@ -12,6 +13,7 @@ import io.flutter.plugin.common.MethodChannel.Result
import wallet.core.jni.HDWallet
import wallet.core.jni.CoinType
import wallet.core.jni.BitcoinAddress
import wallet.core.java.AnySigner

/** TrustdartPlugin */
class TrustdartPlugin: FlutterPlugin, MethodCallHandler {
Expand Down Expand Up @@ -56,7 +58,7 @@ class TrustdartPlugin: FlutterPlugin, MethodCallHandler {
val address: Map<String, String?>? = generateAddressForCoin(path, coin)
if (address == null) result.error("address_null", "failed to generate address", null) else result.success(address)
} else {
result.error("arguments_null", "$path and $coin cannot be null", null)
result.error("arguments_null", "[path] and [coin] cannot be null", null)
}
}
"validateAddressForCoin" -> {
Expand All @@ -69,8 +71,16 @@ class TrustdartPlugin: FlutterPlugin, MethodCallHandler {
result.error("arguments_null", "$address and $coin cannot be null", null)
}
}
"buildTransaction" -> {
result.notImplemented()
"buildAndSignTransaction" -> {
val coin: String? = call.argument("coin")
val path: String? = call.argument("path")
val txData: Map<String, String>? = call.argument("txData")
if (txData != null && coin != null && path != null) {
val txHash: String? = buildAndSignTransaction(coin, path, txData)
if (txHash == null) result.error("txhash_null", "failed to buid and sign transaction", null) else result.success(txHash)
} else {
result.error("arguments_null", "[txData], [coin] and [path] cannot be null", null)
}
}
else -> result.notImplemented()
}
Expand All @@ -81,17 +91,19 @@ class TrustdartPlugin: FlutterPlugin, MethodCallHandler {
}

private fun generateAddressForCoin(path: String, coin: String): Map<String, String?>? {
val privateKey = wallet.getKey(path)
return when(coin) {
"BTC" -> {
val privateKey = wallet.getKey(CoinType.BITCOIN, path)
val publicKey = privateKey.getPublicKeySecp256k1(true)
val address = BitcoinAddress(publicKey, CoinType.BITCOIN.p2pkhPrefix())
mapOf("legacy" to address.description(), "segwit" to CoinType.BITCOIN.deriveAddress(privateKey))
}
"ETH" -> {
val privateKey = wallet.getKey(CoinType.ETHEREUM, path)
mapOf("legacy" to CoinType.ETHEREUM.deriveAddress(privateKey))
}
"XTZ" -> {
val privateKey = wallet.getKey(CoinType.TEZOS, path)
mapOf("legacy" to CoinType.TEZOS.deriveAddress(privateKey))
}
else -> null
Expand All @@ -112,4 +124,38 @@ class TrustdartPlugin: FlutterPlugin, MethodCallHandler {
else -> false
}
}

private fun buildAndSignTransaction(coin: String, path: String, txData: Map<String, String>): String? {
return when(coin) {
"XTZ" -> {
buildAndSignTezosTransaction(path, txData)
}
"ETH" -> {
buildAndSignEthereumTransaction(path, txData)
}
"BTC" -> {
buildAndSignBitcoinTransaction(path, txData)
}
else -> null
}
}

private fun buildAndSignTezosTransaction(path: String, txData: Map<String, String>): String? {
val privateKey = wallet.getKey(CoinType.TEZOS, path)
val opJson = JSONObject(txData).toString();
val result = AnySigner.signJSON(opJson, privateKey.data(), CoinType.TEZOS.value())
return result
}

private fun buildAndSignEthereumTransaction(path: String, txData: Map<String, String>): String? {
val privateKey = wallet.getKey(CoinType.ETHEREUM, path)
val opJson = JSONObject(txData).toString();
val result = AnySigner.signJSON(opJson, privateKey.data(), CoinType.ETHEREUM.value())
return result
}

private fun buildAndSignBitcoinTransaction(path: String, txData: Map<String, String>): String? {
val privateKey = wallet.getKey(CoinType.BITCOIN, path)
return null;
}
}
57 changes: 54 additions & 3 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,50 @@ class _MyAppState extends State<MyApp> {
initPlatformState();
}

Map _getTezosOperation() {
return {
"operationList": {
"branch": "BL8euoCWqNCny9AR3AKjnpi38haYMxjei1ZqNHuXMn19JSQnoWp",
"operations": [{
"source": "tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW",
"fee": 1272,
"counter": 30738,
"gasLimit": 10100,
"storageLimit": 257,
"kind": 107,
"revealOperationData": {
"publicKey": "QpqYbIBypAofOj4qtaWBm7Gy+2mZPFAEg3gVudxVkj4="
}
}, {
"source": "tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW",
"fee": 1272,
"counter": 30739,
"gasLimit": 10100,
"storageLimit": 257,
"kind": 108,
"transactionOperationData": {
"destination": "tz1XVJ8bZUXs7r5NV8dHvuiBhzECvLRLR3jW",
"amount": 1
}
}]
}
};
}

Map _getEthereumOperation() {
return {
"chainId": "AQ==",
"gasPrice": "1pOkAA==",
"gasLimit": "Ugg=",
"toAddress": "0x7d8bf18C7cE84b3E175b339c4Ca93aEd1dD166F1",
"transaction": {
"transfer": {
"amount":"A0i8paFgAA=="
}
}
};
}

// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
Expand All @@ -35,9 +79,12 @@ class _MyAppState extends State<MyApp> {
String dondo = "imitate embody law mammal exotic transfer roof hope price swift ordinary uncle";
bool wallet = await Trustdart.importWalletFromMnemonic(dondo);
print(wallet);
Map btcAddress = await Trustdart.generateAddressForCoin('BTC', "m/44'/0'/0'/0/0");
Map ethAddress = await Trustdart.generateAddressForCoin('ETH', "m/44'/60'/0'/0/0");
Map xtzAddress = await Trustdart.generateAddressForCoin('XTZ', "m/44'/1729'/0'/0'");
String btcPath = "m/44'/0'/0'/0/0";
String ethPath = "m/44'/60'/0'/0/0";
String xtzPath = "m/44'/1729'/0'/0'";
Map btcAddress = await Trustdart.generateAddressForCoin('BTC', btcPath);
Map ethAddress = await Trustdart.generateAddressForCoin('ETH', ethPath);
Map xtzAddress = await Trustdart.generateAddressForCoin('XTZ', xtzPath);
print([btcAddress, ethAddress, xtzAddress]);
bool isBtcLegacyValid = await Trustdart.validateAddressForCoin('BTC', btcAddress['legacy']);
bool isBtcSegWitValid = await Trustdart.validateAddressForCoin('BTC', btcAddress['segwit']);
Expand All @@ -48,6 +95,10 @@ class _MyAppState extends State<MyApp> {
bool invalidETH = await Trustdart.validateAddressForCoin('ETH', xtzAddress['legacy']);
bool invalidXTZ = await Trustdart.validateAddressForCoin('XTZ', btcAddress['legacy']);
print([invalidBTC, invalidETH, invalidXTZ]);

String xtzTx = await Trustdart.buildAndSignTransaction('XTZ', xtzPath, _getTezosOperation());
String ethTx = await Trustdart.buildAndSignTransaction('ETH', ethPath, _getEthereumOperation());
print([xtzTx, ethTx]);
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
Expand Down
9 changes: 9 additions & 0 deletions lib/trustdart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,13 @@ class Trustdart {
});
return isAddressValid;
}

static Future<String> buildAndSignTransaction(String coin, String path, Map txData) async {
final txHash = await _channel.invokeMethod('buildAndSignTransaction', <String, dynamic> {
'coin': coin,
'txData': txData,
'path': path,
});
return txHash;
}
}
3 changes: 3 additions & 0 deletions trustdart.iml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
<excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/trustdart/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/trustdart/build" />
<excludeFolder url="file://$MODULE_DIR$/example/ios/.symlinks/plugins/trustdart/.dart_tool" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
Expand Down

0 comments on commit 8725ccc

Please sign in to comment.