我們常見的區塊鏈錢包有非確定性錢包和確定性錢包兩種,而我們通常創建的脫離節點的輕錢包都是使用的就是確定性的錢包,它是由種子(亂數生成器生成的亂數)進行單向哈希運算生成的,我們備份了種子就可以保存錢包;但是由于種子是一串亂數,不便于記憶,所以我們用演算法將種子轉化為一串助記詞(Mnemonic),方便保存記錄,我們只要保存了助記詞,就可以保存自己的資產,非常方便,
如何創建這樣的數字貨幣錢包呢?
Tokenview github 有全面的開源專案供開發者使用:https://github.com/Tokenview/api-demo
該開源專案包含了各種主流幣的地址生成規則,以及離線簽名的程序,還提供了免費的api呼叫,下載專案代碼后,新建了一個專案,匯入下載的module:專案依賴了maven庫:
<dependency>
<groupId>cash.bitcoinj</groupId>
<artifactId>bitcoinj-tools</artifactId>
<version>0.14.5.2</version>
</dependency>
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>3.0.1</version>
</dependency>
專案中提供了地址生成、交易發送、查詢等一系列例子,首先看看種子的生成程序:
-
long creationTimeSeconds = System.currentTimeMillis() /1000;
-
DeterministicSeed ds =new DeterministicSeed(secureRandom, 128, “”, creationTimeSeconds);
可以選擇種子的長度,分別有128,160,192,224,256位的生成方式;種子長度不同對應的助記詞的個數也不同;生成的種子可以轉換成助記詞:
List mnemonicList = ds.getMnemonicCode();
通過HD錢包我們可以根據不同的幣種和地址索引派生出相對應的公私鑰對:
private static ECKeyPairgetEcKeyPairByDeterministicSeed(String path, DeterministicSeed
ds) {
String [] pathArray = path.split("/");
byte[] seedBytes = ds.getSeedBytes();
if (seedBytes ==null)
return null;
DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
ChildNumber childNumber;
for (int i =1; i < pathArray.length; i++) {
if (pathArray[i].endsWith("'")) {
int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() -1));
childNumber =new ChildNumber(number, true);
}else {
int number = Integer.parseInt(pathArray[i]);
childNumber =new ChildNumber(number, false);
}
dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
}
return ECKeyPair.create(dkKey.getPrivKeyBytes());
}
最后根據地址生成的規則,得到不同鏈對應的地址:
public static WalletBeangenerateAddress(String mnemonic, Coin coin)throws UnreadableWalletException {
ECKeyPair keyPair = ECKeyUtil.generateEcKey(mnemonic, coin);
ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
WalletBean wallet=new WalletBean();
wallet.setCoin_type(coin.getCoin());
NetworkParameters parameters=null;
switch (coin){
case BTC:
case BCH:
case BSV:
parameters= MainNetParams.get();
wallet.setAddress(ecKey.toAddress(parameters).toBase58());
wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
break;
case LTC:
parameters= LitecoinParams.get();
wallet.setAddress(ecKey.toAddress(parameters).toBase58());
wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
break;
case DOGE:
parameters= DogeParams.get();
wallet.setAddress(ecKey.toAddress(parameters).toBase58());
wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
break;
case DASH:
parameters= DashParams.get();
wallet.setAddress(ecKey.toAddress(parameters).toBase58());
wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
break;
case ETH:
case HT:
case ETC:
case PI:
case WAN:
case EM:
String address = Keys.getAddress(keyPair);
if(coin==Coin.EM){
address="EM"+address;
}else{
address="0x"+address;
}
wallet.setAddress(address);
String privateKey = Numeric.toHexStringNoPrefixZeroPadded(keyPair.getPrivateKey(), Keys.PRIVATE_KEY_LENGTH_IN_HEX);
wallet.setPrivateKey(privateKey);
break;
case NEO:
io.neow3j.crypto.ECKeyPair ecKeyPair= io.neow3j.crypto.ECKeyPair.create(keyPair.getPrivateKey());
wallet.setAddress(ecKeyPair.getAddress());
wallet.setPrivateKey(ecKeyPair.exportAsWIF());
break;
default:
break;
}
wallet.setMnemonic(mnemonic);
return wallet;
}
如何驗證地址正確性呢?
這里給大家提供一個驗證地址正確性的網址:https://iancoleman.io/bip39/
地址生成后,可以通過私鑰進行離線簽名并發送交易;例如ETH的交易的離線簽名:首先獲取的某個ETH地址的交易Nonce和當前的最佳手續費,推薦使用 Tokenview API 服務(https://services.tokenview.com/ ),除了獲取當前最佳手續費,還可以查詢100多個區塊鏈的鏈上資料,交易,地址,余額等等,
通過Tokenview API 獲取地址的 Nonce
public void getACCOUNTAddressNonce(){
String nonce =baseService.getACCOUNTAddressInfo("eth","0xda9cacf6c13450bea275c33e83503fb705d27bbb")
.getJSONObject("data")
.getString("nonce");
toResultString("GetACCOUNTAddressNonce", nonce);
}
呼叫SDK提供的簽名方法簽名:
public void testETHSign() {
String sinature =new ETHSign().signETHTransaction(
"0xb71a7616b42110d8345ddc6826ec42c2f1ce24d5f4d8efeb616168d5c1ef4a1f",
"0x9Ae75431335d2e70f8DB0b35F6C179a43756f78e",
"1",
78500000000L,
21000L,
80000000000L);
log.info(sinature);
}
我們獲取到對應的簽完名的交易資料,最后呼叫發送交易的 Tokenview api, 廣播交易到鏈上:
public void testSendETHRawTransaction() {
JSONObject jo =new JSONObject();
jo.put("jsonrpc","2.0");
jo.put("id","viewtoken");
jo.put("method","eth_sendRawTransaction");
jo.put("params", Arrays.asList("0xf86801851246f6f100825208949ae75431335d2e70f8db0b35f6c179a43756f78e8405f5e100801ca058b2130954d3b84918db5c0fc309dcc942b8656d88964a5f981a4a954bbb1221a0788b6b75afaea28d2e9178a6cea3d432983c10db1c778a1dcb6af009f5457701"));
JSONObject onchainwallet =walletservice.sendRawTransaction("eth",jo);
toResultString("SendRawTransaction", onchainwallet);
}
這樣我們就完成的整個錢包的開發,Tokenview API 不僅由基礎的節點資料查詢功能,還提供了各種資料分析和監聽地址的功能,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/273777.html
標籤:區塊鏈
上一篇:好網站,你懂的
下一篇:Go + gRPC-Gateway(V2) 構建微服務實戰系列,小程式登錄鑒權服務:第一篇(內附開發 demo)
