// Path: src/main/java/org/adridadou/ethereum/keystore/AccountProvider.java
// public class AccountProvider {
// 
//     public static final int BIT_LENGTH = 256;
// 
//     private AccountProvider() {}
// 
//     public static EthAccount fromPrivateKey(final byte[] privateKey) {
//         return new EthAccount(new BigInteger(1, privateKey));
//     }
// 
//     public static EthAccount fromPrivateKey(final String privateKey) {
//         return AccountProvider.fromPrivateKey(Hex.decode(privateKey));
//     }
// 
//     public static EthAccount fromECKey(final ECKey ecKey) {
//         return new EthAccount(ecKey.getPrivKey());
//     }
// 
//     public static EthAccount fromSeed(final String id) {
//         return AccountProvider.fromPrivateKey(doSha3(id.getBytes(EthereumFacade.CHARSET)));
//     }
// 
//     public static SecureKey fromKeystore(final File file) {
//         return new FileSecureKey(file);
//     }
// 
//     public static List<SecureKey> listMainKeystores() {
//         return listKeystores(new File(WalletUtils.getMainnetKeyDirectory()));
//     }
// 
//     public static List<SecureKey> listRopstenKeystores() {
//         return listKeystores(new File(WalletUtils.getTestnetKeyDirectory()));
//     }
// 
//     public static List<SecureKey> listKeystores(final File directory) {
//         File[] files = Optional.ofNullable(directory.listFiles()).orElseThrow(() -> new EthereumApiException("cannot find the folder " + WalletUtils.getMainnetKeyDirectory()));
//         return Arrays.stream(files)
//                 .filter(File::isFile)
//                 .map(AccountProvider::fromKeystore)
//                 .collect(Collectors.toList());
//     }
// 
//     private static byte[] doSha3(byte[] message) {
//         SHA3Digest digest = new SHA3Digest(BIT_LENGTH);
//         byte[] hash = new byte[digest.getDigestSize()];
// 
//         if (message.length != 0) {
//             digest.update(message, 0, message.length);
//         }
//         digest.doFinal(hash, 0);
//         return hash;
//     }
// }


import org.adridadou.ethereum.EthereumBackend;
import org.adridadou.ethereum.event.EthereumEventHandler;
import org.adridadou.ethereum.keystore.AccountProvider;
import org.adridadou.ethereum.values.*;
import org.adridadou.exception.EthereumApiException;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.blockchain.StandaloneBlockchain;
import java.math.BigInteger;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
package org.adridadou.ethereum.ethj;



/**
 * Created by davidroon on 20.01.17.
 * This code is released under Apache 2 license
 */
public class EthereumTest implements EthereumBackend {
    private final StandaloneBlockchain blockchain;
    private final TestConfig testConfig;
    private final BlockingQueue<Transaction> transactions = new ArrayBlockingQueue<>(100);
    private final LocalExecutionService localExecutionService;

    public EthereumTest(TestConfig testConfig) {
        this.blockchain = new StandaloneBlockchain();

        blockchain
                .withGasLimit(testConfig.getGasLimit())
                .withGasPrice(testConfig.getGasPrice())
                .withCurrentTime(testConfig.getInitialTime());

        testConfig.getBalances().entrySet()
                .forEach(entry -> blockchain.withAccountBalance(entry.getKey().getAddress().address, entry.getValue().inWei()));

        localExecutionService = new LocalExecutionService(blockchain.getBlockchain());
        CompletableFuture.runAsync(() -> {
            try {
                while(true) {
                    blockchain.submitTransaction(transactions.take());
                    blockchain.createBlock();
                }
            } catch (InterruptedException e) {
                throw new EthereumApiException("error while polling transactions for test env", e);
            }
        });

        this.testConfig = testConfig;
    }

