All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.DNAProject.sdk.manager.WalletMgr Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018 The DNA Authors
 * This file is part of The DNA library.
 *
 *  The DNA is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The DNA is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with The DNA.  If not, see .
 *
 */

package com.github.DNAProject.sdk.manager;

import com.github.DNAProject.common.ErrorCode;
import com.github.DNAProject.common.Helper;
import com.github.DNAProject.common.Address;
import com.github.DNAProject.crypto.*;
import com.github.DNAProject.sdk.exception.*;
import com.github.DNAProject.sdk.info.AccountInfo;
import com.github.DNAProject.sdk.info.IdentityInfo;
import com.github.DNAProject.sdk.wallet.Account;
import com.github.DNAProject.sdk.wallet.Control;
import com.github.DNAProject.sdk.wallet.Identity;
import com.github.DNAProject.sdk.wallet.Wallet;
import com.github.DNAProject.common.Common;
import com.alibaba.fastjson.JSON;

import java.io.*;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 *
 */
public class WalletMgr {
    private Wallet walletInMem;
    private Wallet walletFile;
    private SignatureScheme scheme = null;
    private String filePath = null;
    public WalletMgr(Wallet wallet,SignatureScheme scheme) throws Exception {
        this.scheme = scheme;
        this.walletInMem = wallet;
        this.walletFile = wallet;
    }
    public WalletMgr(String path, SignatureScheme scheme) throws Exception {
        this.scheme = scheme;
        this.filePath = path;
        File file = new File(filePath);
        if (!file.exists()) {
            walletInMem = new Wallet();
            walletInMem.setCreateTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()));
            walletFile = new Wallet();
            file.createNewFile();
            writeWallet();
        }
        InputStream inputStream = new FileInputStream(filePath);
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        String text = new String(bytes);
        walletInMem = JSON.parseObject(text, Wallet.class);
        walletFile = JSON.parseObject(text, Wallet.class);
        if (walletInMem.getIdentities() == null) {
            walletInMem.setIdentities(new ArrayList());
        }
        if (walletInMem.getAccounts() == null) {
            walletInMem.setAccounts(new ArrayList());
        }
        writeWallet();
    }

    private WalletMgr(String path, String label, String password, SignatureScheme scheme) throws Exception {
        this.scheme = scheme;
        this.filePath = path;
        File file = new File(filePath);
        if (!file.exists()) {
            walletInMem = new Wallet();
            walletInMem.setCreateTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date()));
            walletFile = new Wallet();
            file.createNewFile();
            createIdentity(label, password);
            writeWallet();
        }
        InputStream inputStream = new FileInputStream(filePath);
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        String text = new String(bytes);
        walletInMem = JSON.parseObject(text, Wallet.class);
        walletFile = JSON.parseObject(text, Wallet.class);
        if (walletInMem.getIdentities() == null) {
            walletInMem.setIdentities(new ArrayList());
        }
        if (walletInMem.getAccounts() == null) {
            walletInMem.setAccounts(new ArrayList());
        }
        if (walletInMem.getIdentities().size() == 0) {
            createIdentity(label, password);
            writeWallet();
        }
    }

    private static void writeFile(String filePath, String sets) throws IOException {
        FileWriter fw = new FileWriter(filePath);
        PrintWriter out = new PrintWriter(fw);
        out.write(sets);
        out.println();
        fw.close();
        out.close();
    }

    /**
     *
     * @return wallet file data
     */
    public Wallet getWalletFile() {
        return walletFile;
    }

    /**
     *
     * @return wallet in memory
     */
    public Wallet getWallet() {
        return walletInMem;
    }

    /**
     *  wallet in memory = wallet file data
     * @return
     */
    public Wallet resetWallet() {
        walletInMem = walletFile.clone();
        return walletInMem;
    }
    public Wallet saveWallet() throws Exception {
        return writeWallet();
    }
    public Wallet writeWallet() throws Exception {
        writeFile(filePath, JSON.toJSONString(walletInMem));
        walletFile = walletInMem.clone();
        return walletFile;
    }

    public SignatureScheme getSignatureScheme() {
        return scheme;
    }

    public void setSignatureScheme(SignatureScheme scheme) {
        this.scheme = scheme;
    }

    public Identity importIdentity(String encryptedPrikey, String password,byte[] salt, String address) throws Exception {
        return importIdentity("",encryptedPrikey,password,salt,address);
    }
    public Identity importIdentity(String label,String encryptedPrikey, String password,byte[] salt, String address) throws Exception {
        String prikey = com.github.DNAProject.account.Account.getGcmDecodedPrivateKey(encryptedPrikey, password, address,salt, walletFile.getScrypt().getN(), scheme);
        IdentityInfo info = createIdentity(label,password,salt, Helper.hexToBytes(prikey));
        prikey = null;
        return getWallet().getIdentity(info.dnaid);
    }


    public Identity createIdentity(String password) throws Exception {
        return createIdentity("",password);
    }
    public Identity createIdentity(String label,String password) throws Exception {
        IdentityInfo info = createIdentity(label,password, ECC.generateKey());
        return getWallet().getIdentity(info.dnaid);
    }

    public Identity createIdentityFromPriKey(String label,String password, String prikey) throws Exception {
        IdentityInfo info = createIdentity(label,password, Helper.hexToBytes(prikey));
        return getWallet().getIdentity(info.dnaid);
    }

    public Identity createIdentityFromPriKey(String password, String prikey) throws Exception {
        IdentityInfo info = createIdentity("", password, Helper.hexToBytes(prikey));
        prikey = null;
        return getWallet().getIdentity(info.dnaid);
    }

    public IdentityInfo createIdentityInfo(String password) throws Exception {
        return createIdentityInfo("",password);
    }
    public IdentityInfo createIdentityInfo(String label,String password) throws Exception {
        IdentityInfo info = createIdentity(label,password, ECC.generateKey());
        return info;
    }


    public IdentityInfo getIdentityInfo(String dnaid, String password,byte[] salt) throws Exception {
        com.github.DNAProject.account.Account acct = getAccountByAddressOrDnaId(dnaid, password,salt);
        IdentityInfo info = new IdentityInfo();
        info.dnaid = Common.diddna + Address.addressFromPubKey(acct.serializePublicKey()).toBase58();
        info.pubkey = Helper.toHexString(acct.serializePublicKey());
        info.setPrikey(Helper.toHexString(acct.serializePrivateKey()));
        info.setPriwif(acct.exportWif());
        info.encryptedPrikey = acct.exportGcmEncryptedPrikey(password, salt,walletFile.getScrypt().getN());
        info.addressU160 = acct.getAddressU160().toString();
        return info;
    }

    private IdentityInfo createIdentity(String label,String password, byte[] prikey) throws Exception {
        byte[] salt = ECC.generateKey(16);
        return createIdentity(label,password,salt,prikey);
    }
    private IdentityInfo createIdentity(String label,String password,byte[] salt, byte[] prikey) throws Exception {
        com.github.DNAProject.account.Account acct = createAccount(label,password,salt, prikey, false);
        IdentityInfo info = new IdentityInfo();
        info.dnaid = Common.diddna + Address.addressFromPubKey(acct.serializePublicKey()).toBase58();
        info.pubkey = Helper.toHexString(acct.serializePublicKey());
        info.setPrikey(Helper.toHexString(acct.serializePrivateKey()));
        info.setPriwif(acct.exportWif());
        info.encryptedPrikey = acct.exportGcmEncryptedPrikey(password, salt,walletFile.getScrypt().getN());
        info.addressU160 = acct.getAddressU160().toHexString();
        return info;
    }
    public Account importAccount(String encryptedPrikey, String password, String address,byte[] salt) throws Exception {
        return importAccount("",encryptedPrikey,password,address,salt);
    }

    public Account importAccount(String label,String encryptedPrikey, String password, String address,byte[] salt) throws Exception {
        String prikey = com.github.DNAProject.account.Account.getGcmDecodedPrivateKey(encryptedPrikey, password, address,salt, walletFile.getScrypt().getN(), scheme);
        AccountInfo info = createAccountInfo(label,password, salt,Helper.hexToBytes(prikey));
        prikey = null;
        password = null;
        return getWallet().getAccount(info.addressBase58);
    }

    public void createAccounts(int count, String password) throws Exception {
        for (int i = 0; i < count; i++) {
            createAccount("", password);
        }
    }
    public Account createAccount(String password) throws Exception {
        Account account = createAccount("", password);
        return account;
    }
    public Account createAccount(String label,String password) throws Exception {
        AccountInfo info = createAccountInfo(label,password, ECC.generateKey());
        return getWallet().getAccount(info.addressBase58);
    }
    private AccountInfo createAccountInfo(String label,String password,byte[] prikey) throws Exception {
        byte[] salt = ECC.generateKey(16);
        return createAccountInfo(label,password,salt,prikey);
    }

    private AccountInfo createAccountInfo(String label,String password,byte[] salt, byte[] prikey) throws Exception {
        com.github.DNAProject.account.Account acct = createAccount(label,password,salt, prikey, true);
        new SecureRandom().nextBytes(prikey);
        AccountInfo info = new AccountInfo();
        info.addressBase58 = Address.addressFromPubKey(acct.serializePublicKey()).toBase58();
        info.pubkey = Helper.toHexString(acct.serializePublicKey());
        info.setPrikey(Helper.toHexString(acct.serializePrivateKey()));
        info.setPriwif(acct.exportWif());
        info.encryptedPrikey = acct.exportGcmEncryptedPrikey(password, salt,walletFile.getScrypt().getN());
        info.addressU160 = acct.getAddressU160().toHexString();
        return info;
    }

    public Account createAccountFromPriKey(String password, String prikey) throws Exception {
        AccountInfo info = createAccountInfo("",password, Helper.hexToBytes(prikey));
        return getWallet().getAccount(info.addressBase58);
    }
    public Account createAccountFromPriKey(String label,String password, String prikey) throws Exception {
        AccountInfo info = createAccountInfo(label,password, Helper.hexToBytes(prikey));
        return getWallet().getAccount(info.addressBase58);
    }
    public AccountInfo createAccountInfo(String password) throws Exception {
        return createAccountInfo("",password);
    }
    public AccountInfo createAccountInfo(String label,String password) throws Exception {
        AccountInfo info = createAccountInfo(label,password, ECC.generateKey());
        return info;
    }
    public AccountInfo createAccountInfoFromPriKey(String password, String prikey) throws Exception {
        return createAccountInfo("",password, Helper.hexToBytes(prikey));
    }
    public AccountInfo createAccountInfoFromPriKey(String label,String password, String prikey) throws Exception {
        return createAccountInfo(label,password, Helper.hexToBytes(prikey));
    }

    public IdentityInfo createIdentityInfoFromPriKey(String label,String password, String prikey) throws Exception {
        return createIdentity(label,password, Helper.hexToBytes(prikey));
    }

    public String privateKeyToWif(String privateKey) throws Exception {
        com.github.DNAProject.account.Account act = new com.github.DNAProject.account.Account(Helper.hexToBytes(privateKey), scheme);
        return act.exportWif();
    }
    public com.github.DNAProject.account.Account getAccount(String address, String password) throws Exception {
        return getAccount(address, password,getWallet().getAccount(address).getSalt());
    }
    public com.github.DNAProject.account.Account getAccount(String addressOrDnaId, String password, byte[] salt) throws Exception {
        return getAccountByAddressOrDnaId(addressOrDnaId, password,salt);
    }

    public AccountInfo getAccountInfo(String addressOrDnaId, String password,byte[] salt) throws Exception {
        AccountInfo info = new AccountInfo();
        com.github.DNAProject.account.Account acc = getAccountByAddressOrDnaId(addressOrDnaId, password,salt);
        info.addressBase58 = addressOrDnaId.replace(Common.diddna, "");
        info.pubkey = Helper.toHexString(acc.serializePublicKey());
        info.setPrikey(Helper.toHexString(acc.serializePrivateKey()));
        info.encryptedPrikey = acc.exportGcmEncryptedPrikey(password,salt, walletFile.getScrypt().getN());
        info.setPriwif(acc.exportWif());
        info.addressU160 = acc.getAddressU160().toString();
        return info;
    }


    private com.github.DNAProject.account.Account createAccount(String label, String password, byte[] salt, byte[] privateKey, boolean accountFlag) throws Exception {
        com.github.DNAProject.account.Account account = new com.github.DNAProject.account.Account(privateKey, scheme);
        Account acct;
        switch (scheme) {
            case SHA256WITHECDSA:
                acct = new Account("ECDSA", new Object[]{Curve.P256.toString()}, "aes-256-gcm", "SHA256withECDSA", "sha256");
                break;
            case SM3WITHSM2:
                acct = new Account("SM2", new Object[]{Curve.SM2P256V1.toString()}, "aes-256-gcm", "SM3withSM2", "sha256");
                break;
            default:
                throw new SDKException(ErrorCode.OtherError("scheme type error"));
        }
        if (password != null) {
            acct.key = account.exportGcmEncryptedPrikey(password,salt, walletFile.getScrypt().getN());
            password = null;
        } else {
            acct.key = Helper.toHexString(account.serializePrivateKey());
        }
        acct.address = Address.addressFromPubKey(account.serializePublicKey()).toBase58();
        if (label == null || label.equals("")) {
            String uuidStr = UUID.randomUUID().toString();
            label = uuidStr.substring(0, 8);
        }
        if (accountFlag) {
            for (Account e : walletInMem.getAccounts()) {
                if (e.address.equals(acct.address)) {
                    throw new SDKException(ErrorCode.ParamErr("wallet account exist"));
                }
            }
            if (walletInMem.getAccounts().size() == 0) {
                acct.isDefault = true;
                walletInMem.setDefaultAccountAddress(acct.address);
            }
            acct.label = label;
            acct.setSalt(salt);
            acct.setPublicKey(Helper.toHexString(account.serializePublicKey()));
            walletInMem.getAccounts().add(acct);
        } else {
            for (Identity e : walletInMem.getIdentities()) {
                if (e.dnaid.equals(Common.diddna + acct.address)) {
                    throw new SDKException(ErrorCode.ParamErr("wallet Identity exist"));
                }
            }
            Identity idt = new Identity();
            idt.dnaid = Common.diddna + acct.address;
            idt.label = label;
            if (walletInMem.getIdentities().size() == 0) {
                idt.isDefault = true;
                walletInMem.setDefaultDnaid(idt.dnaid);
            }
            idt.controls = new ArrayList();
            Control ctl = new Control(acct.key, "keys-1",Helper.toHexString(account.serializePublicKey()));
            ctl.setSalt(salt);
            ctl.setAddress(acct.address);
            idt.controls.add(ctl);
            walletInMem.getIdentities().add(idt);
        }
        return account;
    }

    private com.github.DNAProject.account.Account getAccountByAddressOrDnaId(String addressOrDnaId, String password, byte[] salt) throws Exception {
        try {
            if(addressOrDnaId.startsWith(Common.diddna)){
                for (Identity e : walletInMem.getIdentities()) {
                    if (e.dnaid.equals(addressOrDnaId)) {
                        String addr = e.dnaid.replace(Common.diddna, "");
                        String prikey = com.github.DNAProject.account.Account.getGcmDecodedPrivateKey(e.controls.get(0).key, password, addr,salt, walletFile.getScrypt().getN(), scheme);
                        return new com.github.DNAProject.account.Account(Helper.hexToBytes(prikey), scheme);
                    }
                }
            }else {
                for (Account e : walletInMem.getAccounts()) {
                    if (e.address.equals(addressOrDnaId)) {
                        String prikey = com.github.DNAProject.account.Account.getGcmDecodedPrivateKey(e.key, password, e.address,salt, walletFile.getScrypt().getN(), scheme);
                        return new com.github.DNAProject.account.Account(Helper.hexToBytes(prikey), scheme);
                    }
                }
            }

        } catch (Exception e) {
            throw new SDKException(ErrorCode.OtherError(e.getMessage()));
        }
        throw new SDKException(ErrorCode.OtherError("Account null"));
    }


    public Identity getDefaultIdentity() {
        for (Identity e : getWallet().getIdentities()) {
            if (e.isDefault) {
                return e;
            }
        }
        return null;
    }
    public Account getDefaultAccount() {
        for (Account e : getWallet().getAccounts()) {
            if (e.isDefault) {
                return e;
            }
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy