Solana生成离线地址(Java)
钱包
- 
BIP32:定义 Hierarchical Deterministic wallet (简称 “HD Wallet”),是一个系统可以从单一个 seed 产生一树状结构储存多组 keypairs(私钥和公钥)。好处是可以方便的备份、转移到其他相容装置(因为都只需要 seed),以及分层的权限控制等。 
- 
BIP39:将 seed 用方便记忆和书写的单字表示。一般由 12 个单字组成,称为 mnemonic code(phrase),中文称为助记词或助记码。例如: 
soldier dish answer treat exhibit blade diary glory arrange shoe ocean card
- BIP44:基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。各层定义如下:
  m / purpose' / coin_type' / account' / change / address_index
  
  //purporse': 固定值44', 代表是BIP44
  //coin_type': 这个代表的是币种, 可以兼容很多种币, 比如BTC是0, ETH是60,TRX是195
  //account: 代表这个币的账户索引,从0开始
  //change: 常量0用于外部(收款地址),常量1用于内部(也称为找零地址)。外部用于在钱包外可见的地址(例如,用于接收付款)。内部链用于在钱包外部不可见的地址,用于返回交易变更。 (所以一般使用0)
  //address_index: 地址索引,从0开始,代表生成第几个地址
  //btc一般是 m/44'/0'/0'/0
  //eth一般是 m/44'/60'/0'/0
  //trx一般是 m/44'/195'/0'/0
依赖
<!-- https://mvnrepository.com/artifact/com.portto.solana/web3 -->
<dependency>
    <groupId>com.portto.solana</groupId>
    <artifactId>web3</artifactId>
    <version>0.1.3</version>
</dependency>
依赖库编译时遇到的问题:卸载2019版本的idea,装了2022版本
// This class file was compiled with different version of Kotlin compiler and can't be decompiled.
//
// Current compiler ABI version is 1.1.15
// File ABI version is 1.6.0
生成地址及私钥
byte[] seed = MnemonicUtils.generateSeed(mnemonic, "");
SolanaBip44 solanaBip44 = new SolanaBip44();
//M/44H/501H/0H/0H
byte[] privateKeyFromSeed = solanaBip44.getPrivateKeyFromSeed(seed, DerivableType.BIP44CHANGE);
TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(privateKeyFromSeed);
System.out.println("地址0:" + Base58.encode(keyPair.getPublicKey()));
System.out.println("私钥0:" + Base58.encode(keyPair.getSecretKey()));
Account account = new Account(keyPair);
System.out.println("Account地址0:" + account.getPublicKey());
System.out.println("Account私钥0:" + Base58.encode(account.getSecretKey()));
BIP44助记词生成N个地址
//拆解 getPrivateKeyFromSeed(seed, DerivableType.BIP44CHANGE);
for (int i = 0; i < 10; i++) {
    HdKeyGenerator hdKeyGenerator = new HdKeyGenerator();
    SolanaCoin solanaCoin = new SolanaCoin();
    HdAddress masterAddress = hdKeyGenerator.getAddressFromSeed(seed, solanaCoin);
    HdAddress purposeAddress = hdKeyGenerator.getAddress(masterAddress, solanaCoin.getPurpose(), solanaCoin.getAlwaysHardened());// 44H
    HdAddress coinTypeAddress = hdKeyGenerator.getAddress(purposeAddress, solanaCoin.getCoinType(), solanaCoin.getAlwaysHardened());// 501H
    HdAddress accountAddress = hdKeyGenerator.getAddress(coinTypeAddress, i, solanaCoin.getAlwaysHardened());//0H
    HdAddress changeAddress = hdKeyGenerator.getAddress(accountAddress, 0L, solanaCoin.getAlwaysHardened()); //0H
    Account account1 = new Account(TweetNaclFast.Signature.keyPair_fromSeed(changeAddress.getPrivateKey().getPrivateKey()));
    System.out.println("Account地址" + i + ":" + account1.getPublicKey());
    System.out.println("Account私钥" + i + ":" + Base58.encode(account1.getSecretKey()));
}
私钥转换地址
package com.hlf.test.solana;
import com.portto.solana.web3.Account;
import com.portto.solana.web3.util.TweetNaclFast;
import org.bitcoinj.core.Base58;
/**
 * @ClassName: PrivateKeyAddress
 * @Description:
 * @Version: 1.0
 **/
public class PrivateKeyAddress {
    //地址0:2Hyaw6rryApLpffVYZxvT2BTAAARoJzoCBSs6Zy3bVow
    //私钥0:3WWsrp38veGfPJcdfmPDwGwqgaGGFQ7uZrk61rcYCbGyKjFXLYWid6CJgBUXTA8Ls2vSS8gMGhjtFrGSLYuAtZ4D
    public static void main(String[] args) {
        String privateKey = "3WWsrp38veGfPJcdfmPDwGwqgaGGFQ7uZrk61rcYCbGyKjFXLYWid6CJgBUXTA8Ls2vSS8gMGhjtFrGSLYuAtZ4D";
        byte[] decode = Base58.decode(privateKey);
        Account account1 = new Account(TweetNaclFast.Signature.keyPair_fromSecretKey(decode));
        Account account2 = new Account(TweetNaclFast.Signature.keyPair_fromSeed(decode));
        System.out.println("私钥转换地址:" + account1.getPublicKey());
        System.out.println("私钥转换地址-私钥:" + Base58.encode(account1.getSecretKey()));
    }
}
示例代码
package com.hlf.test.solana;
import com.portto.solana.web3.Account;
import com.portto.solana.web3.util.TweetNaclFast;
import com.portto.solana.web3.wallet.*;
import org.apache.commons.lang3.StringUtils;
import org.bitcoinj.core.Base58;
import org.web3j.crypto.*;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
/**
 * @ClassName: MnemonicAddress
 * @Description:
 * @Version: 1.0
 **/
public class MnemonicAddress {
    private static final String KEYSTORE_PATH = "/Users/huanglefei/Downloads/";
    public static void main(String[] args) {
        String mnemonic = "soldier dish answer treat exhibit blade diary glory arrange shoe ocean card";
        if (StringUtils.isBlank(mnemonic)) {
            try {
                // generate Mnemonic and keystone File
                Bip39Wallet bip39Wallet = generateBip44Wallet("hlf", KEYSTORE_PATH);
                //助记词
                mnemonic = bip39Wallet.getMnemonic();
                System.out.println("助记词:" + mnemonic);
            } catch (CipherException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        byte[] seed = MnemonicUtils.generateSeed(mnemonic, "");
        SolanaBip44 solanaBip44 = new SolanaBip44();
        //M/44H/501H/0H/0H
        byte[] privateKeyFromSeed = solanaBip44.getPrivateKeyFromSeed(seed, DerivableType.BIP44CHANGE);
        TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(privateKeyFromSeed);
        System.out.println("地址0:" + Base58.encode(keyPair.getPublicKey()));
        System.out.println("私钥0:" + Base58.encode(keyPair.getSecretKey()));
        Account account =  