    public EthAccount defaultAccount() {
// Path: src/main/java/org/adridadou/ethereum/keystore/AccountProvider.java
// public class AccountProvider {
// 
//     public static final int BIT_LENGTH = 256;
// 
//     private AccountProvider() {}
// 
//     public static EthAccount fromPrivateKey(final byte[] privateKey) {
//         return new EthAccount(new BigInteger(1, privateKey));
//     }
// 
//     public static EthAccount fromPrivateKey(final String privateKey) {
//         return AccountProvider.fromPrivateKey(Hex.decode(privateKey));
//     }
// 
//     public static EthAccount fromECKey(final ECKey ecKey) {
//         return new EthAccount(ecKey.getPrivKey());
//     }
// 
//     public static EthAccount fromSeed(final String id) {
//         return AccountProvider.fromPrivateKey(doSha3(id.getBytes(EthereumFacade.CHARSET)));
//     }
// 
//     public static SecureKey fromKeystore(final File file) {
//         return new FileSecureKey(file);
//     }
// 
//     public static List<SecureKey> listMainKeystores() {
//         return listKeystores(new File(WalletUtils.getMainnetKeyDirectory()));
//     }
// 
//     public static List<SecureKey> listRopstenKeystores() {
//         return listKeystores(new File(WalletUtils.getTestnetKeyDirectory()));
//     }
// 
//     public static List<SecureKey> listKeystores(final File directory) {
//         File[] files = Optional.ofNullable(directory.listFiles()).orElseThrow(() -> new EthereumApiException("cannot find the folder " + WalletUtils.getMainnetKeyDirectory()));
//         return Arrays.stream(files)
//                 .filter(File::isFile)
//                 .map(AccountProvider::fromKeystore)
//                 .collect(Collectors.toList());
//     }
// 
//     private static byte[] doSha3(byte[] message) {
//         SHA3Digest digest = new SHA3Digest(BIT_LENGTH);
//         byte[] hash = new byte[digest.getDigestSize()];
// 
//         if (message.length != 0) {
//             digest.update(message, 0, message.length);
//         }
//         digest.doFinal(hash, 0);
//         return hash;
//     }
// }


// Path: src/main/java/org/adridadou/ethereum/ethj/EthereumTest.java
import org.adridadou.ethereum.EthereumBackend;
import org.adridadou.ethereum.event.EthereumEventHandler;
import org.adridadou.ethereum.keystore.AccountProvider;
import org.adridadou.ethereum.values.*;
import org.adridadou.exception.EthereumApiException;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.blockchain.StandaloneBlockchain;
import java.math.BigInteger;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;

package org.adridadou.ethereum.ethj;



/**
 * Created by davidroon on 20.01.17.
 * This code is released under Apache 2 license
 */
public class EthereumTest implements EthereumBackend {
    private final StandaloneBlockchain blockchain;
    private final TestConfig testConfig;
    private final BlockingQueue<Transaction> transactions = new ArrayBlockingQueue<>(100);
    private final LocalExecutionService localExecutionService;

    public EthereumTest(TestConfig testConfig) {
        this.blockchain = new StandaloneBlockchain();

        blockchain
                .withGasLimit(testConfig.getGasLimit())
                .withGasPrice(testConfig.getGasPrice())
                .withCurrentTime(testConfig.getInitialTime());

        testConfig.getBalances().entrySet()
                .forEach(entry -> blockchain.withAccountBalance(entry.getKey().getAddress().address, entry.getValue().inWei()));

        localExecutionService = new LocalExecutionService(blockchain.getBlockchain());
        CompletableFuture.runAsync(() -> {
            try {
                while(true) {
                    blockchain.submitTransaction(transactions.take());
                    blockchain.createBlock();
                }
            } catch (InterruptedException e) {
                throw new EthereumApiException("error while polling transactions for test env", e);
            }
        });

        this.testConfig = testConfig;
    }

    public EthAccount defaultAccount() {
        return AccountProvider.fromECKey(this.blockchain.getSender());