fix: refind Client and Utils.
This commit is contained in:
		
							parent
							
								
									c9832f4de9
								
							
						
					
					
						commit
						fa679c3cb3
					
				@ -65,7 +65,6 @@ protobuf {
 | 
			
		||||
            artifact = 'io.grpc:protoc-gen-grpc-java:' + grpc_java_version
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
   // generatedFilesBaseDir = "$projectDir/src"
 | 
			
		||||
    generateProtoTasks {
 | 
			
		||||
        all().each { task ->
 | 
			
		||||
            task.plugins {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										752
									
								
								src/main/java/org/bdware/bdledger/api/grpc/Client.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										752
									
								
								src/main/java/org/bdware/bdledger/api/grpc/Client.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,752 @@
 | 
			
		||||
package org.bdware.bdledger.api.grpc;
 | 
			
		||||
 | 
			
		||||
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.Metadata;
 | 
			
		||||
import io.grpc.StatusRuntimeException;
 | 
			
		||||
import io.grpc.stub.MetadataUtils;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.CommonProto.TransactionType;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.LedgerGrpc;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.LedgerProto.*;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.NodeGrpc;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.NodeProto.ClientVersionResponse;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.QueryGrpc;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.QueryProto.*;
 | 
			
		||||
 | 
			
		||||
import java.time.ZonedDateTime;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 事务账本客户端
 | 
			
		||||
 *
 | 
			
		||||
 * <p>如有更灵活的需求可直接使用{@link org.bdware.bdledger.api.grpc.pb.LedgerGrpc}类。
 | 
			
		||||
 *
 | 
			
		||||
 * @author nex
 | 
			
		||||
 * @see <a href="#">事务账本API</a>
 | 
			
		||||
 */
 | 
			
		||||
public class Client {
 | 
			
		||||
 | 
			
		||||
  private static final Logger logger = Logger.getLogger(Client.class.getName());
 | 
			
		||||
 | 
			
		||||
  private ManagedChannel channel;
 | 
			
		||||
  private NodeGrpc.NodeFutureStub nodeFutureStub;
 | 
			
		||||
  private NodeGrpc.NodeBlockingStub nodeBlockingStub;
 | 
			
		||||
  private LedgerGrpc.LedgerFutureStub ledgerFutureStub;
 | 
			
		||||
  private LedgerGrpc.LedgerBlockingStub ledgerBlockingStub;
 | 
			
		||||
  private QueryGrpc.QueryFutureStub queryFutureStub;
 | 
			
		||||
  private QueryGrpc.QueryBlockingStub queryBlockingStub;
 | 
			
		||||
//    private final ManagedChannel channel;
 | 
			
		||||
//    private final NodeGrpc.NodeFutureStub nodeFutureStub;
 | 
			
		||||
//    private final NodeGrpc.NodeBlockingStub nodeBlockingStub;
 | 
			
		||||
//    private final LedgerGrpc.LedgerFutureStub ledgerFutureStub;
 | 
			
		||||
//    private final LedgerGrpc.LedgerBlockingStub ledgerBlockingStub;
 | 
			
		||||
//    private final QueryGrpc.QueryFutureStub queryFutureStub;
 | 
			
		||||
//    private final QueryGrpc.QueryBlockingStub queryBlockingStub;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 构造客户端来向{@code host:port} BDLedger节点发请求。
 | 
			
		||||
   */
 | 
			
		||||
  public Client(String host, int port) {
 | 
			
		||||
    this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(), null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 构造客户端,使用{@code token}作access token来向{@code host:port} BDLedger节点发请求。
 | 
			
		||||
   */
 | 
			
		||||
  public Client(String host, int port, String token) {
 | 
			
		||||
    this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(), token);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 用已有的{@link io.grpc.Channel}对象构造客户端来向BDLedger节点发请求。
 | 
			
		||||
   */
 | 
			
		||||
  public Client(ManagedChannelBuilder<?> channelBuilder, String token) {
 | 
			
		||||
    channel = channelBuilder.build();
 | 
			
		||||
 | 
			
		||||
    nodeFutureStub = NodeGrpc.newFutureStub(channel);
 | 
			
		||||
    nodeBlockingStub = NodeGrpc.newBlockingStub(channel);
 | 
			
		||||
    ledgerFutureStub = LedgerGrpc.newFutureStub(channel);
 | 
			
		||||
    ledgerBlockingStub = LedgerGrpc.newBlockingStub(channel);
 | 
			
		||||
    queryFutureStub = QueryGrpc.newFutureStub(channel);
 | 
			
		||||
    queryBlockingStub = QueryGrpc.newBlockingStub(channel);
 | 
			
		||||
 | 
			
		||||
    if (token != null) {
 | 
			
		||||
      Metadata fixedHeaders = new Metadata();
 | 
			
		||||
      fixedHeaders.put(Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER), "bearer " + token);
 | 
			
		||||
      nodeFutureStub = GrpcHeaderInterceptor.attachHeaders(nodeFutureStub, fixedHeaders);
 | 
			
		||||
      nodeBlockingStub = GrpcHeaderInterceptor.attachHeaders(nodeBlockingStub, fixedHeaders);
 | 
			
		||||
      ledgerFutureStub = GrpcHeaderInterceptor.attachHeaders(ledgerFutureStub, fixedHeaders);
 | 
			
		||||
      ledgerBlockingStub = GrpcHeaderInterceptor.attachHeaders(ledgerBlockingStub, fixedHeaders);
 | 
			
		||||
      queryFutureStub = GrpcHeaderInterceptor.attachHeaders(queryFutureStub, fixedHeaders);
 | 
			
		||||
      queryBlockingStub = GrpcHeaderInterceptor.attachHeaders(queryBlockingStub, fixedHeaders);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 关闭客户端的网络连接。
 | 
			
		||||
   */
 | 
			
		||||
  public void shutdown() throws InterruptedException {
 | 
			
		||||
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">查询BDLedger节点版本</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<ClientVersionResponse> clientVersion() {
 | 
			
		||||
 | 
			
		||||
    info("*** clientVersion");
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return nodeFutureStub.clientVersion(Empty.getDefaultInstance());
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">查询BDLedger节点版本</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ClientVersionResponse clientVersionSync() {
 | 
			
		||||
 | 
			
		||||
    info("*** clientVersionSync");
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return nodeBlockingStub.clientVersion(Empty.getDefaultInstance());
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a href="#">创建账本</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<CreateLedgerResponse> createLedger(String name) {
 | 
			
		||||
 | 
			
		||||
    info("*** createLedger: name={0}", name);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerFutureStub.createLedger(createLedgerRequest(name));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a href="#">创建账本</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public CreateLedgerResponse createLedgerSync(String name) {
 | 
			
		||||
 | 
			
		||||
    info("*** createLedgerSync: name={0}", name);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerBlockingStub.createLedger(createLedgerRequest(name));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private CreateLedgerRequest createLedgerRequest(String name) {
 | 
			
		||||
    return CreateLedgerRequest.newBuilder().setName(name).build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a href="#">返回账本列表</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetLedgersResponse> getLedgers() {
 | 
			
		||||
 | 
			
		||||
    info("*** getLedgers");
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerFutureStub.getLedgers(Empty.getDefaultInstance());
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a href="#">返回账本列表</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetLedgersResponse getLedgersSync() {
 | 
			
		||||
 | 
			
		||||
    info("*** getLedgersSync");
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerBlockingStub.getLedgers(Empty.getDefaultInstance());
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">发送新事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<SendTransactionResponse> sendTransaction(
 | 
			
		||||
      String ledger, TransactionType type, String from, long nonce, String to, byte[] data) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** sendTransaction: ledger={0} type={1} from={2} to={3} data={4}",
 | 
			
		||||
        ledger, type, from, to, data);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerFutureStub.sendTransaction(SendTransactionRequest(ledger, type, from, nonce, to, data));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">发送新事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public SendTransactionResponse sendTransactionSync(
 | 
			
		||||
      String ledger, TransactionType type, String from, long nonce, String to, byte[] data) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** sendTransactionSync: ledger={0} type={1} from={2} to={3} data={4}",
 | 
			
		||||
        ledger, type, from, to, data);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return ledgerBlockingStub.sendTransaction(SendTransactionRequest(ledger, type, from, nonce, to, data));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private SendTransactionRequest SendTransactionRequest(
 | 
			
		||||
      String ledger, TransactionType type, String from, long nonce, String to, byte[] data) {
 | 
			
		||||
 | 
			
		||||
    SendTransactionRequest.Transaction.Builder txBuilder =
 | 
			
		||||
        SendTransactionRequest.Transaction.newBuilder().setType(type);
 | 
			
		||||
    if (from != null) {
 | 
			
		||||
      txBuilder.setFrom(ByteString.copyFrom(Utils.hexStringToByteArray(from)));
 | 
			
		||||
    }
 | 
			
		||||
    txBuilder.setNonce(nonce);
 | 
			
		||||
    if (to != null) {
 | 
			
		||||
      txBuilder.setTo(ByteString.copyFrom(Utils.hexStringToByteArray(to)));
 | 
			
		||||
    }
 | 
			
		||||
    if (data != null) {
 | 
			
		||||
      txBuilder.setData(ByteString.copyFrom(data));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return SendTransactionRequest.newBuilder().setLedger(ledger).setTransaction(txBuilder).build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回哈希所指定的区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlockByHashResponse> getBlockByHash(
 | 
			
		||||
      String ledger, String hash, boolean fullTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getBlockByHash: ledger={0} hash={1} fullTransactions={2}",
 | 
			
		||||
        ledger, hash, fullTransactions);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getBlockByHash(getBlockByHashRequest(ledger, hash, fullTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回哈希所指定的区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlockByHashResponse getBlockByHashSync(String ledger, String hash, boolean fullTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getBlockByHashSync: ledger={0} hash={1} fullTransactions={2}",
 | 
			
		||||
        ledger, hash, fullTransactions);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getBlockByHash(getBlockByHashRequest(ledger, hash, fullTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private GetBlockByHashRequest getBlockByHashRequest(
 | 
			
		||||
      String ledger, String hash, boolean fullTransactions) {
 | 
			
		||||
 | 
			
		||||
    GetBlockByHashRequest.Builder reqBuilder =
 | 
			
		||||
        GetBlockByHashRequest.newBuilder().setLedger(ledger).setFullTransactions(fullTransactions);
 | 
			
		||||
    if (hash != null) {
 | 
			
		||||
      reqBuilder.setHash(ByteString.copyFrom(Utils.hexStringToByteArray(hash)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlocksResponse> getBlocks(String ledger, ZonedDateTime startDateTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocks(ledger, startDateTime.toEpochSecond(), includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlocksResponse> getBlocks(String ledger, ZonedDateTime startDateTime, ZonedDateTime endDateTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocks(ledger, startDateTime.toEpochSecond(), endDateTime.toEpochSecond(), includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlocksResponse getBlocksSync(String ledger, ZonedDateTime startDateTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocksSync(ledger, startDateTime.toEpochSecond(), includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlocksResponse getBlocksSync(String ledger, ZonedDateTime startDateTime, ZonedDateTime endDateTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocksSync(ledger, startDateTime.toEpochSecond(), endDateTime.toEpochSecond(), includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlocksResponse> getBlocks(String ledger, long startUnixTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocks(ledger, startUnixTime, -1, includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlocksResponse> getBlocks(String ledger, long startUnixTime, long endUnixTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getBlocks: ledger={0} startUnixTime={1} endUnixTime={2}",
 | 
			
		||||
        ledger, startUnixTime, endUnixTime);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getBlocks(blocksRequest(ledger, startUnixTime, endUnixTime, includeTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlocksResponse getBlocksSync(String ledger, long startUnixTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
    return getBlocksSync(ledger, startUnixTime, -1, includeTransactions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlocksResponse getBlocksSync(String ledger, long startUnixTime, long endUnixTime, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getBlocksSync: ledger={0} startUnixTime={1} endUnixTime={2}",
 | 
			
		||||
        ledger, startUnixTime, endUnixTime);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getBlocks(blocksRequest(ledger, startUnixTime, endUnixTime, includeTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回账本中的区块数量</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<CountBlocksResponse> countBlocks(String ledger) {
 | 
			
		||||
 | 
			
		||||
    info("*** blockNumber: ledger={0}", ledger);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.countBlocks(blocksRequest(ledger, -1, -1, null));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回账本中的区块数量</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public CountBlocksResponse countBlocksSync(String ledger) {
 | 
			
		||||
 | 
			
		||||
    info("*** blockNumberSync: ledger={0}", ledger);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.countBlocks(blocksRequest(ledger, -1, -1, null));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private BlocksRequest blocksRequest(String ledger, long startTimestamp, long endTimestamp, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    BlocksRequest.Builder reqBuilder =
 | 
			
		||||
        BlocksRequest.newBuilder().setLedger(ledger);
 | 
			
		||||
    if (startTimestamp != -1) {
 | 
			
		||||
      reqBuilder.setStartTimestamp(startTimestamp);
 | 
			
		||||
    }
 | 
			
		||||
    if (endTimestamp != -1) {
 | 
			
		||||
      reqBuilder.setEndTimestamp(endTimestamp);
 | 
			
		||||
    }
 | 
			
		||||
    if (includeTransactions == null) {
 | 
			
		||||
      includeTransactions = IncludeTransactions.NONE;
 | 
			
		||||
    }
 | 
			
		||||
    reqBuilder.setIncludeTransactions(includeTransactions);
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间戳最新的若干区块</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetBlocksResponse> getRecentBlocks(String ledger, int count, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getRecentBlocks: ledger={0} count={1} includeTransactions={2}",
 | 
			
		||||
        ledger, count, includeTransactions);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getRecentBlocks(getRecentBlocksRequest(ledger, count, includeTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间戳最新的若干区块</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetBlocksResponse getRecentBlocksSync(String ledger, int count, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getRecentBlocksSync: ledger={0} count={1} includeTransactions={2}",
 | 
			
		||||
        ledger, count, includeTransactions);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getRecentBlocks(getRecentBlocksRequest(ledger, count, includeTransactions));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private RecentBlocksRequest getRecentBlocksRequest(String ledger, int count, IncludeTransactions includeTransactions) {
 | 
			
		||||
 | 
			
		||||
    RecentBlocksRequest.Builder reqBuilder =
 | 
			
		||||
        RecentBlocksRequest.newBuilder()
 | 
			
		||||
            .setLedger(ledger)
 | 
			
		||||
            .setCount(count);
 | 
			
		||||
    if (includeTransactions == null) {
 | 
			
		||||
      includeTransactions = IncludeTransactions.NONE;
 | 
			
		||||
    }
 | 
			
		||||
    reqBuilder.setIncludeTransactions(includeTransactions);
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回哈希所指定的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionByHashResponse> getTransactionByHash(String ledger, String hash) {
 | 
			
		||||
 | 
			
		||||
    info("*** getTransactionByHash: ledger={0} hash={1}", ledger, hash);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getTransactionByHash(getTransactionByHashRequest(ledger, hash));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回哈希所指定的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionByHashResponse getTransactionByHashSync(String ledger, String hash) {
 | 
			
		||||
 | 
			
		||||
    info("*** getTransactionByHashSync: ledger={0} hash={1}", ledger, hash);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getTransactionByHash(getTransactionByHashRequest(ledger, hash));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private GetTransactionByHashRequest getTransactionByHashRequest(String ledger, String hash) {
 | 
			
		||||
 | 
			
		||||
    GetTransactionByHashRequest.Builder reqBuilder =
 | 
			
		||||
        GetTransactionByHashRequest.newBuilder().setLedger(ledger);
 | 
			
		||||
    if (hash != null) {
 | 
			
		||||
      reqBuilder.setHash(ByteString.copyFrom(Utils.hexStringToByteArray(hash)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回区块的哈希与事务的index所指定的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionByBlockHashAndIndexResponse> getTransactionByBlockHashAndIndex(
 | 
			
		||||
      String ledger, String blockHash, int index) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getTransactionByBlockHashAndIndex: ledger={0} blockHash={1} index={2}",
 | 
			
		||||
        ledger, blockHash, index);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getTransactionByBlockHashAndIndex(
 | 
			
		||||
          getTransactionByBlockHashAndIndexRequest(ledger, blockHash, index));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回区块的哈希与事务的index所指定的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionByBlockHashAndIndexResponse getTransactionByBlockHashAndIndexSync(
 | 
			
		||||
      String ledger, String blockHash, int index) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getTransactionByBlockHashAndIndexSync: ledger={0} blockHash={1} index={2}",
 | 
			
		||||
        ledger, blockHash, index);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getTransactionByBlockHashAndIndex(
 | 
			
		||||
          getTransactionByBlockHashAndIndexRequest(ledger, blockHash, index));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private GetTransactionByBlockHashAndIndexRequest getTransactionByBlockHashAndIndexRequest(
 | 
			
		||||
      String ledger, String blockHash, int index) {
 | 
			
		||||
 | 
			
		||||
    GetTransactionByBlockHashAndIndexRequest.Builder reqBuilder =
 | 
			
		||||
        GetTransactionByBlockHashAndIndexRequest.newBuilder().setLedger(ledger).setIndex(index);
 | 
			
		||||
 | 
			
		||||
    if (blockHash != null) {
 | 
			
		||||
      reqBuilder.setBlockHash(ByteString.copyFrom(Utils.hexStringToByteArray(blockHash)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionsResponse> getTransactions(String ledger, ZonedDateTime startDateTime) {
 | 
			
		||||
    return getTransactions(ledger, startDateTime.toEpochSecond());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionsResponse> getTransactions(String ledger, ZonedDateTime startDateTime, ZonedDateTime endDateTime) {
 | 
			
		||||
    return getTransactions(ledger, startDateTime.toEpochSecond(), endDateTime.toEpochSecond());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionsResponse getTransactionsSync(String ledger, ZonedDateTime startDateTime) {
 | 
			
		||||
    return getTransactionsSync(ledger, startDateTime.toEpochSecond());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionsResponse getTransactionsSync(String ledger, ZonedDateTime startDateTime, ZonedDateTime endDateTime) {
 | 
			
		||||
    return getTransactionsSync(ledger, startDateTime.toEpochSecond(), endDateTime.toEpochSecond());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionsResponse> getTransactions(String ledger, long startUnixTime) {
 | 
			
		||||
    return getTransactions(ledger, startUnixTime, -1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<GetTransactionsResponse> getTransactions(String ledger, long startUnixTime, long endUnixTime) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getTransactions: ledger={0} startUnixTime={1} endUnixTime={2}",
 | 
			
		||||
        ledger, startUnixTime, endUnixTime);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.getTransactions(transactionsRequest(ledger, startUnixTime, endUnixTime));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionsResponse getTransactionsSync(String ledger, long startUnixTime) {
 | 
			
		||||
    return getTransactionsSync(ledger, startUnixTime, -1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回时间范围内的事务</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public GetTransactionsResponse getTransactionsSync(String ledger, long startUnixTime, long endUnixTime) {
 | 
			
		||||
 | 
			
		||||
    info(
 | 
			
		||||
        "*** getTransactionsSync: ledger={0} startUnixTime={1} endUnixTime={2}",
 | 
			
		||||
        ledger, startUnixTime, endUnixTime);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.getTransactions(transactionsRequest(ledger, startUnixTime, endUnixTime));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回账本中的事务数量</a>
 | 
			
		||||
   * (非阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public ListenableFuture<CountTransactionsResponse> countTransactions(String ledger) {
 | 
			
		||||
 | 
			
		||||
    info("*** blockNumber: ledger={0}", ledger);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryFutureStub.countTransactions(transactionsRequest(ledger, -1, -1));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * <a
 | 
			
		||||
   * href="#">返回账本中的事务数量</a>
 | 
			
		||||
   * (阻塞)
 | 
			
		||||
   */
 | 
			
		||||
  public CountTransactionsResponse countTransactionsSync(String ledger) {
 | 
			
		||||
 | 
			
		||||
    info("*** blockNumberSync: ledger={0}", ledger);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      return queryBlockingStub.countTransactions(transactionsRequest(ledger, -1, -1));
 | 
			
		||||
    } catch (StatusRuntimeException e) {
 | 
			
		||||
      warning("RPC failed: {0}", e.getStatus());
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private TransactionsRequest transactionsRequest(String ledger, long startTimestamp, long endTimestamp) {
 | 
			
		||||
 | 
			
		||||
    TransactionsRequest.Builder reqBuilder =
 | 
			
		||||
        TransactionsRequest.newBuilder().setLedger(ledger);
 | 
			
		||||
    if (startTimestamp != -1) {
 | 
			
		||||
      reqBuilder.setStartTimestamp(startTimestamp);
 | 
			
		||||
    }
 | 
			
		||||
    if (endTimestamp != -1) {
 | 
			
		||||
      reqBuilder.setEndTimestamp(endTimestamp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reqBuilder.build();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,33 @@
 | 
			
		||||
package org.bdware.bdledger.api.grpc;
 | 
			
		||||
 | 
			
		||||
import io.grpc.*;
 | 
			
		||||
import io.grpc.stub.AbstractStub;
 | 
			
		||||
import org.bdware.bdledger.api.grpc.pb.NodeGrpc;
 | 
			
		||||
 | 
			
		||||
public class GrpcHeaderInterceptor implements ClientInterceptor {
 | 
			
		||||
 | 
			
		||||
    private final Metadata extraHeaders;
 | 
			
		||||
 | 
			
		||||
    public GrpcHeaderInterceptor(Metadata metadata) {
 | 
			
		||||
        this.extraHeaders = metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
 | 
			
		||||
        return new ForwardingClientCall.SimpleForwardingClientCall<ReqT,RespT>(next.newCall(method, callOptions)) {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void start(Listener<RespT> responseListener, Metadata headers) {
 | 
			
		||||
                // 合并额外的头信息
 | 
			
		||||
                headers.merge(extraHeaders);
 | 
			
		||||
                super.start(responseListener, headers);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T extends AbstractStub<T>> T attachHeaders(T stub, Metadata metadata) {
 | 
			
		||||
        Channel channel = stub.getChannel();
 | 
			
		||||
        Channel interceptedChannel = ClientInterceptors.intercept(channel, new GrpcHeaderInterceptor(metadata));
 | 
			
		||||
        return stub.withChannel(interceptedChannel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								src/main/java/org/bdware/bdledger/api/grpc/Utils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/java/org/bdware/bdledger/api/grpc/Utils.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
package org.bdware.bdledger.api.grpc;
 | 
			
		||||
 | 
			
		||||
public class Utils {
 | 
			
		||||
 | 
			
		||||
  public static byte[] hexStringToByteArray(String s) {
 | 
			
		||||
    if (s.startsWith("0x")) {
 | 
			
		||||
      s = s.substring(2);
 | 
			
		||||
    }
 | 
			
		||||
    int l = s.length();
 | 
			
		||||
    byte[] data = new byte[l / 2];
 | 
			
		||||
    for (int i = 0; i < l; i += 2) {
 | 
			
		||||
      data[i / 2] =
 | 
			
		||||
          (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public static String byteArrayToHexString(byte[] bs) {
 | 
			
		||||
    StringBuilder data = new StringBuilder();
 | 
			
		||||
    for (byte b : bs) {
 | 
			
		||||
      data.append(Integer.toHexString((b >> 4) & 0xf));
 | 
			
		||||
      data.append(Integer.toHexString(b & 0xf));
 | 
			
		||||
    }
 | 
			
		||||
    return data.toString();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user