package bdledger.api; import bdchain.api.grpc.common.ClientVersionResponse; import bdchain.api.grpc.common.TransactionType; import bdchain.api.grpc.txledger.*; import com.google.common.util.concurrent.ListenableFuture; import com.google.protobuf.ByteString; import com.google.protobuf.Empty; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.StatusRuntimeException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; // import bdchain.api.grpc.txledger.TransactionLedgerGrpc.TransactionLedgerStub; /** * 事务账本客户端 * *

如有更灵活的需求可直接使用{@link bdchain.api.grpc.txledger.TransactionLedgerGrpc}类。 * * @see 事务账本API * @author nex */ public class TransactionLedgerClient { private static final Logger logger = Logger.getLogger(TransactionLedgerClient.class.getName()); private final ManagedChannel channel; private final TransactionLedgerFutureStub futureStub; private final TransactionLedgerBlockingStub blockingStub; // private final TransactionLedgerStub asyncStub; /** 构造客户端来访问{@code host:port}的事务账本服务。 */ public TransactionLedgerClient(String host, int port) { this(ManagedChannelBuilder.forAddress(host, port).usePlaintext()); } /** 用已有的{@link io.grpc.Channel}对象构造客户端来访问事务账本服务。 */ public TransactionLedgerClient(ManagedChannelBuilder channelBuilder) { channel = channelBuilder.build(); futureStub = TransactionLedgerGrpc.newFutureStub(channel); blockingStub = TransactionLedgerGrpc.newBlockingStub(channel); // asyncStub = TransactionLedgerGrpc.newStub(channel); } /** 关闭客户端的网络连接。 */ public void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } /** * 查询节点客户端版本 * (非阻塞) */ public ListenableFuture clientVersion() { info("*** clientVersion"); try { return futureStub.clientVersion(Empty.getDefaultInstance()); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 查询节点客户端版本 * (阻塞) */ public ClientVersionResponse clientVersionSync() { info("*** clientVersionSync"); try { return blockingStub.clientVersion(Empty.getDefaultInstance()); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 创建账本 * (非阻塞) */ public ListenableFuture createLedger(String name) { info("*** createLedger: name={0}", name); try { return futureStub.createLedger(createLedgerRequest(name)); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 创建账本 * (阻塞) */ public CreateLedgerResponse createLedgerSync(String name) { info("*** createLedgerSync: name={0}", name); try { return blockingStub.createLedger(createLedgerRequest(name)); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } private CreateLedgerRequest createLedgerRequest(String name) { return CreateLedgerRequest.newBuilder().setName(name).build(); } /** * 返回账本列表 * (非阻塞) */ public ListenableFuture getLedgers() { info("*** getLedgers"); try { return futureStub.getLedgers(Empty.getDefaultInstance()); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 返回账本列表 * (阻塞) */ public GetLedgersResponse getLedgersSync() { info("*** getLedgersSync"); try { return blockingStub.getLedgers(Empty.getDefaultInstance()); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 发送新事务 * (非阻塞) */ public ListenableFuture sendTransaction( String ledger, TransactionType type, String from, String to, byte[] data) { info( "*** sendTransaction: ledger={0} type={1} from={2} to={3} data={4}", ledger, type, from, to, data); try { return futureStub.sendTransaction(SendTransactionRequest(ledger, type, from, to, data)); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } /** * 发送新事务 * (阻塞) */ public SendTransactionResponse sendTransactionSync( String ledger, TransactionType type, String from, String to, byte[] data) { info( "*** sendTransactionSync: ledger={0} type={1} from={2} to={3} data={4}", ledger, type, from, to, data); try { return blockingStub.sendTransaction(SendTransactionRequest(ledger, type, from, to, data)); } catch (StatusRuntimeException e) { warning("RPC failed: {0}", e.getStatus()); return null; } } private SendTransactionRequest SendTransactionRequest( String ledger, TransactionType type, String from, String to, byte[] data) { SendTransactionRequest.Transaction.Builder txBuilder = SendTransactionRequest.Transaction.newBuilder().setType(type); if (from != null) { txBuilder.setFrom(ByteString.copyFrom(Utils.hexStringToByteArray(from))); } if (to != null) { txBuilder.setTo(ByteString.copyFrom(Utils.hexStringToByteArray(to))); } if (data != null) { txBuilder.setData(ByteString.copyFrom(data)); } SendTransactionRequest request = SendTransactionRequest.newBuilder().setLedger(ledger).setTransaction(txBuilder).build(); return request; } private void info(String msg, Object... params) { logger.log(Level.INFO, msg, params); } private void warning(String msg, Object... params) { logger.log(Level.WARNING, msg, params); } }