區塊鏈錢包-android篇

来源:https://www.cnblogs.com/zhjing/p/18061560
-Advertisement-
Play Games

​ 1:使用Protocol Buffers 首先根目錄gradle中添加依賴: classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.3" 然後項目文件中添加plugin,添加依賴包: apply plugin: 'com.google ...



1:使用Protocol Buffers
 首先根目錄gradle中添加依賴:

classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.3"

然後項目文件中添加plugin,添加依賴包:

apply plugin: 'com.google.protobuf'

protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.6.1'
}
plugins {
javalite {
artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
}
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.17.1'
}
}
generateProtoTasks {
all().each { task ->
task.plugins {
javalite {}
grpc {
// Options added to --grpc_out
option 'lite'
}
}
}
}
configurations {
all*.exclude group: 'com.android.support', module: 'support-v13'
}
}

dependencies {
api 'io.grpc:grpc-okhttp:1.17.1'
api 'io.grpc:grpc-protobuf-lite:1.17.1'
api 'io.grpc:grpc-stub:1.17.1'
}
 最後main下添加proto路徑,添加proto文件;

2:tron基礎類
       關於tron的基礎類,我整理了個lib,使用時直接導入lib即可。

主要包括wallet錢包類,管理類等內容。

這裡我主要貼出wallet的代碼

package org.tron.walletserver;

import android.os.Build;
import android.support.annotation.RequiresApi;

import org.tron.common.crypto.ECKey;
import org.tron.common.utils.Utils;

import java.math.BigInteger;

