程序员

如何创建BTC/ETH/TRX等主流钱包并离线签名 – Tokenview

作者:admin 2021-05-12 我要评论

我们常见的区块链钱包有非确定性钱包和确定性钱包两种而我们通常创建的脱离节点的轻钱包都是使用的就是确定性的钱包它是由种子(随机数生成器生成的随机数)进行单...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

我们常见的区块链钱包有非确定性钱包和确定性钱包两种,而我们通常创建的脱离节点的轻钱包都是使用的就是确定性的钱包,它是由种子(随机数生成器生成的随机数)进行单向哈希运算生成的。我们备份了种子就可以保存钱包;但是由于种子是一串随机数,不便于记忆,所以我们用算法将种子转化为一串助记词(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://blog.csdn.net/Tokenview/article/details/115489915

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 如何创建BTC/ETH/TRX等主流钱包并离线

    如何创建BTC/ETH/TRX等主流钱包并离线

  • Go + gRPC-Gateway(V2) 构建微服务实战

    Go + gRPC-Gateway(V2) 构建微服务实战

  • 实验四 拷贝构造函数和赋值运算符函数

    实验四 拷贝构造函数和赋值运算符函数

  • 【Java学习】什么是SSL、TLS、HTTPS

    【Java学习】什么是SSL、TLS、HTTPS

腾讯云代理商
海外云服务器