public class Wallet {
private ECKey mECKey = null;

private boolean isWatchOnly = false;
private boolean isColdWallet = false;
private String walletName = "";
private String encPassword = "";
private String address = "";
private byte[] encPrivateKey;
private byte[] publicKey;


public Wallet() {
}

public Wallet(boolean generateECKey) {
    if(generateECKey) {
        mECKey = new ECKey(Utils.getRandom());
    }
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public Wallet(String privateKey) {
    setPrivateKey(privateKey);
}

public boolean isOpen() {
    return mECKey != null && mECKey.getPrivKeyBytes() != null;
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public boolean open(String password) {
    if(encPrivateKey != null) {
        setPrivateKey(AddressUtils.decryptPrivateKey(encPrivateKey, password));
        return isOpen();
    } else {
        return false;
    }
}

public byte[] getPublicKey() {
    return mECKey != null ? mECKey.getPubKey() : publicKey;
}

public void setPublicKey(byte[] publicKey) {
    this.publicKey = publicKey;
}

public byte[] getPrivateKey() {
    return mECKey != null ? mECKey.getPrivKeyBytes() : null;
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void setPrivateKey(String privateKey) {
    if(privateKey != null && !privateKey.isEmpty()) {
        ECKey tempKey = null;
        try {
            BigInteger priK = new BigInteger(privateKey, 16);
            tempKey = ECKey.fromPrivate(priK);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        mECKey = tempKey;
    } else {
        mECKey = null;
    }
}


public boolean isWatchOnly() {
    return isWatchOnly;
}

public void setWatchOnly(boolean watchOnly) {
    isWatchOnly = watchOnly;
}

public boolean isColdWallet() {
    return isColdWallet;
}

public void setColdWallet(boolean coldWallet) {
    isColdWallet = coldWallet;
}

public String getWalletName() {
    return walletName;
}

public void setWalletName(String walletName) {
    this.walletName = walletName;
}

public String getEncryptedPassword() {
    return encPassword;
}

public void setEncryptedPassword(String password) {
    this.encPassword = password;
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public String getAddress() {
    if(mECKey != null) {
        return AddressUtils.encode58Check(mECKey.getAddress());
    }
    else if (publicKey != null){
        return AddressUtils.encode58Check(ECKey.fromPublicOnly(publicKey).getAddress());
    } else {
        return address;
    }
}

public void setAddress(String address) {
    this.address = address;
}

public ECKey getECKey() {
    return mECKey;
}

public byte[] getEncryptedPrivateKey() {
    return encPrivateKey;
}

public void setEncryptedPrivateKey(byte[] encPrivateKey) {
    this.encPrivateKey = encPrivateKey;
}

}
3:導入錢包

其實就一步操作,就是根據私鑰 創建wallet對象。

//根據私鑰創建錢包
Wallet wallet = new Wallet(privateKey);
//設置錢包名稱,我這裡不需要就設置成錢包地址了。
wallet.setWalletName(wallet.getAddress());
//項目存儲導入的錢包
TronManager.storeTron(wallet);

4:創建錢包
       創建錢包需要兩個參數,一個是錢包名稱,一個是設置的密碼,錢包名稱還好,重要的是密碼,因為轉賬,導出私鑰助記詞等信息時,都是需要密碼驗證的。

Wallet wallet = new Wallet(true);
wallet.setWalletName(name);
WalletManager.store(this,wallet, pwd);
store方法是使用SharedPreferences存儲當前錢包的信息,其中我們可以通過密碼來獲取wallet的eckey從而得到錢包的公鑰和私鑰。

5:錢包信息
      這裡主要用到項目中grpcClient類和walletmanager類。

這個類主要封裝了對應的網路請求以及錢包管理

grpcClient類的initGrpc需要傳入對應的fullnode和soliditynode,這個可以去下麵的地址去選擇,

documentation/Official_Public_Node.md at master · tronprotocol/documentation · GitHub

查詢賬戶需要用到賬戶的地址:

Protocol.Account account = WalletManager.queryAccount(address, false);
GrpcAPI.AccountNetMessage accountNetMessage = WalletManager.getAccountNet(address);
GrpcAPI.AccountResourceMessage accountResMessage = WalletManager.getAccountRes(address);
  account可以查詢balance和FrozenList;

accountNetMessage 可以查詢賬戶的帶寬信息。

具體代碼如下:

double balance=mAccount.getBalance()/1000000.0d;
binding.tvWalletAccount.setText(balance+"");

        long frozenTotal = 0;
        for(Protocol.Account.Frozen frozen : mAccount.getFrozenList()) {
            frozenTotal += frozen.getFrozenBalance();
        }
        binding.tvWalletTronWeight.setText((frozenTotal/1000000)+"");

        GrpcAPI.AccountNetMessage accountNetMessage = TronUtil.getAccountNet(getActivity(), wallet.getWalletName());

        long bandwidth = accountNetMessage.getNetLimit() + accountNetMessage.getFreeNetLimit();
        long bandwidthUsed = accountNetMessage.getNetUsed()+accountNetMessage.getFreeNetUsed();
        long bandwidthLeft = bandwidth - bandwidthUsed;

        binding.tvWalletBandwidth.setText(bandwidthLeft+"");

6:轉賬

byte[] toRaw;
try {
toRaw = WalletManager.decodeFromBase58Check(sendAddress);
} catch (IllegalArgumentException ignored) {
Toast.makeText(this,"請輸入一個有效地址",Toast.LENGTH_SHORT).show();
return;
}

    double amount=Double.parseDouble(sendAmount);
    Contract.TransferContract contract = WalletManager.createTransferContract(toRaw, WalletManager.decodeFromBase58Check(mWallet.getAddress()), (long) (amount * 1000000.0d));
    Protocol.Transaction transaction = WalletManager.createTransaction4Transfer(contract);
    byte[]  mTransactionBytes = transaction.toByteArray();
    try {
        mTransactionUnsigned = Protocol.Transaction.parseFrom(mTransactionBytes);
    } catch (InvalidProtocolBufferException e) {
        e.printStackTrace();
    }

根據上面的代碼,獲取到mTransactionUnsigned ,然後輸入密碼校驗密碼並獲取到wallet的eckey。

設置時間戳,交易簽名。

mTransactionSigned = TransactionUtils.setTimestamp(mTransactionUnsigned);
mTransactionSigned = TransactionUtils.sign(mTransactionSigned, mWallet.getECKey());
WalletManager.broadcastTransaction(mTransactionSigned);
最後一步是廣播交易。

具體的代碼可查看git。

git地址

本文由博客一文多發平臺 OpenWrite 發佈!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 索引相關 類型隱式轉換 大坑 **欄位filed1是varchar類型,且加了索引,如果 where filed1 = 123; type 可能是all,因為123是數字類型,mysql內部會用函數做隱式轉換,用了函數,索引就失效了。** 大數據深度分頁,用主鍵 select field1,fiel ...
  • 推薦:SQL語句執行順序相關問題。 MySQL Server架構 分層概述 MySQL Server架構可抽象為3層。 連接層:驗證用戶名密碼,認證成功後,獲取當前賬號的許可權並緩存,並分配TCP連接池和線程池資源。 處理層:實現核心的處理功能。 存儲層:將處理後的數據高性能安全的寫入磁碟,或從磁碟中 ...
  • 在 Walrus 平臺上,運維團隊在資源定義(Resource Definition)中聲明提供的資源類型,通過設置匹配規則,將不同的資源部署模板應用到不同類型的環境、項目等。與此同時,研發人員無需關註底層具體實現方式,通過創建 Resource 對象聲明需要使用的資源類型及基本信息,就可以靈活地在 ...
  • 掌握這幾種SQL進階用法,你將能夠更高效地處理各種複雜的數據操作,並少走很多彎路。這些技巧能夠提高你的SQL查詢能力,使得你在日常的數據處理工作中更得心應手。 ...
  • 什麼是MySQL的頁? 頁是指存儲引擎使用的最小的數據存儲單位。 當 MySQL 執行讀取或寫入操作時,是以頁為基本單位來進行操作的。即使讀寫一條數據,MySQL 也會按頁操作。 MySQL 的存儲引擎會將數據分成多個頁,並根據需要將這些頁載入到記憶體中進行處理。 通過使用頁來組織數據,MySQL 能 ...
  • 搭建Redis三主三從集群的詳細步驟如下: 準備環境: 確保你有六台伺服器或虛擬機,每台伺服器上都已經安裝了Redis。這些伺服器將用於搭建三主三從的Redis集群。 確保所有伺服器之間的網路連接正常,並且防火牆設置允許Redis通信。 安裝Redis: 在每台伺服器上下載並安裝Redis。你可以從 ...
  • 結論:當一個事務要對錶進行鎖定時,首先會獲取相應的意向鎖。其他事務可以通過檢查意向鎖來判斷是否有其他事務在更細粒度的級別上對錶進行了鎖定。這有助於避免衝突和提高併發性能 在討論此問題之前我們應當明確兩個前提: Innodb存儲引擎支持行鎖和表鎖共存 行鎖與表鎖之間互不衝突 意向鎖是表級別的鎖,意向鎖 ...
  • 原文: Android 獲取設備的CPU型號和設備型號-Stars-One的雜貨小窩 之前整的項目的總結信息,可能不太全,湊合著用吧,代碼在最下麵一節 CPU型號數據 華為: ro.mediatek.platform vivo: ro.vivo.product.platform oppo: ro.b ...
一周排行
    -Advertisement-
    Play Games
  • 前言 微服務架構已經成為搭建高效、可擴展系統的關鍵技術之一,然而,現有許多微服務框架往往過於複雜,使得我們普通開發者難以快速上手並體驗到微服務帶了的便利。為瞭解決這一問題,於是作者精心打造了一款最接地氣的 .NET 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...