From e988933a445d579ebd41844bd0d2608d98fb3b28 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 11 Sep 2024 11:33:10 -0600 Subject: [PATCH 01/40] Add initial protos, test that request works and made a round trip --- .../java/io/provlabs/flow/api/NavEvent.java | 1642 +++++++++++++++++ .../provlabs/flow/api/NavEventOrBuilder.java | 117 ++ .../provlabs/flow/api/NavEventOuterClass.java | 80 + .../io/provlabs/flow/api/NavEventRequest.java | 767 ++++++++ .../flow/api/NavEventRequestOrBuilder.java | 39 + .../provlabs/flow/api/NavEventResponse.java | 778 ++++++++ .../flow/api/NavEventResponseOrBuilder.java | 33 + .../io/provlabs/flow/api/NavServiceGrpc.java | 303 +++ .../explorer/service/TokenService.kt | 21 +- .../explorer/service/TokenServiceTest.kt | 27 +- 10 files changed, 3805 insertions(+), 2 deletions(-) create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEvent.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventRequest.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventResponse.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavEventResponseOrBuilder.java create mode 100644 service/src/main/java/io/provlabs/flow/api/NavServiceGrpc.java diff --git a/service/src/main/java/io/provlabs/flow/api/NavEvent.java b/service/src/main/java/io/provlabs/flow/api/NavEvent.java new file mode 100644 index 00000000..7f614735 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEvent.java @@ -0,0 +1,1642 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +/** + *
+ * NavEvent represents a navigation event within a block.
+ * 
+ * + * Protobuf type {@code nav.NavEvent} + */ +public final class NavEvent extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:nav.NavEvent) + NavEventOrBuilder { +private static final long serialVersionUID = 0L; + // Use NavEvent.newBuilder() to construct. + private NavEvent(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private NavEvent() { + txHash_ = ""; + eventType_ = ""; + scopeId_ = ""; + denom_ = ""; + priceDenom_ = ""; + source_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new NavEvent(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private NavEvent( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + blockHeight_ = input.readInt32(); + break; + } + case 16: { + + blockTime_ = input.readUInt64(); + break; + } + case 24: { + + chainId_ = input.readInt32(); + break; + } + case 34: { + java.lang.String s = input.readStringRequireUtf8(); + + txHash_ = s; + break; + } + case 40: { + + eventOrder_ = input.readInt32(); + break; + } + case 50: { + java.lang.String s = input.readStringRequireUtf8(); + + eventType_ = s; + break; + } + case 58: { + java.lang.String s = input.readStringRequireUtf8(); + + scopeId_ = s; + break; + } + case 66: { + java.lang.String s = input.readStringRequireUtf8(); + + denom_ = s; + break; + } + case 72: { + + priceAmount_ = input.readInt64(); + break; + } + case 82: { + java.lang.String s = input.readStringRequireUtf8(); + + priceDenom_ = s; + break; + } + case 88: { + + volume_ = input.readInt64(); + break; + } + case 98: { + java.lang.String s = input.readStringRequireUtf8(); + + source_ = s; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEvent.class, io.provlabs.flow.api.NavEvent.Builder.class); + } + + public static final int BLOCK_HEIGHT_FIELD_NUMBER = 1; + private int blockHeight_; + /** + * int32 block_height = 1; + * @return The blockHeight. + */ + @java.lang.Override + public int getBlockHeight() { + return blockHeight_; + } + + public static final int BLOCK_TIME_FIELD_NUMBER = 2; + private long blockTime_; + /** + * uint64 block_time = 2; + * @return The blockTime. + */ + @java.lang.Override + public long getBlockTime() { + return blockTime_; + } + + public static final int CHAIN_ID_FIELD_NUMBER = 3; + private int chainId_; + /** + * int32 chain_id = 3; + * @return The chainId. + */ + @java.lang.Override + public int getChainId() { + return chainId_; + } + + public static final int TX_HASH_FIELD_NUMBER = 4; + private volatile java.lang.Object txHash_; + /** + * string tx_hash = 4; + * @return The txHash. + */ + @java.lang.Override + public java.lang.String getTxHash() { + java.lang.Object ref = txHash_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + txHash_ = s; + return s; + } + } + /** + * string tx_hash = 4; + * @return The bytes for txHash. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTxHashBytes() { + java.lang.Object ref = txHash_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + txHash_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int EVENT_ORDER_FIELD_NUMBER = 5; + private int eventOrder_; + /** + * int32 event_order = 5; + * @return The eventOrder. + */ + @java.lang.Override + public int getEventOrder() { + return eventOrder_; + } + + public static final int EVENT_TYPE_FIELD_NUMBER = 6; + private volatile java.lang.Object eventType_; + /** + * string event_type = 6; + * @return The eventType. + */ + @java.lang.Override + public java.lang.String getEventType() { + java.lang.Object ref = eventType_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + eventType_ = s; + return s; + } + } + /** + * string event_type = 6; + * @return The bytes for eventType. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getEventTypeBytes() { + java.lang.Object ref = eventType_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + eventType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPE_ID_FIELD_NUMBER = 7; + private volatile java.lang.Object scopeId_; + /** + * string scope_id = 7; + * @return The scopeId. + */ + @java.lang.Override + public java.lang.String getScopeId() { + java.lang.Object ref = scopeId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scopeId_ = s; + return s; + } + } + /** + * string scope_id = 7; + * @return The bytes for scopeId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getScopeIdBytes() { + java.lang.Object ref = scopeId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scopeId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DENOM_FIELD_NUMBER = 8; + private volatile java.lang.Object denom_; + /** + * string denom = 8; + * @return The denom. + */ + @java.lang.Override + public java.lang.String getDenom() { + java.lang.Object ref = denom_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + denom_ = s; + return s; + } + } + /** + * string denom = 8; + * @return The bytes for denom. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDenomBytes() { + java.lang.Object ref = denom_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + denom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PRICE_AMOUNT_FIELD_NUMBER = 9; + private long priceAmount_; + /** + * int64 price_amount = 9; + * @return The priceAmount. + */ + @java.lang.Override + public long getPriceAmount() { + return priceAmount_; + } + + public static final int PRICE_DENOM_FIELD_NUMBER = 10; + private volatile java.lang.Object priceDenom_; + /** + * string price_denom = 10; + * @return The priceDenom. + */ + @java.lang.Override + public java.lang.String getPriceDenom() { + java.lang.Object ref = priceDenom_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + priceDenom_ = s; + return s; + } + } + /** + * string price_denom = 10; + * @return The bytes for priceDenom. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPriceDenomBytes() { + java.lang.Object ref = priceDenom_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + priceDenom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int VOLUME_FIELD_NUMBER = 11; + private long volume_; + /** + * int64 volume = 11; + * @return The volume. + */ + @java.lang.Override + public long getVolume() { + return volume_; + } + + public static final int SOURCE_FIELD_NUMBER = 12; + private volatile java.lang.Object source_; + /** + * string source = 12; + * @return The source. + */ + @java.lang.Override + public java.lang.String getSource() { + java.lang.Object ref = source_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + source_ = s; + return s; + } + } + /** + * string source = 12; + * @return The bytes for source. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getSourceBytes() { + java.lang.Object ref = source_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + source_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (blockHeight_ != 0) { + output.writeInt32(1, blockHeight_); + } + if (blockTime_ != 0L) { + output.writeUInt64(2, blockTime_); + } + if (chainId_ != 0) { + output.writeInt32(3, chainId_); + } + if (!getTxHashBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, txHash_); + } + if (eventOrder_ != 0) { + output.writeInt32(5, eventOrder_); + } + if (!getEventTypeBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 6, eventType_); + } + if (!getScopeIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 7, scopeId_); + } + if (!getDenomBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 8, denom_); + } + if (priceAmount_ != 0L) { + output.writeInt64(9, priceAmount_); + } + if (!getPriceDenomBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 10, priceDenom_); + } + if (volume_ != 0L) { + output.writeInt64(11, volume_); + } + if (!getSourceBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 12, source_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (blockHeight_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, blockHeight_); + } + if (blockTime_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(2, blockTime_); + } + if (chainId_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, chainId_); + } + if (!getTxHashBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, txHash_); + } + if (eventOrder_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, eventOrder_); + } + if (!getEventTypeBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, eventType_); + } + if (!getScopeIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, scopeId_); + } + if (!getDenomBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, denom_); + } + if (priceAmount_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(9, priceAmount_); + } + if (!getPriceDenomBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(10, priceDenom_); + } + if (volume_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(11, volume_); + } + if (!getSourceBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(12, source_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof io.provlabs.flow.api.NavEvent)) { + return super.equals(obj); + } + io.provlabs.flow.api.NavEvent other = (io.provlabs.flow.api.NavEvent) obj; + + if (getBlockHeight() + != other.getBlockHeight()) return false; + if (getBlockTime() + != other.getBlockTime()) return false; + if (getChainId() + != other.getChainId()) return false; + if (!getTxHash() + .equals(other.getTxHash())) return false; + if (getEventOrder() + != other.getEventOrder()) return false; + if (!getEventType() + .equals(other.getEventType())) return false; + if (!getScopeId() + .equals(other.getScopeId())) return false; + if (!getDenom() + .equals(other.getDenom())) return false; + if (getPriceAmount() + != other.getPriceAmount()) return false; + if (!getPriceDenom() + .equals(other.getPriceDenom())) return false; + if (getVolume() + != other.getVolume()) return false; + if (!getSource() + .equals(other.getSource())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + BLOCK_HEIGHT_FIELD_NUMBER; + hash = (53 * hash) + getBlockHeight(); + hash = (37 * hash) + BLOCK_TIME_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getBlockTime()); + hash = (37 * hash) + CHAIN_ID_FIELD_NUMBER; + hash = (53 * hash) + getChainId(); + hash = (37 * hash) + TX_HASH_FIELD_NUMBER; + hash = (53 * hash) + getTxHash().hashCode(); + hash = (37 * hash) + EVENT_ORDER_FIELD_NUMBER; + hash = (53 * hash) + getEventOrder(); + hash = (37 * hash) + EVENT_TYPE_FIELD_NUMBER; + hash = (53 * hash) + getEventType().hashCode(); + hash = (37 * hash) + SCOPE_ID_FIELD_NUMBER; + hash = (53 * hash) + getScopeId().hashCode(); + hash = (37 * hash) + DENOM_FIELD_NUMBER; + hash = (53 * hash) + getDenom().hashCode(); + hash = (37 * hash) + PRICE_AMOUNT_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getPriceAmount()); + hash = (37 * hash) + PRICE_DENOM_FIELD_NUMBER; + hash = (53 * hash) + getPriceDenom().hashCode(); + hash = (37 * hash) + VOLUME_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getVolume()); + hash = (37 * hash) + SOURCE_FIELD_NUMBER; + hash = (53 * hash) + getSource().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static io.provlabs.flow.api.NavEvent parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEvent parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEvent parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEvent parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEvent parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEvent parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.provlabs.flow.api.NavEvent prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+   * NavEvent represents a navigation event within a block.
+   * 
+ * + * Protobuf type {@code nav.NavEvent} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:nav.NavEvent) + io.provlabs.flow.api.NavEventOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEvent_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEvent_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEvent.class, io.provlabs.flow.api.NavEvent.Builder.class); + } + + // Construct using io.provlabs.flow.api.NavEvent.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + blockHeight_ = 0; + + blockTime_ = 0L; + + chainId_ = 0; + + txHash_ = ""; + + eventOrder_ = 0; + + eventType_ = ""; + + scopeId_ = ""; + + denom_ = ""; + + priceAmount_ = 0L; + + priceDenom_ = ""; + + volume_ = 0L; + + source_ = ""; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEvent_descriptor; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEvent getDefaultInstanceForType() { + return io.provlabs.flow.api.NavEvent.getDefaultInstance(); + } + + @java.lang.Override + public io.provlabs.flow.api.NavEvent build() { + io.provlabs.flow.api.NavEvent result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEvent buildPartial() { + io.provlabs.flow.api.NavEvent result = new io.provlabs.flow.api.NavEvent(this); + result.blockHeight_ = blockHeight_; + result.blockTime_ = blockTime_; + result.chainId_ = chainId_; + result.txHash_ = txHash_; + result.eventOrder_ = eventOrder_; + result.eventType_ = eventType_; + result.scopeId_ = scopeId_; + result.denom_ = denom_; + result.priceAmount_ = priceAmount_; + result.priceDenom_ = priceDenom_; + result.volume_ = volume_; + result.source_ = source_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.provlabs.flow.api.NavEvent) { + return mergeFrom((io.provlabs.flow.api.NavEvent)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.provlabs.flow.api.NavEvent other) { + if (other == io.provlabs.flow.api.NavEvent.getDefaultInstance()) return this; + if (other.getBlockHeight() != 0) { + setBlockHeight(other.getBlockHeight()); + } + if (other.getBlockTime() != 0L) { + setBlockTime(other.getBlockTime()); + } + if (other.getChainId() != 0) { + setChainId(other.getChainId()); + } + if (!other.getTxHash().isEmpty()) { + txHash_ = other.txHash_; + onChanged(); + } + if (other.getEventOrder() != 0) { + setEventOrder(other.getEventOrder()); + } + if (!other.getEventType().isEmpty()) { + eventType_ = other.eventType_; + onChanged(); + } + if (!other.getScopeId().isEmpty()) { + scopeId_ = other.scopeId_; + onChanged(); + } + if (!other.getDenom().isEmpty()) { + denom_ = other.denom_; + onChanged(); + } + if (other.getPriceAmount() != 0L) { + setPriceAmount(other.getPriceAmount()); + } + if (!other.getPriceDenom().isEmpty()) { + priceDenom_ = other.priceDenom_; + onChanged(); + } + if (other.getVolume() != 0L) { + setVolume(other.getVolume()); + } + if (!other.getSource().isEmpty()) { + source_ = other.source_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + io.provlabs.flow.api.NavEvent parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (io.provlabs.flow.api.NavEvent) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int blockHeight_ ; + /** + * int32 block_height = 1; + * @return The blockHeight. + */ + @java.lang.Override + public int getBlockHeight() { + return blockHeight_; + } + /** + * int32 block_height = 1; + * @param value The blockHeight to set. + * @return This builder for chaining. + */ + public Builder setBlockHeight(int value) { + + blockHeight_ = value; + onChanged(); + return this; + } + /** + * int32 block_height = 1; + * @return This builder for chaining. + */ + public Builder clearBlockHeight() { + + blockHeight_ = 0; + onChanged(); + return this; + } + + private long blockTime_ ; + /** + * uint64 block_time = 2; + * @return The blockTime. + */ + @java.lang.Override + public long getBlockTime() { + return blockTime_; + } + /** + * uint64 block_time = 2; + * @param value The blockTime to set. + * @return This builder for chaining. + */ + public Builder setBlockTime(long value) { + + blockTime_ = value; + onChanged(); + return this; + } + /** + * uint64 block_time = 2; + * @return This builder for chaining. + */ + public Builder clearBlockTime() { + + blockTime_ = 0L; + onChanged(); + return this; + } + + private int chainId_ ; + /** + * int32 chain_id = 3; + * @return The chainId. + */ + @java.lang.Override + public int getChainId() { + return chainId_; + } + /** + * int32 chain_id = 3; + * @param value The chainId to set. + * @return This builder for chaining. + */ + public Builder setChainId(int value) { + + chainId_ = value; + onChanged(); + return this; + } + /** + * int32 chain_id = 3; + * @return This builder for chaining. + */ + public Builder clearChainId() { + + chainId_ = 0; + onChanged(); + return this; + } + + private java.lang.Object txHash_ = ""; + /** + * string tx_hash = 4; + * @return The txHash. + */ + public java.lang.String getTxHash() { + java.lang.Object ref = txHash_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + txHash_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string tx_hash = 4; + * @return The bytes for txHash. + */ + public com.google.protobuf.ByteString + getTxHashBytes() { + java.lang.Object ref = txHash_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + txHash_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string tx_hash = 4; + * @param value The txHash to set. + * @return This builder for chaining. + */ + public Builder setTxHash( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + txHash_ = value; + onChanged(); + return this; + } + /** + * string tx_hash = 4; + * @return This builder for chaining. + */ + public Builder clearTxHash() { + + txHash_ = getDefaultInstance().getTxHash(); + onChanged(); + return this; + } + /** + * string tx_hash = 4; + * @param value The bytes for txHash to set. + * @return This builder for chaining. + */ + public Builder setTxHashBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + txHash_ = value; + onChanged(); + return this; + } + + private int eventOrder_ ; + /** + * int32 event_order = 5; + * @return The eventOrder. + */ + @java.lang.Override + public int getEventOrder() { + return eventOrder_; + } + /** + * int32 event_order = 5; + * @param value The eventOrder to set. + * @return This builder for chaining. + */ + public Builder setEventOrder(int value) { + + eventOrder_ = value; + onChanged(); + return this; + } + /** + * int32 event_order = 5; + * @return This builder for chaining. + */ + public Builder clearEventOrder() { + + eventOrder_ = 0; + onChanged(); + return this; + } + + private java.lang.Object eventType_ = ""; + /** + * string event_type = 6; + * @return The eventType. + */ + public java.lang.String getEventType() { + java.lang.Object ref = eventType_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + eventType_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string event_type = 6; + * @return The bytes for eventType. + */ + public com.google.protobuf.ByteString + getEventTypeBytes() { + java.lang.Object ref = eventType_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + eventType_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string event_type = 6; + * @param value The eventType to set. + * @return This builder for chaining. + */ + public Builder setEventType( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + eventType_ = value; + onChanged(); + return this; + } + /** + * string event_type = 6; + * @return This builder for chaining. + */ + public Builder clearEventType() { + + eventType_ = getDefaultInstance().getEventType(); + onChanged(); + return this; + } + /** + * string event_type = 6; + * @param value The bytes for eventType to set. + * @return This builder for chaining. + */ + public Builder setEventTypeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + eventType_ = value; + onChanged(); + return this; + } + + private java.lang.Object scopeId_ = ""; + /** + * string scope_id = 7; + * @return The scopeId. + */ + public java.lang.String getScopeId() { + java.lang.Object ref = scopeId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scopeId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string scope_id = 7; + * @return The bytes for scopeId. + */ + public com.google.protobuf.ByteString + getScopeIdBytes() { + java.lang.Object ref = scopeId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scopeId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string scope_id = 7; + * @param value The scopeId to set. + * @return This builder for chaining. + */ + public Builder setScopeId( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + scopeId_ = value; + onChanged(); + return this; + } + /** + * string scope_id = 7; + * @return This builder for chaining. + */ + public Builder clearScopeId() { + + scopeId_ = getDefaultInstance().getScopeId(); + onChanged(); + return this; + } + /** + * string scope_id = 7; + * @param value The bytes for scopeId to set. + * @return This builder for chaining. + */ + public Builder setScopeIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + scopeId_ = value; + onChanged(); + return this; + } + + private java.lang.Object denom_ = ""; + /** + * string denom = 8; + * @return The denom. + */ + public java.lang.String getDenom() { + java.lang.Object ref = denom_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + denom_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string denom = 8; + * @return The bytes for denom. + */ + public com.google.protobuf.ByteString + getDenomBytes() { + java.lang.Object ref = denom_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + denom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string denom = 8; + * @param value The denom to set. + * @return This builder for chaining. + */ + public Builder setDenom( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + denom_ = value; + onChanged(); + return this; + } + /** + * string denom = 8; + * @return This builder for chaining. + */ + public Builder clearDenom() { + + denom_ = getDefaultInstance().getDenom(); + onChanged(); + return this; + } + /** + * string denom = 8; + * @param value The bytes for denom to set. + * @return This builder for chaining. + */ + public Builder setDenomBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + denom_ = value; + onChanged(); + return this; + } + + private long priceAmount_ ; + /** + * int64 price_amount = 9; + * @return The priceAmount. + */ + @java.lang.Override + public long getPriceAmount() { + return priceAmount_; + } + /** + * int64 price_amount = 9; + * @param value The priceAmount to set. + * @return This builder for chaining. + */ + public Builder setPriceAmount(long value) { + + priceAmount_ = value; + onChanged(); + return this; + } + /** + * int64 price_amount = 9; + * @return This builder for chaining. + */ + public Builder clearPriceAmount() { + + priceAmount_ = 0L; + onChanged(); + return this; + } + + private java.lang.Object priceDenom_ = ""; + /** + * string price_denom = 10; + * @return The priceDenom. + */ + public java.lang.String getPriceDenom() { + java.lang.Object ref = priceDenom_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + priceDenom_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string price_denom = 10; + * @return The bytes for priceDenom. + */ + public com.google.protobuf.ByteString + getPriceDenomBytes() { + java.lang.Object ref = priceDenom_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + priceDenom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string price_denom = 10; + * @param value The priceDenom to set. + * @return This builder for chaining. + */ + public Builder setPriceDenom( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + priceDenom_ = value; + onChanged(); + return this; + } + /** + * string price_denom = 10; + * @return This builder for chaining. + */ + public Builder clearPriceDenom() { + + priceDenom_ = getDefaultInstance().getPriceDenom(); + onChanged(); + return this; + } + /** + * string price_denom = 10; + * @param value The bytes for priceDenom to set. + * @return This builder for chaining. + */ + public Builder setPriceDenomBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + priceDenom_ = value; + onChanged(); + return this; + } + + private long volume_ ; + /** + * int64 volume = 11; + * @return The volume. + */ + @java.lang.Override + public long getVolume() { + return volume_; + } + /** + * int64 volume = 11; + * @param value The volume to set. + * @return This builder for chaining. + */ + public Builder setVolume(long value) { + + volume_ = value; + onChanged(); + return this; + } + /** + * int64 volume = 11; + * @return This builder for chaining. + */ + public Builder clearVolume() { + + volume_ = 0L; + onChanged(); + return this; + } + + private java.lang.Object source_ = ""; + /** + * string source = 12; + * @return The source. + */ + public java.lang.String getSource() { + java.lang.Object ref = source_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + source_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string source = 12; + * @return The bytes for source. + */ + public com.google.protobuf.ByteString + getSourceBytes() { + java.lang.Object ref = source_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + source_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string source = 12; + * @param value The source to set. + * @return This builder for chaining. + */ + public Builder setSource( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + source_ = value; + onChanged(); + return this; + } + /** + * string source = 12; + * @return This builder for chaining. + */ + public Builder clearSource() { + + source_ = getDefaultInstance().getSource(); + onChanged(); + return this; + } + /** + * string source = 12; + * @param value The bytes for source to set. + * @return This builder for chaining. + */ + public Builder setSourceBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + source_ = value; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:nav.NavEvent) + } + + // @@protoc_insertion_point(class_scope:nav.NavEvent) + private static final io.provlabs.flow.api.NavEvent DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.provlabs.flow.api.NavEvent(); + } + + public static io.provlabs.flow.api.NavEvent getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public NavEvent parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new NavEvent(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEvent getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java b/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java new file mode 100644 index 00000000..2f46eda5 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java @@ -0,0 +1,117 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +public interface NavEventOrBuilder extends + // @@protoc_insertion_point(interface_extends:nav.NavEvent) + com.google.protobuf.MessageOrBuilder { + + /** + * int32 block_height = 1; + * @return The blockHeight. + */ + int getBlockHeight(); + + /** + * uint64 block_time = 2; + * @return The blockTime. + */ + long getBlockTime(); + + /** + * int32 chain_id = 3; + * @return The chainId. + */ + int getChainId(); + + /** + * string tx_hash = 4; + * @return The txHash. + */ + java.lang.String getTxHash(); + /** + * string tx_hash = 4; + * @return The bytes for txHash. + */ + com.google.protobuf.ByteString + getTxHashBytes(); + + /** + * int32 event_order = 5; + * @return The eventOrder. + */ + int getEventOrder(); + + /** + * string event_type = 6; + * @return The eventType. + */ + java.lang.String getEventType(); + /** + * string event_type = 6; + * @return The bytes for eventType. + */ + com.google.protobuf.ByteString + getEventTypeBytes(); + + /** + * string scope_id = 7; + * @return The scopeId. + */ + java.lang.String getScopeId(); + /** + * string scope_id = 7; + * @return The bytes for scopeId. + */ + com.google.protobuf.ByteString + getScopeIdBytes(); + + /** + * string denom = 8; + * @return The denom. + */ + java.lang.String getDenom(); + /** + * string denom = 8; + * @return The bytes for denom. + */ + com.google.protobuf.ByteString + getDenomBytes(); + + /** + * int64 price_amount = 9; + * @return The priceAmount. + */ + long getPriceAmount(); + + /** + * string price_denom = 10; + * @return The priceDenom. + */ + java.lang.String getPriceDenom(); + /** + * string price_denom = 10; + * @return The bytes for priceDenom. + */ + com.google.protobuf.ByteString + getPriceDenomBytes(); + + /** + * int64 volume = 11; + * @return The volume. + */ + long getVolume(); + + /** + * string source = 12; + * @return The source. + */ + java.lang.String getSource(); + /** + * string source = 12; + * @return The bytes for source. + */ + com.google.protobuf.ByteString + getSourceBytes(); +} diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java b/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java new file mode 100644 index 00000000..f1869834 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java @@ -0,0 +1,80 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +public final class NavEventOuterClass { + private NavEventOuterClass() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_nav_NavEvent_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_nav_NavEvent_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_nav_NavEventRequest_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_nav_NavEventRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_nav_NavEventResponse_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_nav_NavEventResponse_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\017nav_event.proto\022\003nav\"\354\001\n\010NavEvent\022\024\n\014b" + + "lock_height\030\001 \001(\005\022\022\n\nblock_time\030\002 \001(\004\022\020\n" + + "\010chain_id\030\003 \001(\005\022\017\n\007tx_hash\030\004 \001(\t\022\023\n\013even" + + "t_order\030\005 \001(\005\022\022\n\nevent_type\030\006 \001(\t\022\020\n\010sco" + + "pe_id\030\007 \001(\t\022\r\n\005denom\030\010 \001(\t\022\024\n\014price_amou" + + "nt\030\t \001(\003\022\023\n\013price_denom\030\n \001(\t\022\016\n\006volume\030" + + "\013 \001(\003\022\016\n\006source\030\014 \001(\t\"A\n\017NavEventRequest" + + "\022\r\n\005denom\030\001 \001(\t\022\020\n\010scope_id\030\002 \001(\t\022\r\n\005lim" + + "it\030\003 \001(\005\"5\n\020NavEventResponse\022!\n\nnav_even" + + "ts\030\001 \003(\0132\r.nav.NavEvent2I\n\nNavService\022;\n" + + "\014GetNavEvents\022\024.nav.NavEventRequest\032\025.na" + + "v.NavEventResponseB \n\024io.provlabs.flow.a" + + "piP\001Z\006/typesb\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_nav_NavEvent_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_nav_NavEvent_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_nav_NavEvent_descriptor, + new java.lang.String[] { "BlockHeight", "BlockTime", "ChainId", "TxHash", "EventOrder", "EventType", "ScopeId", "Denom", "PriceAmount", "PriceDenom", "Volume", "Source", }); + internal_static_nav_NavEventRequest_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_nav_NavEventRequest_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_nav_NavEventRequest_descriptor, + new java.lang.String[] { "Denom", "ScopeId", "Limit", }); + internal_static_nav_NavEventResponse_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_nav_NavEventResponse_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_nav_NavEventResponse_descriptor, + new java.lang.String[] { "NavEvents", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java b/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java new file mode 100644 index 00000000..fd1701b2 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java @@ -0,0 +1,767 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +/** + *
+ * NavEventRequest represents a request for NavEvents by either denom or scope_id.
+ * 
+ * + * Protobuf type {@code nav.NavEventRequest} + */ +public final class NavEventRequest extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:nav.NavEventRequest) + NavEventRequestOrBuilder { +private static final long serialVersionUID = 0L; + // Use NavEventRequest.newBuilder() to construct. + private NavEventRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private NavEventRequest() { + denom_ = ""; + scopeId_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new NavEventRequest(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private NavEventRequest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + denom_ = s; + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + scopeId_ = s; + break; + } + case 24: { + + limit_ = input.readInt32(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEventRequest.class, io.provlabs.flow.api.NavEventRequest.Builder.class); + } + + public static final int DENOM_FIELD_NUMBER = 1; + private volatile java.lang.Object denom_; + /** + * string denom = 1; + * @return The denom. + */ + @java.lang.Override + public java.lang.String getDenom() { + java.lang.Object ref = denom_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + denom_ = s; + return s; + } + } + /** + * string denom = 1; + * @return The bytes for denom. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDenomBytes() { + java.lang.Object ref = denom_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + denom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SCOPE_ID_FIELD_NUMBER = 2; + private volatile java.lang.Object scopeId_; + /** + * string scope_id = 2; + * @return The scopeId. + */ + @java.lang.Override + public java.lang.String getScopeId() { + java.lang.Object ref = scopeId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scopeId_ = s; + return s; + } + } + /** + * string scope_id = 2; + * @return The bytes for scopeId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getScopeIdBytes() { + java.lang.Object ref = scopeId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scopeId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int LIMIT_FIELD_NUMBER = 3; + private int limit_; + /** + * int32 limit = 3; + * @return The limit. + */ + @java.lang.Override + public int getLimit() { + return limit_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getDenomBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, denom_); + } + if (!getScopeIdBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, scopeId_); + } + if (limit_ != 0) { + output.writeInt32(3, limit_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getDenomBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, denom_); + } + if (!getScopeIdBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, scopeId_); + } + if (limit_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, limit_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof io.provlabs.flow.api.NavEventRequest)) { + return super.equals(obj); + } + io.provlabs.flow.api.NavEventRequest other = (io.provlabs.flow.api.NavEventRequest) obj; + + if (!getDenom() + .equals(other.getDenom())) return false; + if (!getScopeId() + .equals(other.getScopeId())) return false; + if (getLimit() + != other.getLimit()) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + DENOM_FIELD_NUMBER; + hash = (53 * hash) + getDenom().hashCode(); + hash = (37 * hash) + SCOPE_ID_FIELD_NUMBER; + hash = (53 * hash) + getScopeId().hashCode(); + hash = (37 * hash) + LIMIT_FIELD_NUMBER; + hash = (53 * hash) + getLimit(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static io.provlabs.flow.api.NavEventRequest parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventRequest parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventRequest parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.provlabs.flow.api.NavEventRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+   * NavEventRequest represents a request for NavEvents by either denom or scope_id.
+   * 
+ * + * Protobuf type {@code nav.NavEventRequest} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:nav.NavEventRequest) + io.provlabs.flow.api.NavEventRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEventRequest.class, io.provlabs.flow.api.NavEventRequest.Builder.class); + } + + // Construct using io.provlabs.flow.api.NavEventRequest.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + denom_ = ""; + + scopeId_ = ""; + + limit_ = 0; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventRequest_descriptor; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventRequest getDefaultInstanceForType() { + return io.provlabs.flow.api.NavEventRequest.getDefaultInstance(); + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventRequest build() { + io.provlabs.flow.api.NavEventRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventRequest buildPartial() { + io.provlabs.flow.api.NavEventRequest result = new io.provlabs.flow.api.NavEventRequest(this); + result.denom_ = denom_; + result.scopeId_ = scopeId_; + result.limit_ = limit_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.provlabs.flow.api.NavEventRequest) { + return mergeFrom((io.provlabs.flow.api.NavEventRequest)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.provlabs.flow.api.NavEventRequest other) { + if (other == io.provlabs.flow.api.NavEventRequest.getDefaultInstance()) return this; + if (!other.getDenom().isEmpty()) { + denom_ = other.denom_; + onChanged(); + } + if (!other.getScopeId().isEmpty()) { + scopeId_ = other.scopeId_; + onChanged(); + } + if (other.getLimit() != 0) { + setLimit(other.getLimit()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + io.provlabs.flow.api.NavEventRequest parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (io.provlabs.flow.api.NavEventRequest) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object denom_ = ""; + /** + * string denom = 1; + * @return The denom. + */ + public java.lang.String getDenom() { + java.lang.Object ref = denom_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + denom_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string denom = 1; + * @return The bytes for denom. + */ + public com.google.protobuf.ByteString + getDenomBytes() { + java.lang.Object ref = denom_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + denom_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string denom = 1; + * @param value The denom to set. + * @return This builder for chaining. + */ + public Builder setDenom( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + denom_ = value; + onChanged(); + return this; + } + /** + * string denom = 1; + * @return This builder for chaining. + */ + public Builder clearDenom() { + + denom_ = getDefaultInstance().getDenom(); + onChanged(); + return this; + } + /** + * string denom = 1; + * @param value The bytes for denom to set. + * @return This builder for chaining. + */ + public Builder setDenomBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + denom_ = value; + onChanged(); + return this; + } + + private java.lang.Object scopeId_ = ""; + /** + * string scope_id = 2; + * @return The scopeId. + */ + public java.lang.String getScopeId() { + java.lang.Object ref = scopeId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + scopeId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string scope_id = 2; + * @return The bytes for scopeId. + */ + public com.google.protobuf.ByteString + getScopeIdBytes() { + java.lang.Object ref = scopeId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + scopeId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string scope_id = 2; + * @param value The scopeId to set. + * @return This builder for chaining. + */ + public Builder setScopeId( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + scopeId_ = value; + onChanged(); + return this; + } + /** + * string scope_id = 2; + * @return This builder for chaining. + */ + public Builder clearScopeId() { + + scopeId_ = getDefaultInstance().getScopeId(); + onChanged(); + return this; + } + /** + * string scope_id = 2; + * @param value The bytes for scopeId to set. + * @return This builder for chaining. + */ + public Builder setScopeIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + scopeId_ = value; + onChanged(); + return this; + } + + private int limit_ ; + /** + * int32 limit = 3; + * @return The limit. + */ + @java.lang.Override + public int getLimit() { + return limit_; + } + /** + * int32 limit = 3; + * @param value The limit to set. + * @return This builder for chaining. + */ + public Builder setLimit(int value) { + + limit_ = value; + onChanged(); + return this; + } + /** + * int32 limit = 3; + * @return This builder for chaining. + */ + public Builder clearLimit() { + + limit_ = 0; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:nav.NavEventRequest) + } + + // @@protoc_insertion_point(class_scope:nav.NavEventRequest) + private static final io.provlabs.flow.api.NavEventRequest DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.provlabs.flow.api.NavEventRequest(); + } + + public static io.provlabs.flow.api.NavEventRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public NavEventRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new NavEventRequest(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java b/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java new file mode 100644 index 00000000..10ea5778 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java @@ -0,0 +1,39 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +public interface NavEventRequestOrBuilder extends + // @@protoc_insertion_point(interface_extends:nav.NavEventRequest) + com.google.protobuf.MessageOrBuilder { + + /** + * string denom = 1; + * @return The denom. + */ + java.lang.String getDenom(); + /** + * string denom = 1; + * @return The bytes for denom. + */ + com.google.protobuf.ByteString + getDenomBytes(); + + /** + * string scope_id = 2; + * @return The scopeId. + */ + java.lang.String getScopeId(); + /** + * string scope_id = 2; + * @return The bytes for scopeId. + */ + com.google.protobuf.ByteString + getScopeIdBytes(); + + /** + * int32 limit = 3; + * @return The limit. + */ + int getLimit(); +} diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventResponse.java b/service/src/main/java/io/provlabs/flow/api/NavEventResponse.java new file mode 100644 index 00000000..4fbfc9c9 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventResponse.java @@ -0,0 +1,778 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +/** + *
+ * NavEventResponse represents the response containing a list of NavEvents.
+ * 
+ * + * Protobuf type {@code nav.NavEventResponse} + */ +public final class NavEventResponse extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:nav.NavEventResponse) + NavEventResponseOrBuilder { +private static final long serialVersionUID = 0L; + // Use NavEventResponse.newBuilder() to construct. + private NavEventResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private NavEventResponse() { + navEvents_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new NavEventResponse(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private NavEventResponse( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + navEvents_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + navEvents_.add( + input.readMessage(io.provlabs.flow.api.NavEvent.parser(), extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + navEvents_ = java.util.Collections.unmodifiableList(navEvents_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEventResponse.class, io.provlabs.flow.api.NavEventResponse.Builder.class); + } + + public static final int NAV_EVENTS_FIELD_NUMBER = 1; + private java.util.List navEvents_; + /** + * repeated .nav.NavEvent nav_events = 1; + */ + @java.lang.Override + public java.util.List getNavEventsList() { + return navEvents_; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + @java.lang.Override + public java.util.List + getNavEventsOrBuilderList() { + return navEvents_; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + @java.lang.Override + public int getNavEventsCount() { + return navEvents_.size(); + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + @java.lang.Override + public io.provlabs.flow.api.NavEvent getNavEvents(int index) { + return navEvents_.get(index); + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + @java.lang.Override + public io.provlabs.flow.api.NavEventOrBuilder getNavEventsOrBuilder( + int index) { + return navEvents_.get(index); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < navEvents_.size(); i++) { + output.writeMessage(1, navEvents_.get(i)); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < navEvents_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, navEvents_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof io.provlabs.flow.api.NavEventResponse)) { + return super.equals(obj); + } + io.provlabs.flow.api.NavEventResponse other = (io.provlabs.flow.api.NavEventResponse) obj; + + if (!getNavEventsList() + .equals(other.getNavEventsList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (getNavEventsCount() > 0) { + hash = (37 * hash) + NAV_EVENTS_FIELD_NUMBER; + hash = (53 * hash) + getNavEventsList().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static io.provlabs.flow.api.NavEventResponse parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventResponse parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventResponse parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static io.provlabs.flow.api.NavEventResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(io.provlabs.flow.api.NavEventResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+   * NavEventResponse represents the response containing a list of NavEvents.
+   * 
+ * + * Protobuf type {@code nav.NavEventResponse} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:nav.NavEventResponse) + io.provlabs.flow.api.NavEventResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + io.provlabs.flow.api.NavEventResponse.class, io.provlabs.flow.api.NavEventResponse.Builder.class); + } + + // Construct using io.provlabs.flow.api.NavEventResponse.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + getNavEventsFieldBuilder(); + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + if (navEventsBuilder_ == null) { + navEvents_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + navEventsBuilder_.clear(); + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return io.provlabs.flow.api.NavEventOuterClass.internal_static_nav_NavEventResponse_descriptor; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventResponse getDefaultInstanceForType() { + return io.provlabs.flow.api.NavEventResponse.getDefaultInstance(); + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventResponse build() { + io.provlabs.flow.api.NavEventResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventResponse buildPartial() { + io.provlabs.flow.api.NavEventResponse result = new io.provlabs.flow.api.NavEventResponse(this); + int from_bitField0_ = bitField0_; + if (navEventsBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + navEvents_ = java.util.Collections.unmodifiableList(navEvents_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.navEvents_ = navEvents_; + } else { + result.navEvents_ = navEventsBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof io.provlabs.flow.api.NavEventResponse) { + return mergeFrom((io.provlabs.flow.api.NavEventResponse)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(io.provlabs.flow.api.NavEventResponse other) { + if (other == io.provlabs.flow.api.NavEventResponse.getDefaultInstance()) return this; + if (navEventsBuilder_ == null) { + if (!other.navEvents_.isEmpty()) { + if (navEvents_.isEmpty()) { + navEvents_ = other.navEvents_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureNavEventsIsMutable(); + navEvents_.addAll(other.navEvents_); + } + onChanged(); + } + } else { + if (!other.navEvents_.isEmpty()) { + if (navEventsBuilder_.isEmpty()) { + navEventsBuilder_.dispose(); + navEventsBuilder_ = null; + navEvents_ = other.navEvents_; + bitField0_ = (bitField0_ & ~0x00000001); + navEventsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getNavEventsFieldBuilder() : null; + } else { + navEventsBuilder_.addAllMessages(other.navEvents_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + io.provlabs.flow.api.NavEventResponse parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (io.provlabs.flow.api.NavEventResponse) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List navEvents_ = + java.util.Collections.emptyList(); + private void ensureNavEventsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + navEvents_ = new java.util.ArrayList(navEvents_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + io.provlabs.flow.api.NavEvent, io.provlabs.flow.api.NavEvent.Builder, io.provlabs.flow.api.NavEventOrBuilder> navEventsBuilder_; + + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public java.util.List getNavEventsList() { + if (navEventsBuilder_ == null) { + return java.util.Collections.unmodifiableList(navEvents_); + } else { + return navEventsBuilder_.getMessageList(); + } + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public int getNavEventsCount() { + if (navEventsBuilder_ == null) { + return navEvents_.size(); + } else { + return navEventsBuilder_.getCount(); + } + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public io.provlabs.flow.api.NavEvent getNavEvents(int index) { + if (navEventsBuilder_ == null) { + return navEvents_.get(index); + } else { + return navEventsBuilder_.getMessage(index); + } + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder setNavEvents( + int index, io.provlabs.flow.api.NavEvent value) { + if (navEventsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNavEventsIsMutable(); + navEvents_.set(index, value); + onChanged(); + } else { + navEventsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder setNavEvents( + int index, io.provlabs.flow.api.NavEvent.Builder builderForValue) { + if (navEventsBuilder_ == null) { + ensureNavEventsIsMutable(); + navEvents_.set(index, builderForValue.build()); + onChanged(); + } else { + navEventsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder addNavEvents(io.provlabs.flow.api.NavEvent value) { + if (navEventsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNavEventsIsMutable(); + navEvents_.add(value); + onChanged(); + } else { + navEventsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder addNavEvents( + int index, io.provlabs.flow.api.NavEvent value) { + if (navEventsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureNavEventsIsMutable(); + navEvents_.add(index, value); + onChanged(); + } else { + navEventsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder addNavEvents( + io.provlabs.flow.api.NavEvent.Builder builderForValue) { + if (navEventsBuilder_ == null) { + ensureNavEventsIsMutable(); + navEvents_.add(builderForValue.build()); + onChanged(); + } else { + navEventsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder addNavEvents( + int index, io.provlabs.flow.api.NavEvent.Builder builderForValue) { + if (navEventsBuilder_ == null) { + ensureNavEventsIsMutable(); + navEvents_.add(index, builderForValue.build()); + onChanged(); + } else { + navEventsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder addAllNavEvents( + java.lang.Iterable values) { + if (navEventsBuilder_ == null) { + ensureNavEventsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, navEvents_); + onChanged(); + } else { + navEventsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder clearNavEvents() { + if (navEventsBuilder_ == null) { + navEvents_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + navEventsBuilder_.clear(); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public Builder removeNavEvents(int index) { + if (navEventsBuilder_ == null) { + ensureNavEventsIsMutable(); + navEvents_.remove(index); + onChanged(); + } else { + navEventsBuilder_.remove(index); + } + return this; + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public io.provlabs.flow.api.NavEvent.Builder getNavEventsBuilder( + int index) { + return getNavEventsFieldBuilder().getBuilder(index); + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public io.provlabs.flow.api.NavEventOrBuilder getNavEventsOrBuilder( + int index) { + if (navEventsBuilder_ == null) { + return navEvents_.get(index); } else { + return navEventsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public java.util.List + getNavEventsOrBuilderList() { + if (navEventsBuilder_ != null) { + return navEventsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(navEvents_); + } + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public io.provlabs.flow.api.NavEvent.Builder addNavEventsBuilder() { + return getNavEventsFieldBuilder().addBuilder( + io.provlabs.flow.api.NavEvent.getDefaultInstance()); + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public io.provlabs.flow.api.NavEvent.Builder addNavEventsBuilder( + int index) { + return getNavEventsFieldBuilder().addBuilder( + index, io.provlabs.flow.api.NavEvent.getDefaultInstance()); + } + /** + * repeated .nav.NavEvent nav_events = 1; + */ + public java.util.List + getNavEventsBuilderList() { + return getNavEventsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + io.provlabs.flow.api.NavEvent, io.provlabs.flow.api.NavEvent.Builder, io.provlabs.flow.api.NavEventOrBuilder> + getNavEventsFieldBuilder() { + if (navEventsBuilder_ == null) { + navEventsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + io.provlabs.flow.api.NavEvent, io.provlabs.flow.api.NavEvent.Builder, io.provlabs.flow.api.NavEventOrBuilder>( + navEvents_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + navEvents_ = null; + } + return navEventsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:nav.NavEventResponse) + } + + // @@protoc_insertion_point(class_scope:nav.NavEventResponse) + private static final io.provlabs.flow.api.NavEventResponse DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new io.provlabs.flow.api.NavEventResponse(); + } + + public static io.provlabs.flow.api.NavEventResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public NavEventResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new NavEventResponse(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public io.provlabs.flow.api.NavEventResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventResponseOrBuilder.java b/service/src/main/java/io/provlabs/flow/api/NavEventResponseOrBuilder.java new file mode 100644 index 00000000..c73a9163 --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavEventResponseOrBuilder.java @@ -0,0 +1,33 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: nav_event.proto + +package io.provlabs.flow.api; + +public interface NavEventResponseOrBuilder extends + // @@protoc_insertion_point(interface_extends:nav.NavEventResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .nav.NavEvent nav_events = 1; + */ + java.util.List + getNavEventsList(); + /** + * repeated .nav.NavEvent nav_events = 1; + */ + io.provlabs.flow.api.NavEvent getNavEvents(int index); + /** + * repeated .nav.NavEvent nav_events = 1; + */ + int getNavEventsCount(); + /** + * repeated .nav.NavEvent nav_events = 1; + */ + java.util.List + getNavEventsOrBuilderList(); + /** + * repeated .nav.NavEvent nav_events = 1; + */ + io.provlabs.flow.api.NavEventOrBuilder getNavEventsOrBuilder( + int index); +} diff --git a/service/src/main/java/io/provlabs/flow/api/NavServiceGrpc.java b/service/src/main/java/io/provlabs/flow/api/NavServiceGrpc.java new file mode 100644 index 00000000..d47c18ec --- /dev/null +++ b/service/src/main/java/io/provlabs/flow/api/NavServiceGrpc.java @@ -0,0 +1,303 @@ +package io.provlabs.flow.api; + +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; +import static io.grpc.stub.ClientCalls.asyncServerStreamingCall; +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; +import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; + +/** + *
+ * NavService is the gRPC service for retrieving NavEvents.
+ * 
+ */ +@javax.annotation.Generated( + value = "by gRPC proto compiler", + comments = "Source: nav_event.proto") +public final class NavServiceGrpc { + + private NavServiceGrpc() {} + + public static final String SERVICE_NAME = "nav.NavService"; + + // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor getGetNavEventsMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "GetNavEvents", + requestType = io.provlabs.flow.api.NavEventRequest.class, + responseType = io.provlabs.flow.api.NavEventResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetNavEventsMethod() { + io.grpc.MethodDescriptor getGetNavEventsMethod; + if ((getGetNavEventsMethod = NavServiceGrpc.getGetNavEventsMethod) == null) { + synchronized (NavServiceGrpc.class) { + if ((getGetNavEventsMethod = NavServiceGrpc.getGetNavEventsMethod) == null) { + NavServiceGrpc.getGetNavEventsMethod = getGetNavEventsMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetNavEvents")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + io.provlabs.flow.api.NavEventRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + io.provlabs.flow.api.NavEventResponse.getDefaultInstance())) + .setSchemaDescriptor(new NavServiceMethodDescriptorSupplier("GetNavEvents")) + .build(); + } + } + } + return getGetNavEventsMethod; + } + + /** + * Creates a new async stub that supports all call types for the service + */ + public static NavServiceStub newStub(io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public NavServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceStub(channel, callOptions); + } + }; + return NavServiceStub.newStub(factory, channel); + } + + /** + * Creates a new blocking-style stub that supports unary and streaming output calls on the service + */ + public static NavServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public NavServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceBlockingStub(channel, callOptions); + } + }; + return NavServiceBlockingStub.newStub(factory, channel); + } + + /** + * Creates a new ListenableFuture-style stub that supports unary calls on the service + */ + public static NavServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public NavServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceFutureStub(channel, callOptions); + } + }; + return NavServiceFutureStub.newStub(factory, channel); + } + + /** + *
+   * NavService is the gRPC service for retrieving NavEvents.
+   * 
+ */ + public static abstract class NavServiceImplBase implements io.grpc.BindableService { + + /** + */ + public void getNavEvents(io.provlabs.flow.api.NavEventRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(getGetNavEventsMethod(), responseObserver); + } + + @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getGetNavEventsMethod(), + asyncUnaryCall( + new MethodHandlers< + io.provlabs.flow.api.NavEventRequest, + io.provlabs.flow.api.NavEventResponse>( + this, METHODID_GET_NAV_EVENTS))) + .build(); + } + } + + /** + *
+   * NavService is the gRPC service for retrieving NavEvents.
+   * 
+ */ + public static final class NavServiceStub extends io.grpc.stub.AbstractAsyncStub { + private NavServiceStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected NavServiceStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceStub(channel, callOptions); + } + + /** + */ + public void getNavEvents(io.provlabs.flow.api.NavEventRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(getGetNavEventsMethod(), getCallOptions()), request, responseObserver); + } + } + + /** + *
+   * NavService is the gRPC service for retrieving NavEvents.
+   * 
+ */ + public static final class NavServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { + private NavServiceBlockingStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected NavServiceBlockingStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceBlockingStub(channel, callOptions); + } + + /** + */ + public io.provlabs.flow.api.NavEventResponse getNavEvents(io.provlabs.flow.api.NavEventRequest request) { + return blockingUnaryCall( + getChannel(), getGetNavEventsMethod(), getCallOptions(), request); + } + } + + /** + *
+   * NavService is the gRPC service for retrieving NavEvents.
+   * 
+ */ + public static final class NavServiceFutureStub extends io.grpc.stub.AbstractFutureStub { + private NavServiceFutureStub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected NavServiceFutureStub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new NavServiceFutureStub(channel, callOptions); + } + + /** + */ + public com.google.common.util.concurrent.ListenableFuture getNavEvents( + io.provlabs.flow.api.NavEventRequest request) { + return futureUnaryCall( + getChannel().newCall(getGetNavEventsMethod(), getCallOptions()), request); + } + } + + private static final int METHODID_GET_NAV_EVENTS = 0; + + private static final class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final NavServiceImplBase serviceImpl; + private final int methodId; + + MethodHandlers(NavServiceImplBase serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_GET_NAV_EVENTS: + serviceImpl.getNavEvents((io.provlabs.flow.api.NavEventRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + default: + throw new AssertionError(); + } + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + } + + private static abstract class NavServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + NavServiceBaseDescriptorSupplier() {} + + @java.lang.Override + public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { + return io.provlabs.flow.api.NavEventOuterClass.getDescriptor(); + } + + @java.lang.Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("NavService"); + } + } + + private static final class NavServiceFileDescriptorSupplier + extends NavServiceBaseDescriptorSupplier { + NavServiceFileDescriptorSupplier() {} + } + + private static final class NavServiceMethodDescriptorSupplier + extends NavServiceBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + NavServiceMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } + } + + private static volatile io.grpc.ServiceDescriptor serviceDescriptor; + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + io.grpc.ServiceDescriptor result = serviceDescriptor; + if (result == null) { + synchronized (NavServiceGrpc.class) { + result = serviceDescriptor; + if (result == null) { + serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) + .setSchemaDescriptor(new NavServiceFileDescriptorSupplier()) + .addMethod(getGetNavEventsMethod()) + .build(); + } + } + } + return result; + } +} diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 0dabd3cb..17be6233 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -45,6 +45,10 @@ import io.provenance.explorer.model.TokenSupply import io.provenance.explorer.model.base.CoinStr import io.provenance.explorer.model.base.CountStrTotal import io.provenance.explorer.model.base.PagedResults +import io.provlabs.flow.api.NavEvent +import io.provlabs.flow.api.NavEventRequest +import io.provlabs.flow.api.NavEventResponse +import io.provlabs.flow.api.NavServiceGrpc import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map @@ -63,7 +67,7 @@ import java.util.zip.ZipOutputStream import javax.servlet.ServletOutputStream @Service -class TokenService(private val accountClient: AccountGrpcClient) { +class TokenService(private val accountClient: AccountGrpcClient, private val navService: NavServiceGrpc.NavServiceBlockingStub) { protected val logger = logger(TokenService::class) @@ -255,6 +259,21 @@ class TokenService(private val accountClient: AccountGrpcClient) { } } + fun fetchOnChainNavData(denom: String, limit: Int = 100): List = runBlocking { + val request = NavEventRequest.newBuilder() + .setDenom(denom) + .setLimit(limit) + .build() + + try { + val response: NavEventResponse = navService.getNavEvents(request) + return@runBlocking response.navEventsList + } catch (e: Exception) { + logger.error("Error fetching Nav Events: ${e.message}", e) + emptyList() + } + } + enum class TimeFrame(val minutes: Int) { FIVE_MINUTES(5), TWO_HOURS(120), diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 524c2b9e..58b2df2a 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -1,7 +1,11 @@ package io.provenance.explorer.service +import io.grpc.ManagedChannel +import io.grpc.ManagedChannelBuilder import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.grpc.v1.AccountGrpcClient +import io.provlabs.flow.api.NavEvent +import io.provlabs.flow.api.NavServiceGrpc import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import org.joda.time.DateTimeZone @@ -15,11 +19,18 @@ class TokenServiceTest { private lateinit var accountClient: AccountGrpcClient private lateinit var tokenService: TokenService + private lateinit var channel: ManagedChannel + private lateinit var navServiceStub: NavServiceGrpc.NavServiceBlockingStub @BeforeEach fun setUp() { accountClient = AccountGrpcClient(URI("https://www.google.com")) - tokenService = TokenService(accountClient) + channel = ManagedChannelBuilder.forAddress("localhost", 50051) + .usePlaintext() + .build() + + navServiceStub = NavServiceGrpc.newBlockingStub(channel) + tokenService = TokenService(accountClient, navServiceStub) } @Test @@ -61,4 +72,18 @@ class TokenServiceTest { val expectedQuery1 = """%7B%22json%22%3A%7B%22coinDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22coinMinimalDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22timeFrame%22%3A%7B%22custom%22%3A%7B%22timeFrame%22%3A5%2C%22numRecentFrames%22%3A2880%7D%7D%7D%7D""" assertEquals(expectedQuery1, inputQuery1) } + + @Test + fun `test fetchOnChainNavData`() { + val denom = "nhash" + val limit = 100 + + val result: List = tokenService.fetchOnChainNavData(denom, limit) + + result.forEach { navEvent -> + println("NavEvent: BlockHeight=${navEvent.blockHeight}, Denom=${navEvent.denom}") + } + + assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } + } } From 63f6cee6bf7960760bd01cb1778bbbc0ff65e088 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Thu, 12 Sep 2024 15:16:09 -0600 Subject: [PATCH 02/40] add fetch on chain nav data call to call flow api, add a test to run it locally --- .../java/io/provlabs/flow/api/NavEvent.java | 268 ++++++- .../provlabs/flow/api/NavEventOrBuilder.java | 72 ++ .../provlabs/flow/api/NavEventOuterClass.java | 17 +- .../io/provlabs/flow/api/NavEventRequest.java | 673 +++++++++++++++++- .../flow/api/NavEventRequestOrBuilder.java | 103 ++- .../explorer/service/TokenService.kt | 7 +- .../explorer/service/TokenServiceTest.kt | 17 +- 7 files changed, 1132 insertions(+), 25 deletions(-) diff --git a/service/src/main/java/io/provlabs/flow/api/NavEvent.java b/service/src/main/java/io/provlabs/flow/api/NavEvent.java index 7f614735..ac1e0e09 100644 --- a/service/src/main/java/io/provlabs/flow/api/NavEvent.java +++ b/service/src/main/java/io/provlabs/flow/api/NavEvent.java @@ -5,7 +5,7 @@ /** *
- * NavEvent represents a navigation event within a block.
+ * NavEvent represents a Net Asset Value (NAV) event within a block.
  * 
* * Protobuf type {@code nav.NavEvent} @@ -159,6 +159,10 @@ private NavEvent( public static final int BLOCK_HEIGHT_FIELD_NUMBER = 1; private int blockHeight_; /** + *
+   * The block height where this Nav event occurred.
+   * 
+ * * int32 block_height = 1; * @return The blockHeight. */ @@ -170,6 +174,10 @@ public int getBlockHeight() { public static final int BLOCK_TIME_FIELD_NUMBER = 2; private long blockTime_; /** + *
+   * The block time in UNIX epoch format when the Nav event occurred.
+   * 
+ * * uint64 block_time = 2; * @return The blockTime. */ @@ -181,6 +189,10 @@ public long getBlockTime() { public static final int CHAIN_ID_FIELD_NUMBER = 3; private int chainId_; /** + *
+   * The unique chain ID representing the blockchain where this NAV event occurred.
+   * 
+ * * int32 chain_id = 3; * @return The chainId. */ @@ -192,6 +204,10 @@ public int getChainId() { public static final int TX_HASH_FIELD_NUMBER = 4; private volatile java.lang.Object txHash_; /** + *
+   * The tx hash related to this NAV event.
+   * 
+ * * string tx_hash = 4; * @return The txHash. */ @@ -209,6 +225,10 @@ public java.lang.String getTxHash() { } } /** + *
+   * The tx hash related to this NAV event.
+   * 
+ * * string tx_hash = 4; * @return The bytes for txHash. */ @@ -230,6 +250,10 @@ public java.lang.String getTxHash() { public static final int EVENT_ORDER_FIELD_NUMBER = 5; private int eventOrder_; /** + *
+   * The order in which this event was emitted within the block_height and tx_hash.
+   * 
+ * * int32 event_order = 5; * @return The eventOrder. */ @@ -241,6 +265,10 @@ public int getEventOrder() { public static final int EVENT_TYPE_FIELD_NUMBER = 6; private volatile java.lang.Object eventType_; /** + *
+   * The type of Nav event type.
+   * 
+ * * string event_type = 6; * @return The eventType. */ @@ -258,6 +286,10 @@ public java.lang.String getEventType() { } } /** + *
+   * The type of Nav event type.
+   * 
+ * * string event_type = 6; * @return The bytes for eventType. */ @@ -279,6 +311,10 @@ public java.lang.String getEventType() { public static final int SCOPE_ID_FIELD_NUMBER = 7; private volatile java.lang.Object scopeId_; /** + *
+   * The scope ID associated with this Nav.
+   * 
+ * * string scope_id = 7; * @return The scopeId. */ @@ -296,6 +332,10 @@ public java.lang.String getScopeId() { } } /** + *
+   * The scope ID associated with this Nav.
+   * 
+ * * string scope_id = 7; * @return The bytes for scopeId. */ @@ -317,6 +357,10 @@ public java.lang.String getScopeId() { public static final int DENOM_FIELD_NUMBER = 8; private volatile java.lang.Object denom_; /** + *
+   * The token denomination for the Nav.
+   * 
+ * * string denom = 8; * @return The denom. */ @@ -334,6 +378,10 @@ public java.lang.String getDenom() { } } /** + *
+   * The token denomination for the Nav.
+   * 
+ * * string denom = 8; * @return The bytes for denom. */ @@ -355,6 +403,10 @@ public java.lang.String getDenom() { public static final int PRICE_AMOUNT_FIELD_NUMBER = 9; private long priceAmount_; /** + *
+   * The price amount for the NAV.
+   * 
+ * * int64 price_amount = 9; * @return The priceAmount. */ @@ -366,6 +418,10 @@ public long getPriceAmount() { public static final int PRICE_DENOM_FIELD_NUMBER = 10; private volatile java.lang.Object priceDenom_; /** + *
+   * The denomination of the price.
+   * 
+ * * string price_denom = 10; * @return The priceDenom. */ @@ -383,6 +439,10 @@ public java.lang.String getPriceDenom() { } } /** + *
+   * The denomination of the price.
+   * 
+ * * string price_denom = 10; * @return The bytes for priceDenom. */ @@ -404,6 +464,10 @@ public java.lang.String getPriceDenom() { public static final int VOLUME_FIELD_NUMBER = 11; private long volume_; /** + *
+   * The volume of tokens involved in the Nav event.
+   * 
+ * * int64 volume = 11; * @return The volume. */ @@ -415,6 +479,10 @@ public long getVolume() { public static final int SOURCE_FIELD_NUMBER = 12; private volatile java.lang.Object source_; /** + *
+   * The source of the NAV event.
+   * 
+ * * string source = 12; * @return The source. */ @@ -432,6 +500,10 @@ public java.lang.String getSource() { } } /** + *
+   * The source of the NAV event.
+   * 
+ * * string source = 12; * @return The bytes for source. */ @@ -725,7 +797,7 @@ protected Builder newBuilderForType( } /** *
-   * NavEvent represents a navigation event within a block.
+   * NavEvent represents a Net Asset Value (NAV) event within a block.
    * 
* * Protobuf type {@code nav.NavEvent} @@ -948,6 +1020,10 @@ public Builder mergeFrom( private int blockHeight_ ; /** + *
+     * The block height where this Nav event occurred.
+     * 
+ * * int32 block_height = 1; * @return The blockHeight. */ @@ -956,6 +1032,10 @@ public int getBlockHeight() { return blockHeight_; } /** + *
+     * The block height where this Nav event occurred.
+     * 
+ * * int32 block_height = 1; * @param value The blockHeight to set. * @return This builder for chaining. @@ -967,6 +1047,10 @@ public Builder setBlockHeight(int value) { return this; } /** + *
+     * The block height where this Nav event occurred.
+     * 
+ * * int32 block_height = 1; * @return This builder for chaining. */ @@ -979,6 +1063,10 @@ public Builder clearBlockHeight() { private long blockTime_ ; /** + *
+     * The block time in UNIX epoch format when the Nav event occurred.
+     * 
+ * * uint64 block_time = 2; * @return The blockTime. */ @@ -987,6 +1075,10 @@ public long getBlockTime() { return blockTime_; } /** + *
+     * The block time in UNIX epoch format when the Nav event occurred.
+     * 
+ * * uint64 block_time = 2; * @param value The blockTime to set. * @return This builder for chaining. @@ -998,6 +1090,10 @@ public Builder setBlockTime(long value) { return this; } /** + *
+     * The block time in UNIX epoch format when the Nav event occurred.
+     * 
+ * * uint64 block_time = 2; * @return This builder for chaining. */ @@ -1010,6 +1106,10 @@ public Builder clearBlockTime() { private int chainId_ ; /** + *
+     * The unique chain ID representing the blockchain where this NAV event occurred.
+     * 
+ * * int32 chain_id = 3; * @return The chainId. */ @@ -1018,6 +1118,10 @@ public int getChainId() { return chainId_; } /** + *
+     * The unique chain ID representing the blockchain where this NAV event occurred.
+     * 
+ * * int32 chain_id = 3; * @param value The chainId to set. * @return This builder for chaining. @@ -1029,6 +1133,10 @@ public Builder setChainId(int value) { return this; } /** + *
+     * The unique chain ID representing the blockchain where this NAV event occurred.
+     * 
+ * * int32 chain_id = 3; * @return This builder for chaining. */ @@ -1041,6 +1149,10 @@ public Builder clearChainId() { private java.lang.Object txHash_ = ""; /** + *
+     * The tx hash related to this NAV event.
+     * 
+ * * string tx_hash = 4; * @return The txHash. */ @@ -1057,6 +1169,10 @@ public java.lang.String getTxHash() { } } /** + *
+     * The tx hash related to this NAV event.
+     * 
+ * * string tx_hash = 4; * @return The bytes for txHash. */ @@ -1074,6 +1190,10 @@ public java.lang.String getTxHash() { } } /** + *
+     * The tx hash related to this NAV event.
+     * 
+ * * string tx_hash = 4; * @param value The txHash to set. * @return This builder for chaining. @@ -1089,6 +1209,10 @@ public Builder setTxHash( return this; } /** + *
+     * The tx hash related to this NAV event.
+     * 
+ * * string tx_hash = 4; * @return This builder for chaining. */ @@ -1099,6 +1223,10 @@ public Builder clearTxHash() { return this; } /** + *
+     * The tx hash related to this NAV event.
+     * 
+ * * string tx_hash = 4; * @param value The bytes for txHash to set. * @return This builder for chaining. @@ -1117,6 +1245,10 @@ public Builder setTxHashBytes( private int eventOrder_ ; /** + *
+     * The order in which this event was emitted within the block_height and tx_hash.
+     * 
+ * * int32 event_order = 5; * @return The eventOrder. */ @@ -1125,6 +1257,10 @@ public int getEventOrder() { return eventOrder_; } /** + *
+     * The order in which this event was emitted within the block_height and tx_hash.
+     * 
+ * * int32 event_order = 5; * @param value The eventOrder to set. * @return This builder for chaining. @@ -1136,6 +1272,10 @@ public Builder setEventOrder(int value) { return this; } /** + *
+     * The order in which this event was emitted within the block_height and tx_hash.
+     * 
+ * * int32 event_order = 5; * @return This builder for chaining. */ @@ -1148,6 +1288,10 @@ public Builder clearEventOrder() { private java.lang.Object eventType_ = ""; /** + *
+     * The type of Nav event type.
+     * 
+ * * string event_type = 6; * @return The eventType. */ @@ -1164,6 +1308,10 @@ public java.lang.String getEventType() { } } /** + *
+     * The type of Nav event type.
+     * 
+ * * string event_type = 6; * @return The bytes for eventType. */ @@ -1181,6 +1329,10 @@ public java.lang.String getEventType() { } } /** + *
+     * The type of Nav event type.
+     * 
+ * * string event_type = 6; * @param value The eventType to set. * @return This builder for chaining. @@ -1196,6 +1348,10 @@ public Builder setEventType( return this; } /** + *
+     * The type of Nav event type.
+     * 
+ * * string event_type = 6; * @return This builder for chaining. */ @@ -1206,6 +1362,10 @@ public Builder clearEventType() { return this; } /** + *
+     * The type of Nav event type.
+     * 
+ * * string event_type = 6; * @param value The bytes for eventType to set. * @return This builder for chaining. @@ -1224,6 +1384,10 @@ public Builder setEventTypeBytes( private java.lang.Object scopeId_ = ""; /** + *
+     * The scope ID associated with this Nav.
+     * 
+ * * string scope_id = 7; * @return The scopeId. */ @@ -1240,6 +1404,10 @@ public java.lang.String getScopeId() { } } /** + *
+     * The scope ID associated with this Nav.
+     * 
+ * * string scope_id = 7; * @return The bytes for scopeId. */ @@ -1257,6 +1425,10 @@ public java.lang.String getScopeId() { } } /** + *
+     * The scope ID associated with this Nav.
+     * 
+ * * string scope_id = 7; * @param value The scopeId to set. * @return This builder for chaining. @@ -1272,6 +1444,10 @@ public Builder setScopeId( return this; } /** + *
+     * The scope ID associated with this Nav.
+     * 
+ * * string scope_id = 7; * @return This builder for chaining. */ @@ -1282,6 +1458,10 @@ public Builder clearScopeId() { return this; } /** + *
+     * The scope ID associated with this Nav.
+     * 
+ * * string scope_id = 7; * @param value The bytes for scopeId to set. * @return This builder for chaining. @@ -1300,6 +1480,10 @@ public Builder setScopeIdBytes( private java.lang.Object denom_ = ""; /** + *
+     * The token denomination for the Nav.
+     * 
+ * * string denom = 8; * @return The denom. */ @@ -1316,6 +1500,10 @@ public java.lang.String getDenom() { } } /** + *
+     * The token denomination for the Nav.
+     * 
+ * * string denom = 8; * @return The bytes for denom. */ @@ -1333,6 +1521,10 @@ public java.lang.String getDenom() { } } /** + *
+     * The token denomination for the Nav.
+     * 
+ * * string denom = 8; * @param value The denom to set. * @return This builder for chaining. @@ -1348,6 +1540,10 @@ public Builder setDenom( return this; } /** + *
+     * The token denomination for the Nav.
+     * 
+ * * string denom = 8; * @return This builder for chaining. */ @@ -1358,6 +1554,10 @@ public Builder clearDenom() { return this; } /** + *
+     * The token denomination for the Nav.
+     * 
+ * * string denom = 8; * @param value The bytes for denom to set. * @return This builder for chaining. @@ -1376,6 +1576,10 @@ public Builder setDenomBytes( private long priceAmount_ ; /** + *
+     * The price amount for the NAV.
+     * 
+ * * int64 price_amount = 9; * @return The priceAmount. */ @@ -1384,6 +1588,10 @@ public long getPriceAmount() { return priceAmount_; } /** + *
+     * The price amount for the NAV.
+     * 
+ * * int64 price_amount = 9; * @param value The priceAmount to set. * @return This builder for chaining. @@ -1395,6 +1603,10 @@ public Builder setPriceAmount(long value) { return this; } /** + *
+     * The price amount for the NAV.
+     * 
+ * * int64 price_amount = 9; * @return This builder for chaining. */ @@ -1407,6 +1619,10 @@ public Builder clearPriceAmount() { private java.lang.Object priceDenom_ = ""; /** + *
+     * The denomination of the price.
+     * 
+ * * string price_denom = 10; * @return The priceDenom. */ @@ -1423,6 +1639,10 @@ public java.lang.String getPriceDenom() { } } /** + *
+     * The denomination of the price.
+     * 
+ * * string price_denom = 10; * @return The bytes for priceDenom. */ @@ -1440,6 +1660,10 @@ public java.lang.String getPriceDenom() { } } /** + *
+     * The denomination of the price.
+     * 
+ * * string price_denom = 10; * @param value The priceDenom to set. * @return This builder for chaining. @@ -1455,6 +1679,10 @@ public Builder setPriceDenom( return this; } /** + *
+     * The denomination of the price.
+     * 
+ * * string price_denom = 10; * @return This builder for chaining. */ @@ -1465,6 +1693,10 @@ public Builder clearPriceDenom() { return this; } /** + *
+     * The denomination of the price.
+     * 
+ * * string price_denom = 10; * @param value The bytes for priceDenom to set. * @return This builder for chaining. @@ -1483,6 +1715,10 @@ public Builder setPriceDenomBytes( private long volume_ ; /** + *
+     * The volume of tokens involved in the Nav event.
+     * 
+ * * int64 volume = 11; * @return The volume. */ @@ -1491,6 +1727,10 @@ public long getVolume() { return volume_; } /** + *
+     * The volume of tokens involved in the Nav event.
+     * 
+ * * int64 volume = 11; * @param value The volume to set. * @return This builder for chaining. @@ -1502,6 +1742,10 @@ public Builder setVolume(long value) { return this; } /** + *
+     * The volume of tokens involved in the Nav event.
+     * 
+ * * int64 volume = 11; * @return This builder for chaining. */ @@ -1514,6 +1758,10 @@ public Builder clearVolume() { private java.lang.Object source_ = ""; /** + *
+     * The source of the NAV event.
+     * 
+ * * string source = 12; * @return The source. */ @@ -1530,6 +1778,10 @@ public java.lang.String getSource() { } } /** + *
+     * The source of the NAV event.
+     * 
+ * * string source = 12; * @return The bytes for source. */ @@ -1547,6 +1799,10 @@ public java.lang.String getSource() { } } /** + *
+     * The source of the NAV event.
+     * 
+ * * string source = 12; * @param value The source to set. * @return This builder for chaining. @@ -1562,6 +1818,10 @@ public Builder setSource( return this; } /** + *
+     * The source of the NAV event.
+     * 
+ * * string source = 12; * @return This builder for chaining. */ @@ -1572,6 +1832,10 @@ public Builder clearSource() { return this; } /** + *
+     * The source of the NAV event.
+     * 
+ * * string source = 12; * @param value The bytes for source to set. * @return This builder for chaining. diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java b/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java index 2f46eda5..634778c0 100644 --- a/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java +++ b/service/src/main/java/io/provlabs/flow/api/NavEventOrBuilder.java @@ -8,29 +8,49 @@ public interface NavEventOrBuilder extends com.google.protobuf.MessageOrBuilder { /** + *
+   * The block height where this Nav event occurred.
+   * 
+ * * int32 block_height = 1; * @return The blockHeight. */ int getBlockHeight(); /** + *
+   * The block time in UNIX epoch format when the Nav event occurred.
+   * 
+ * * uint64 block_time = 2; * @return The blockTime. */ long getBlockTime(); /** + *
+   * The unique chain ID representing the blockchain where this NAV event occurred.
+   * 
+ * * int32 chain_id = 3; * @return The chainId. */ int getChainId(); /** + *
+   * The tx hash related to this NAV event.
+   * 
+ * * string tx_hash = 4; * @return The txHash. */ java.lang.String getTxHash(); /** + *
+   * The tx hash related to this NAV event.
+   * 
+ * * string tx_hash = 4; * @return The bytes for txHash. */ @@ -38,17 +58,29 @@ public interface NavEventOrBuilder extends getTxHashBytes(); /** + *
+   * The order in which this event was emitted within the block_height and tx_hash.
+   * 
+ * * int32 event_order = 5; * @return The eventOrder. */ int getEventOrder(); /** + *
+   * The type of Nav event type.
+   * 
+ * * string event_type = 6; * @return The eventType. */ java.lang.String getEventType(); /** + *
+   * The type of Nav event type.
+   * 
+ * * string event_type = 6; * @return The bytes for eventType. */ @@ -56,11 +88,19 @@ public interface NavEventOrBuilder extends getEventTypeBytes(); /** + *
+   * The scope ID associated with this Nav.
+   * 
+ * * string scope_id = 7; * @return The scopeId. */ java.lang.String getScopeId(); /** + *
+   * The scope ID associated with this Nav.
+   * 
+ * * string scope_id = 7; * @return The bytes for scopeId. */ @@ -68,11 +108,19 @@ public interface NavEventOrBuilder extends getScopeIdBytes(); /** + *
+   * The token denomination for the Nav.
+   * 
+ * * string denom = 8; * @return The denom. */ java.lang.String getDenom(); /** + *
+   * The token denomination for the Nav.
+   * 
+ * * string denom = 8; * @return The bytes for denom. */ @@ -80,17 +128,29 @@ public interface NavEventOrBuilder extends getDenomBytes(); /** + *
+   * The price amount for the NAV.
+   * 
+ * * int64 price_amount = 9; * @return The priceAmount. */ long getPriceAmount(); /** + *
+   * The denomination of the price.
+   * 
+ * * string price_denom = 10; * @return The priceDenom. */ java.lang.String getPriceDenom(); /** + *
+   * The denomination of the price.
+   * 
+ * * string price_denom = 10; * @return The bytes for priceDenom. */ @@ -98,17 +158,29 @@ public interface NavEventOrBuilder extends getPriceDenomBytes(); /** + *
+   * The volume of tokens involved in the Nav event.
+   * 
+ * * int64 volume = 11; * @return The volume. */ long getVolume(); /** + *
+   * The source of the NAV event.
+   * 
+ * * string source = 12; * @return The source. */ java.lang.String getSource(); /** + *
+   * The source of the NAV event.
+   * 
+ * * string source = 12; * @return The bytes for source. */ diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java b/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java index f1869834..7dafd981 100644 --- a/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java +++ b/service/src/main/java/io/provlabs/flow/api/NavEventOuterClass.java @@ -44,13 +44,14 @@ public static void registerAllExtensions( "t_order\030\005 \001(\005\022\022\n\nevent_type\030\006 \001(\t\022\020\n\010sco" + "pe_id\030\007 \001(\t\022\r\n\005denom\030\010 \001(\t\022\024\n\014price_amou" + "nt\030\t \001(\003\022\023\n\013price_denom\030\n \001(\t\022\016\n\006volume\030" + - "\013 \001(\003\022\016\n\006source\030\014 \001(\t\"A\n\017NavEventRequest" + - "\022\r\n\005denom\030\001 \001(\t\022\020\n\010scope_id\030\002 \001(\t\022\r\n\005lim" + - "it\030\003 \001(\005\"5\n\020NavEventResponse\022!\n\nnav_even" + - "ts\030\001 \003(\0132\r.nav.NavEvent2I\n\nNavService\022;\n" + - "\014GetNavEvents\022\024.nav.NavEventRequest\032\025.na" + - "v.NavEventResponseB \n\024io.provlabs.flow.a" + - "piP\001Z\006/typesb\006proto3" + "\013 \001(\003\022\016\n\006source\030\014 \001(\t\"{\n\017NavEventRequest" + + "\022\r\n\005denom\030\001 \001(\t\022\020\n\010scope_id\030\002 \001(\t\022\024\n\014pri" + + "ce_denoms\030\003 \003(\t\022\021\n\tfrom_date\030\004 \001(\t\022\017\n\007to" + + "_date\030\005 \001(\t\022\r\n\005limit\030\006 \001(\005\"5\n\020NavEventRe" + + "sponse\022!\n\nnav_events\030\001 \003(\0132\r.nav.NavEven" + + "t2I\n\nNavService\022;\n\014GetNavEvents\022\024.nav.Na" + + "vEventRequest\032\025.nav.NavEventResponseB \n\024" + + "io.provlabs.flow.apiP\001Z\006/typesb\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -67,7 +68,7 @@ public static void registerAllExtensions( internal_static_nav_NavEventRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_nav_NavEventRequest_descriptor, - new java.lang.String[] { "Denom", "ScopeId", "Limit", }); + new java.lang.String[] { "Denom", "ScopeId", "PriceDenoms", "FromDate", "ToDate", "Limit", }); internal_static_nav_NavEventResponse_descriptor = getDescriptor().getMessageTypes().get(2); internal_static_nav_NavEventResponse_fieldAccessorTable = new diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java b/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java index fd1701b2..aefc6493 100644 --- a/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java +++ b/service/src/main/java/io/provlabs/flow/api/NavEventRequest.java @@ -5,7 +5,8 @@ /** *
- * NavEventRequest represents a request for NavEvents by either denom or scope_id.
+ * NavEventRequest represents a request for NavEvents by either `denom` or `scope_id`.
+ * One of `denom` or `scope_id` must be provided; the other fields are optional.
  * 
* * Protobuf type {@code nav.NavEventRequest} @@ -22,6 +23,9 @@ private NavEventRequest(com.google.protobuf.GeneratedMessageV3.Builder builde private NavEventRequest() { denom_ = ""; scopeId_ = ""; + priceDenoms_ = com.google.protobuf.LazyStringArrayList.EMPTY; + fromDate_ = ""; + toDate_ = ""; } @java.lang.Override @@ -44,6 +48,7 @@ private NavEventRequest( if (extensionRegistry == null) { throw new java.lang.NullPointerException(); } + int mutable_bitField0_ = 0; com.google.protobuf.UnknownFieldSet.Builder unknownFields = com.google.protobuf.UnknownFieldSet.newBuilder(); try { @@ -66,7 +71,28 @@ private NavEventRequest( scopeId_ = s; break; } - case 24: { + case 26: { + java.lang.String s = input.readStringRequireUtf8(); + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + priceDenoms_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000001; + } + priceDenoms_.add(s); + break; + } + case 34: { + java.lang.String s = input.readStringRequireUtf8(); + + fromDate_ = s; + break; + } + case 42: { + java.lang.String s = input.readStringRequireUtf8(); + + toDate_ = s; + break; + } + case 48: { limit_ = input.readInt32(); break; @@ -86,6 +112,9 @@ private NavEventRequest( throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + priceDenoms_ = priceDenoms_.getUnmodifiableView(); + } this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } @@ -106,6 +135,10 @@ private NavEventRequest( public static final int DENOM_FIELD_NUMBER = 1; private volatile java.lang.Object denom_; /** + *
+   * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string denom = 1; * @return The denom. */ @@ -123,6 +156,10 @@ public java.lang.String getDenom() { } } /** + *
+   * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string denom = 1; * @return The bytes for denom. */ @@ -144,6 +181,10 @@ public java.lang.String getDenom() { public static final int SCOPE_ID_FIELD_NUMBER = 2; private volatile java.lang.Object scopeId_; /** + *
+   * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string scope_id = 2; * @return The scopeId. */ @@ -161,6 +202,10 @@ public java.lang.String getScopeId() { } } /** + *
+   * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string scope_id = 2; * @return The bytes for scopeId. */ @@ -179,10 +224,157 @@ public java.lang.String getScopeId() { } } - public static final int LIMIT_FIELD_NUMBER = 3; + public static final int PRICE_DENOMS_FIELD_NUMBER = 3; + private com.google.protobuf.LazyStringList priceDenoms_; + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @return A list containing the priceDenoms. + */ + public com.google.protobuf.ProtocolStringList + getPriceDenomsList() { + return priceDenoms_; + } + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @return The count of priceDenoms. + */ + public int getPriceDenomsCount() { + return priceDenoms_.size(); + } + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the element to return. + * @return The priceDenoms at the given index. + */ + public java.lang.String getPriceDenoms(int index) { + return priceDenoms_.get(index); + } + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the value to return. + * @return The bytes of the priceDenoms at the given index. + */ + public com.google.protobuf.ByteString + getPriceDenomsBytes(int index) { + return priceDenoms_.getByteString(index); + } + + public static final int FROM_DATE_FIELD_NUMBER = 4; + private volatile java.lang.Object fromDate_; + /** + *
+   * Optional. The start date (in string format) to filter events.
+   * 
+ * + * string from_date = 4; + * @return The fromDate. + */ + @java.lang.Override + public java.lang.String getFromDate() { + java.lang.Object ref = fromDate_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + fromDate_ = s; + return s; + } + } + /** + *
+   * Optional. The start date (in string format) to filter events.
+   * 
+ * + * string from_date = 4; + * @return The bytes for fromDate. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getFromDateBytes() { + java.lang.Object ref = fromDate_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + fromDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TO_DATE_FIELD_NUMBER = 5; + private volatile java.lang.Object toDate_; + /** + *
+   * Optional. The end date (in string format) to filter events.
+   * 
+ * + * string to_date = 5; + * @return The toDate. + */ + @java.lang.Override + public java.lang.String getToDate() { + java.lang.Object ref = toDate_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + toDate_ = s; + return s; + } + } + /** + *
+   * Optional. The end date (in string format) to filter events.
+   * 
+ * + * string to_date = 5; + * @return The bytes for toDate. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getToDateBytes() { + java.lang.Object ref = toDate_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + toDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int LIMIT_FIELD_NUMBER = 6; private int limit_; /** - * int32 limit = 3; + *
+   * Optional. The maximum number of results to return. If not provided, defaults to 100.
+   * 
+ * + * int32 limit = 6; * @return The limit. */ @java.lang.Override @@ -210,8 +402,17 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!getScopeIdBytes().isEmpty()) { com.google.protobuf.GeneratedMessageV3.writeString(output, 2, scopeId_); } + for (int i = 0; i < priceDenoms_.size(); i++) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, priceDenoms_.getRaw(i)); + } + if (!getFromDateBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, fromDate_); + } + if (!getToDateBytes().isEmpty()) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, toDate_); + } if (limit_ != 0) { - output.writeInt32(3, limit_); + output.writeInt32(6, limit_); } unknownFields.writeTo(output); } @@ -228,9 +429,23 @@ public int getSerializedSize() { if (!getScopeIdBytes().isEmpty()) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, scopeId_); } + { + int dataSize = 0; + for (int i = 0; i < priceDenoms_.size(); i++) { + dataSize += computeStringSizeNoTag(priceDenoms_.getRaw(i)); + } + size += dataSize; + size += 1 * getPriceDenomsList().size(); + } + if (!getFromDateBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, fromDate_); + } + if (!getToDateBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, toDate_); + } if (limit_ != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, limit_); + .computeInt32Size(6, limit_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -251,6 +466,12 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getDenom())) return false; if (!getScopeId() .equals(other.getScopeId())) return false; + if (!getPriceDenomsList() + .equals(other.getPriceDenomsList())) return false; + if (!getFromDate() + .equals(other.getFromDate())) return false; + if (!getToDate() + .equals(other.getToDate())) return false; if (getLimit() != other.getLimit()) return false; if (!unknownFields.equals(other.unknownFields)) return false; @@ -268,6 +489,14 @@ public int hashCode() { hash = (53 * hash) + getDenom().hashCode(); hash = (37 * hash) + SCOPE_ID_FIELD_NUMBER; hash = (53 * hash) + getScopeId().hashCode(); + if (getPriceDenomsCount() > 0) { + hash = (37 * hash) + PRICE_DENOMS_FIELD_NUMBER; + hash = (53 * hash) + getPriceDenomsList().hashCode(); + } + hash = (37 * hash) + FROM_DATE_FIELD_NUMBER; + hash = (53 * hash) + getFromDate().hashCode(); + hash = (37 * hash) + TO_DATE_FIELD_NUMBER; + hash = (53 * hash) + getToDate().hashCode(); hash = (37 * hash) + LIMIT_FIELD_NUMBER; hash = (53 * hash) + getLimit(); hash = (29 * hash) + unknownFields.hashCode(); @@ -367,7 +596,8 @@ protected Builder newBuilderForType( } /** *
-   * NavEventRequest represents a request for NavEvents by either denom or scope_id.
+   * NavEventRequest represents a request for NavEvents by either `denom` or `scope_id`.
+   * One of `denom` or `scope_id` must be provided; the other fields are optional.
    * 
* * Protobuf type {@code nav.NavEventRequest} @@ -411,6 +641,12 @@ public Builder clear() { scopeId_ = ""; + priceDenoms_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + fromDate_ = ""; + + toDate_ = ""; + limit_ = 0; return this; @@ -439,8 +675,16 @@ public io.provlabs.flow.api.NavEventRequest build() { @java.lang.Override public io.provlabs.flow.api.NavEventRequest buildPartial() { io.provlabs.flow.api.NavEventRequest result = new io.provlabs.flow.api.NavEventRequest(this); + int from_bitField0_ = bitField0_; result.denom_ = denom_; result.scopeId_ = scopeId_; + if (((bitField0_ & 0x00000001) != 0)) { + priceDenoms_ = priceDenoms_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.priceDenoms_ = priceDenoms_; + result.fromDate_ = fromDate_; + result.toDate_ = toDate_; result.limit_ = limit_; onBuilt(); return result; @@ -498,6 +742,24 @@ public Builder mergeFrom(io.provlabs.flow.api.NavEventRequest other) { scopeId_ = other.scopeId_; onChanged(); } + if (!other.priceDenoms_.isEmpty()) { + if (priceDenoms_.isEmpty()) { + priceDenoms_ = other.priceDenoms_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensurePriceDenomsIsMutable(); + priceDenoms_.addAll(other.priceDenoms_); + } + onChanged(); + } + if (!other.getFromDate().isEmpty()) { + fromDate_ = other.fromDate_; + onChanged(); + } + if (!other.getToDate().isEmpty()) { + toDate_ = other.toDate_; + onChanged(); + } if (other.getLimit() != 0) { setLimit(other.getLimit()); } @@ -529,9 +791,14 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private java.lang.Object denom_ = ""; /** + *
+     * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string denom = 1; * @return The denom. */ @@ -548,6 +815,10 @@ public java.lang.String getDenom() { } } /** + *
+     * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string denom = 1; * @return The bytes for denom. */ @@ -565,6 +836,10 @@ public java.lang.String getDenom() { } } /** + *
+     * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string denom = 1; * @param value The denom to set. * @return This builder for chaining. @@ -580,6 +855,10 @@ public Builder setDenom( return this; } /** + *
+     * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string denom = 1; * @return This builder for chaining. */ @@ -590,6 +869,10 @@ public Builder clearDenom() { return this; } /** + *
+     * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string denom = 1; * @param value The bytes for denom to set. * @return This builder for chaining. @@ -608,6 +891,10 @@ public Builder setDenomBytes( private java.lang.Object scopeId_ = ""; /** + *
+     * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string scope_id = 2; * @return The scopeId. */ @@ -624,6 +911,10 @@ public java.lang.String getScopeId() { } } /** + *
+     * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string scope_id = 2; * @return The bytes for scopeId. */ @@ -641,6 +932,10 @@ public java.lang.String getScopeId() { } } /** + *
+     * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string scope_id = 2; * @param value The scopeId to set. * @return This builder for chaining. @@ -656,6 +951,10 @@ public Builder setScopeId( return this; } /** + *
+     * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string scope_id = 2; * @return This builder for chaining. */ @@ -666,6 +965,10 @@ public Builder clearScopeId() { return this; } /** + *
+     * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+     * 
+ * * string scope_id = 2; * @param value The bytes for scopeId to set. * @return This builder for chaining. @@ -682,9 +985,351 @@ public Builder setScopeIdBytes( return this; } + private com.google.protobuf.LazyStringList priceDenoms_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensurePriceDenomsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + priceDenoms_ = new com.google.protobuf.LazyStringArrayList(priceDenoms_); + bitField0_ |= 0x00000001; + } + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @return A list containing the priceDenoms. + */ + public com.google.protobuf.ProtocolStringList + getPriceDenomsList() { + return priceDenoms_.getUnmodifiableView(); + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @return The count of priceDenoms. + */ + public int getPriceDenomsCount() { + return priceDenoms_.size(); + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the element to return. + * @return The priceDenoms at the given index. + */ + public java.lang.String getPriceDenoms(int index) { + return priceDenoms_.get(index); + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the value to return. + * @return The bytes of the priceDenoms at the given index. + */ + public com.google.protobuf.ByteString + getPriceDenomsBytes(int index) { + return priceDenoms_.getByteString(index); + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param index The index to set the value at. + * @param value The priceDenoms to set. + * @return This builder for chaining. + */ + public Builder setPriceDenoms( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensurePriceDenomsIsMutable(); + priceDenoms_.set(index, value); + onChanged(); + return this; + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param value The priceDenoms to add. + * @return This builder for chaining. + */ + public Builder addPriceDenoms( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensurePriceDenomsIsMutable(); + priceDenoms_.add(value); + onChanged(); + return this; + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param values The priceDenoms to add. + * @return This builder for chaining. + */ + public Builder addAllPriceDenoms( + java.lang.Iterable values) { + ensurePriceDenomsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, priceDenoms_); + onChanged(); + return this; + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @return This builder for chaining. + */ + public Builder clearPriceDenoms() { + priceDenoms_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + *
+     * Optional. A list of price denominations to filter by.
+     * 
+ * + * repeated string price_denoms = 3; + * @param value The bytes of the priceDenoms to add. + * @return This builder for chaining. + */ + public Builder addPriceDenomsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + ensurePriceDenomsIsMutable(); + priceDenoms_.add(value); + onChanged(); + return this; + } + + private java.lang.Object fromDate_ = ""; + /** + *
+     * Optional. The start date (in string format) to filter events.
+     * 
+ * + * string from_date = 4; + * @return The fromDate. + */ + public java.lang.String getFromDate() { + java.lang.Object ref = fromDate_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + fromDate_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+     * Optional. The start date (in string format) to filter events.
+     * 
+ * + * string from_date = 4; + * @return The bytes for fromDate. + */ + public com.google.protobuf.ByteString + getFromDateBytes() { + java.lang.Object ref = fromDate_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + fromDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+     * Optional. The start date (in string format) to filter events.
+     * 
+ * + * string from_date = 4; + * @param value The fromDate to set. + * @return This builder for chaining. + */ + public Builder setFromDate( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + fromDate_ = value; + onChanged(); + return this; + } + /** + *
+     * Optional. The start date (in string format) to filter events.
+     * 
+ * + * string from_date = 4; + * @return This builder for chaining. + */ + public Builder clearFromDate() { + + fromDate_ = getDefaultInstance().getFromDate(); + onChanged(); + return this; + } + /** + *
+     * Optional. The start date (in string format) to filter events.
+     * 
+ * + * string from_date = 4; + * @param value The bytes for fromDate to set. + * @return This builder for chaining. + */ + public Builder setFromDateBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + fromDate_ = value; + onChanged(); + return this; + } + + private java.lang.Object toDate_ = ""; + /** + *
+     * Optional. The end date (in string format) to filter events.
+     * 
+ * + * string to_date = 5; + * @return The toDate. + */ + public java.lang.String getToDate() { + java.lang.Object ref = toDate_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + toDate_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+     * Optional. The end date (in string format) to filter events.
+     * 
+ * + * string to_date = 5; + * @return The bytes for toDate. + */ + public com.google.protobuf.ByteString + getToDateBytes() { + java.lang.Object ref = toDate_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + toDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+     * Optional. The end date (in string format) to filter events.
+     * 
+ * + * string to_date = 5; + * @param value The toDate to set. + * @return This builder for chaining. + */ + public Builder setToDate( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + toDate_ = value; + onChanged(); + return this; + } + /** + *
+     * Optional. The end date (in string format) to filter events.
+     * 
+ * + * string to_date = 5; + * @return This builder for chaining. + */ + public Builder clearToDate() { + + toDate_ = getDefaultInstance().getToDate(); + onChanged(); + return this; + } + /** + *
+     * Optional. The end date (in string format) to filter events.
+     * 
+ * + * string to_date = 5; + * @param value The bytes for toDate to set. + * @return This builder for chaining. + */ + public Builder setToDateBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + toDate_ = value; + onChanged(); + return this; + } + private int limit_ ; /** - * int32 limit = 3; + *
+     * Optional. The maximum number of results to return. If not provided, defaults to 100.
+     * 
+ * + * int32 limit = 6; * @return The limit. */ @java.lang.Override @@ -692,7 +1337,11 @@ public int getLimit() { return limit_; } /** - * int32 limit = 3; + *
+     * Optional. The maximum number of results to return. If not provided, defaults to 100.
+     * 
+ * + * int32 limit = 6; * @param value The limit to set. * @return This builder for chaining. */ @@ -703,7 +1352,11 @@ public Builder setLimit(int value) { return this; } /** - * int32 limit = 3; + *
+     * Optional. The maximum number of results to return. If not provided, defaults to 100.
+     * 
+ * + * int32 limit = 6; * @return This builder for chaining. */ public Builder clearLimit() { diff --git a/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java b/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java index 10ea5778..2d720aae 100644 --- a/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java +++ b/service/src/main/java/io/provlabs/flow/api/NavEventRequestOrBuilder.java @@ -8,11 +8,19 @@ public interface NavEventRequestOrBuilder extends com.google.protobuf.MessageOrBuilder { /** + *
+   * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string denom = 1; * @return The denom. */ java.lang.String getDenom(); /** + *
+   * The token denomination to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string denom = 1; * @return The bytes for denom. */ @@ -20,11 +28,19 @@ public interface NavEventRequestOrBuilder extends getDenomBytes(); /** + *
+   * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string scope_id = 2; * @return The scopeId. */ java.lang.String getScopeId(); /** + *
+   * The scope ID to filter events by. Either `denom` or `scope_id` is required.
+   * 
+ * * string scope_id = 2; * @return The bytes for scopeId. */ @@ -32,7 +48,92 @@ public interface NavEventRequestOrBuilder extends getScopeIdBytes(); /** - * int32 limit = 3; + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @return A list containing the priceDenoms. + */ + java.util.List + getPriceDenomsList(); + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @return The count of priceDenoms. + */ + int getPriceDenomsCount(); + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the element to return. + * @return The priceDenoms at the given index. + */ + java.lang.String getPriceDenoms(int index); + /** + *
+   * Optional. A list of price denominations to filter by.
+   * 
+ * + * repeated string price_denoms = 3; + * @param index The index of the value to return. + * @return The bytes of the priceDenoms at the given index. + */ + com.google.protobuf.ByteString + getPriceDenomsBytes(int index); + + /** + *
+   * Optional. The start date (in string format) to filter events.
+   * 
+ * + * string from_date = 4; + * @return The fromDate. + */ + java.lang.String getFromDate(); + /** + *
+   * Optional. The start date (in string format) to filter events.
+   * 
+ * + * string from_date = 4; + * @return The bytes for fromDate. + */ + com.google.protobuf.ByteString + getFromDateBytes(); + + /** + *
+   * Optional. The end date (in string format) to filter events.
+   * 
+ * + * string to_date = 5; + * @return The toDate. + */ + java.lang.String getToDate(); + /** + *
+   * Optional. The end date (in string format) to filter events.
+   * 
+ * + * string to_date = 5; + * @return The bytes for toDate. + */ + com.google.protobuf.ByteString + getToDateBytes(); + + /** + *
+   * Optional. The maximum number of results to return. If not provided, defaults to 100.
+   * 
+ * + * int32 limit = 6; * @return The limit. */ int getLimit(); diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 17be6233..30910afe 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -58,6 +58,7 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.joda.time.Duration +import org.joda.time.format.DateTimeFormat import org.springframework.stereotype.Service import java.math.BigDecimal import java.math.RoundingMode @@ -259,9 +260,13 @@ class TokenService(private val accountClient: AccountGrpcClient, private val nav } } - fun fetchOnChainNavData(denom: String, limit: Int = 100): List = runBlocking { + fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { + val fromDateString = fromDate?.toString(DateTimeFormat.forPattern("yyyy-MM-dd")) ?: "" val request = NavEventRequest.newBuilder() .setDenom(denom) + .addPriceDenoms("uusd.trading") + .addPriceDenoms("uusdc.figure.se") + .setFromDate(fromDateString) .setLimit(limit) .build() diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 58b2df2a..989c124b 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -14,6 +14,7 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import java.net.URI +import java.util.* class TokenServiceTest { @@ -74,16 +75,26 @@ class TokenServiceTest { } @Test - fun `test fetchOnChainNavData`() { + @Disabled("Test was used to manually call the endpoint") + fun `test fetchOnChainNavData`() { val denom = "nhash" + val fromDate = DateTime.now().minusDays(7) val limit = 100 - val result: List = tokenService.fetchOnChainNavData(denom, limit) + val result: List = tokenService.fetchOnChainNavData(denom, fromDate, limit) + + val groupedByPriceDenom = result.groupBy { it.priceDenom } + + groupedByPriceDenom.forEach { (priceDenom, events) -> + println("PriceDenom: $priceDenom, Count: ${events.size}") + } result.forEach { navEvent -> - println("NavEvent: BlockHeight=${navEvent.blockHeight}, Denom=${navEvent.denom}") + println("NavEvent: BlockHeight=${navEvent.blockHeight}, PriceDenom=${navEvent.priceDenom}") } assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } } + + } From 68a53ccf39e6551584b4f205d9923b49b14040f8 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 17 Sep 2024 10:09:11 -0600 Subject: [PATCH 03/40] add temp function in test --- .../explorer/service/TokenServiceTest.kt | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 989c124b..7dad4bd6 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -75,7 +75,7 @@ class TokenServiceTest { } @Test - @Disabled("Test was used to manually call the endpoint") +// @Disabled("Test was used to manually call the endpoint") fun `test fetchOnChainNavData`() { val denom = "nhash" val fromDate = DateTime.now().minusDays(7) @@ -90,11 +90,28 @@ class TokenServiceTest { } result.forEach { navEvent -> - println("NavEvent: BlockHeight=${navEvent.blockHeight}, PriceDenom=${navEvent.priceDenom}") + val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + println("NavEvent: BlockHeight=${navEvent.blockHeight}, PriceDenom=${navEvent.priceDenom}, Hash Price: ${pricePerHash}") } assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } } + fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { + // 1 hash = 1,000,000,000 nhash + val N_HASH_IN_HASH: Long = 1000000000 + // Convert nhash volume to hash + val volumeHash = volumeNhash.toDouble() / N_HASH_IN_HASH + + // If volume is zero, avoid division by zero + require(volumeHash != 0.0) { "Volume cannot be zero." } + + // Calculate the price of 1 hash + // priceAmountMillis is in millis (e.g., 1234 = $1.234) + val pricePerHash = priceAmountMillis.toDouble() / volumeHash + + // Convert the price back to a dollar amount by dividing by 1000 + return pricePerHash / 1000.0 + } } From 92e78470c366be1bdc7125eab67952039c3a560a Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Fri, 20 Sep 2024 07:36:58 -0600 Subject: [PATCH 04/40] keep test disabled for now --- .../kotlin/io/provenance/explorer/service/TokenServiceTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 7dad4bd6..c6f18c96 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -75,7 +75,7 @@ class TokenServiceTest { } @Test -// @Disabled("Test was used to manually call the endpoint") + @Disabled("Test was used to manually call the endpoint") fun `test fetchOnChainNavData`() { val denom = "nhash" val fromDate = DateTime.now().minusDays(7) @@ -98,12 +98,10 @@ class TokenServiceTest { } fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { - // 1 hash = 1,000,000,000 nhash val N_HASH_IN_HASH: Long = 1000000000 // Convert nhash volume to hash val volumeHash = volumeNhash.toDouble() / N_HASH_IN_HASH - // If volume is zero, avoid division by zero require(volumeHash != 0.0) { "Volume cannot be zero." } // Calculate the price of 1 hash From ddc3206278244a6dac60fe17d2a247fc876312df Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 13:20:30 -0600 Subject: [PATCH 05/40] add calculate price per hash method --- .../explorer/service/TokenService.kt | 20 ++++++++++++++++++ .../explorer/service/TokenServiceTest.kt | 21 +++++++------------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 30910afe..3f1c823f 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -11,8 +11,10 @@ import io.ktor.client.statement.bodyAsText import io.ktor.http.ContentType import io.provenance.explorer.KTOR_CLIENT_JAVA import io.provenance.explorer.VANILLA_MAPPER +import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.config.ExplorerProperties.Companion.PROV_ACC_PREFIX import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN +import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_MULTIPLIER import io.provenance.explorer.domain.core.logger import io.provenance.explorer.domain.entities.AccountRecord import io.provenance.explorer.domain.entities.CacheKeys @@ -370,4 +372,22 @@ class TokenService(private val accountClient: AccountGrpcClient, private val nav } } +/** + * Calculates the price per hash unit based on the total price in USD (expressed as whole numbers + * where 12345 equals $12.345 USD) and the volume in nHash (nano Hash). + * + * @param priceAmount The total price in whole-number USD cents (e.g., 12345 equals $12.345 USD). + * @param volumeNhash The volume of the transaction in nHash (nano Hash). + * 1 Hash = 1,000,000,000 nHash. + * @return The price per hash unit. Returns 0.0 if the volumeNhash is 0 to avoid division by zero. + */ +fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { + if (volumeNhash == 0L) { + return 0.0 + } + val volumeHash = BigDecimal(volumeNhash).divide(UTILITY_TOKEN_BASE_MULTIPLIER, 10, RoundingMode.HALF_UP) + val pricePerHash = BigDecimal(priceAmountMillis).divide(volumeHash, 10, RoundingMode.HALF_UP) + return pricePerHash.divide(BigDecimal(1000), 10, RoundingMode.HALF_UP).toDouble() +} + fun BigDecimal.asPercentOf(divisor: BigDecimal): BigDecimal = this.divide(divisor, 20, RoundingMode.CEILING) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index c6f18c96..bbb79c7c 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -2,6 +2,7 @@ package io.provenance.explorer.service import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder +import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provlabs.flow.api.NavEvent @@ -91,25 +92,19 @@ class TokenServiceTest { result.forEach { navEvent -> val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) - println("NavEvent: BlockHeight=${navEvent.blockHeight}, PriceDenom=${navEvent.priceDenom}, Hash Price: ${pricePerHash}") + println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000, DateTimeZone.getDefault())}, PriceDenom=${navEvent.priceDenom}, Hash Price: ${pricePerHash}") } assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } } - fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { - val N_HASH_IN_HASH: Long = 1000000000 - // Convert nhash volume to hash - val volumeHash = volumeNhash.toDouble() / N_HASH_IN_HASH - require(volumeHash != 0.0) { "Volume cannot be zero." } - - // Calculate the price of 1 hash - // priceAmountMillis is in millis (e.g., 1234 = $1.234) - val pricePerHash = priceAmountMillis.toDouble() / volumeHash + @Test + fun `test calculatePricePerHash with multiple scenarios`() { + var result = calculatePricePerHash(12345L, ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER.toLong()) + assertEquals(12.345, result, "price per hash calculation is incorrect") - // Convert the price back to a dollar amount by dividing by 1000 - return pricePerHash / 1000.0 + result = calculatePricePerHash(12345L, 0L) + assertEquals(0.0, result, "Should return 0.0 when volume is 0") } - } From 73aa5a55171060366f02f95c9f0dff2e75955be1 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 13:21:01 -0600 Subject: [PATCH 06/40] remove unused import --- .../kotlin/io/provenance/explorer/service/TokenServiceTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index bbb79c7c..4e924787 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -15,7 +15,6 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import java.net.URI -import java.util.* class TokenServiceTest { From 7655bf6302d68e2ad3c39885d6caace380efd43e Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 13:50:31 -0600 Subject: [PATCH 07/40] add on-chain nav values for hash price --- ...osisModels.kt => HistoricalPriceModels.kt} | 9 ++++++ .../explorer/service/TokenService.kt | 31 +++++++++++++++++++ .../service/async/ScheduledTaskService.kt | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) rename service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/{OsmosisModels.kt => HistoricalPriceModels.kt} (71%) diff --git a/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/OsmosisModels.kt b/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt similarity index 71% rename from service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/OsmosisModels.kt rename to service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt index 55313a97..2903acc7 100644 --- a/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/OsmosisModels.kt +++ b/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt @@ -2,6 +2,15 @@ package io.provenance.explorer.domain.models import java.math.BigDecimal +data class HistoricalPrice( + val time: Long, + val high: BigDecimal, + val low: BigDecimal, + val close: BigDecimal, + val open: BigDecimal, + val volume: BigDecimal +) + data class OsmosisHistoricalPrice( val time: Long, val high: BigDecimal, diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 3f1c823f..07d2e01a 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -34,6 +34,7 @@ import io.provenance.explorer.domain.extensions.startOfDay import io.provenance.explorer.domain.extensions.toCoinStr import io.provenance.explorer.domain.extensions.toOffset import io.provenance.explorer.domain.extensions.toPercentage +import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.OsmosisApiResponse import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.domain.models.explorer.TokenHistoricalDataRequest @@ -239,6 +240,36 @@ class TokenService(private val accountClient: AccountGrpcClient, private val nav VANILLA_MAPPER.readValue(it) } + fun fetchHistoricalPriceData(fromDate: DateTime?): List = runBlocking { + val osmosisHistoricalPrices = fetchOsmosisData(fromDate) + val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) + + val osmosisPrices = osmosisHistoricalPrices.map { osmosisPrice -> + HistoricalPrice( + time = osmosisPrice.time, + high = osmosisPrice.high, + low = osmosisPrice.low, + close = osmosisPrice.close, + open = osmosisPrice.open, + volume = osmosisPrice.volume + ) + } + + val navPrices = onChainNavEvents.map { navEvent -> + val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + HistoricalPrice( + time = navEvent.blockTime, + high = BigDecimal(pricePerHash), + low = BigDecimal(pricePerHash), + close = BigDecimal(pricePerHash), + open = BigDecimal(pricePerHash), + volume = BigDecimal(navEvent.volume) + ) + } + + return@runBlocking osmosisPrices + navPrices + } + fun fetchOsmosisData(fromDate: DateTime?): List = runBlocking { val input = buildInputQuery(fromDate, determineTimeFrame(fromDate)) try { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index f84f1a36..2c11a496 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -360,7 +360,7 @@ class ScheduledTaskService( fun updateTokenLatest() { val today = DateTime.now().withZone(DateTimeZone.UTC) val startDate = today.minusDays(7) - tokenService.fetchOsmosisData(startDate) + tokenService.fetchHistoricalPriceData(startDate) ?.sortedBy { it.time } ?.let { list -> val prevRecIdx = list.indexOfLast { DateTime(it.time * 1000).isBefore(today.minusDays(1)) } From df9811b392bada6ab8c326e597d21bfbe27a5a70 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 13:59:42 -0600 Subject: [PATCH 08/40] fix lints --- .../kotlin/io/provenance/explorer/service/TokenService.kt | 1 - .../io/provenance/explorer/service/TokenServiceTest.kt | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 07d2e01a..1797efa9 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -11,7 +11,6 @@ import io.ktor.client.statement.bodyAsText import io.ktor.http.ContentType import io.provenance.explorer.KTOR_CLIENT_JAVA import io.provenance.explorer.VANILLA_MAPPER -import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.config.ExplorerProperties.Companion.PROV_ACC_PREFIX import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_MULTIPLIER diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 4e924787..76c304f1 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -91,19 +91,18 @@ class TokenServiceTest { result.forEach { navEvent -> val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) - println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000, DateTimeZone.getDefault())}, PriceDenom=${navEvent.priceDenom}, Hash Price: ${pricePerHash}") + println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000, DateTimeZone.getDefault())}, PriceDenom=${navEvent.priceDenom}, Hash Price: $pricePerHash") } assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } } - @Test fun `test calculatePricePerHash with multiple scenarios`() { var result = calculatePricePerHash(12345L, ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER.toLong()) assertEquals(12.345, result, "price per hash calculation is incorrect") - result = calculatePricePerHash(12345L, 0L) + result = calculatePricePerHash(12345L, 0L) assertEquals(0.0, result, "Should return 0.0 when volume is 0") } } From dd8de47883bd1d701a804bbe29b43ffd834310dd Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 15:01:24 -0600 Subject: [PATCH 09/40] simplify update token latest job --- .../service/async/ScheduledTaskService.kt | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index 2c11a496..f0d315d1 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -359,23 +359,14 @@ class ScheduledTaskService( @Scheduled(cron = "0 0/5 * * * ?") // Every 5 minutes fun updateTokenLatest() { val today = DateTime.now().withZone(DateTimeZone.UTC) - val startDate = today.minusDays(7) + val startDate = today.minusDays(1) tokenService.fetchHistoricalPriceData(startDate) ?.sortedBy { it.time } ?.let { list -> - val prevRecIdx = list.indexOfLast { DateTime(it.time * 1000).isBefore(today.minusDays(1)) } - val prevRecord = list[prevRecIdx] + val prevRecord = list.firstOrNull() ?: return val price = list.last().close.toThirdDecimal() - val percentChg = if (prevRecIdx == list.lastIndex) { - BigDecimal.ZERO - } else { - price.percentChange(prevRecord.close.toThirdDecimal()) - } - val vol24Hr = if (prevRecIdx == list.lastIndex) { - BigDecimal.ZERO - } else { - list.subList(prevRecIdx + 1, list.lastIndex + 1).sumOf { it.volume.toThirdDecimal() }.stripTrailingZeros() - } + val percentChg = price.percentChange(prevRecord.close.toThirdDecimal()) + val vol24Hr = list.sumOf { it.volume.toThirdDecimal() }.stripTrailingZeros() val marketCap = price.multiply(tokenService.totalSupply().divide(UTILITY_TOKEN_BASE_MULTIPLIER)).toThirdDecimal() val rec = CmcLatestDataAbbrev( today, From 01743a68af977aad76051a66ce242aaa271df20f Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 24 Sep 2024 16:28:30 -0600 Subject: [PATCH 10/40] add configurations for flow api --- .../explorer/config/ExplorerProperties.kt | 1 + .../config/FlowApiGrpcClientConfig.kt | 16 ++++++ .../explorer/grpc/flow/FlowApiGrpcClient.kt | 57 +++++++++++++++++++ .../explorer/service/TokenService.kt | 21 ++----- .../application-development.properties | 1 + .../explorer/service/TokenServiceTest.kt | 10 +--- 6 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt create mode 100644 service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt diff --git a/service/src/main/kotlin/io/provenance/explorer/config/ExplorerProperties.kt b/service/src/main/kotlin/io/provenance/explorer/config/ExplorerProperties.kt index 27eff1aa..dd4af046 100644 --- a/service/src/main/kotlin/io/provenance/explorer/config/ExplorerProperties.kt +++ b/service/src/main/kotlin/io/provenance/explorer/config/ExplorerProperties.kt @@ -13,6 +13,7 @@ import java.math.BigDecimal class ExplorerProperties( val mainnet: String, val pbUrl: String, + val flowApiUrl: String, val initialHistoricalDayCount: String, val spotlightTtlMs: String, val genesisVersionUrl: String, diff --git a/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt b/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt new file mode 100644 index 00000000..12a0dfb5 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt @@ -0,0 +1,16 @@ +package io.provenance.explorer.config + +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import java.net.URI + +@EnableConfigurationProperties( + value = [ExplorerProperties::class] +) +@Configuration +class FlowApiGrpcClientConfig(val props: ExplorerProperties) { + + @Bean + fun flowApiChannelUri() = URI(props.flowApiUrl) +} \ No newline at end of file diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt new file mode 100644 index 00000000..7594323e --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -0,0 +1,57 @@ +package io.provenance.explorer.grpc.flow + +import io.grpc.ManagedChannelBuilder +import io.provenance.attribute.v1.QueryGrpcKt +import io.provenance.explorer.config.interceptor.GrpcLoggingInterceptor +import io.provenance.explorer.domain.core.logger +import io.provlabs.flow.api.NavEvent +import io.provlabs.flow.api.NavEventRequest +import io.provlabs.flow.api.NavEventResponse +import io.provlabs.flow.api.NavServiceGrpc +import kotlinx.coroutines.runBlocking +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import java.net.URI +import java.util.concurrent.TimeUnit + +class FlowApiGrpcClient(flowApiChannelUri: URI) { + + private val navService: NavServiceGrpc.NavServiceBlockingStub + + init { + val channel = + ManagedChannelBuilder.forAddress(flowApiChannelUri.host, flowApiChannelUri.port) + .also { + if (flowApiChannelUri.scheme == "grpcs") { + it.useTransportSecurity() + } else { + it.usePlaintext() + } + } + .idleTimeout(60, TimeUnit.SECONDS) + .keepAliveTime(10, TimeUnit.SECONDS) + .keepAliveTimeout(10, TimeUnit.SECONDS) + .intercept(GrpcLoggingInterceptor()) + .build() + + navService = NavServiceGrpc.newBlockingStub(channel) + } + + fun getMarkerNavByPriceDenoms(denom: String, priceDenoms: List, fromDate: DateTime?, limit: Int = 100): List = runBlocking { + val fromDateString = fromDate?.toString(DateTimeFormat.forPattern("yyyy-MM-dd")) ?: "" + val requestBuilder = NavEventRequest.newBuilder() + .setDenom(denom) + .setFromDate(fromDateString) + .setLimit(limit) + + priceDenoms.forEach { requestBuilder.addPriceDenoms(it) } + + try { + val response: NavEventResponse = navService.getNavEvents(requestBuilder.build()) + return@runBlocking response.navEventsList + } catch (e: Exception) { + logger().error("Error fetching Nav Events: ${e.message}", e) + emptyList() + } + } +} \ No newline at end of file diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 1797efa9..58280454 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -37,6 +37,7 @@ import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.OsmosisApiResponse import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.domain.models.explorer.TokenHistoricalDataRequest +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provenance.explorer.model.AssetHolder import io.provenance.explorer.model.CmcLatestDataAbbrev @@ -70,7 +71,7 @@ import java.util.zip.ZipOutputStream import javax.servlet.ServletOutputStream @Service -class TokenService(private val accountClient: AccountGrpcClient, private val navService: NavServiceGrpc.NavServiceBlockingStub) { +class TokenService(private val accountClient: AccountGrpcClient, private val flowApiGrpcClient: FlowApiGrpcClient) { protected val logger = logger(TokenService::class) @@ -293,22 +294,8 @@ class TokenService(private val accountClient: AccountGrpcClient, private val nav } fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { - val fromDateString = fromDate?.toString(DateTimeFormat.forPattern("yyyy-MM-dd")) ?: "" - val request = NavEventRequest.newBuilder() - .setDenom(denom) - .addPriceDenoms("uusd.trading") - .addPriceDenoms("uusdc.figure.se") - .setFromDate(fromDateString) - .setLimit(limit) - .build() - - try { - val response: NavEventResponse = navService.getNavEvents(request) - return@runBlocking response.navEventsList - } catch (e: Exception) { - logger.error("Error fetching Nav Events: ${e.message}", e) - emptyList() - } + val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") + flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) } enum class TimeFrame(val minutes: Int) { diff --git a/service/src/main/resources/application-development.properties b/service/src/main/resources/application-development.properties index 53ce166b..edddb6d3 100644 --- a/service/src/main/resources/application-development.properties +++ b/service/src/main/resources/application-development.properties @@ -7,6 +7,7 @@ spring.datasource.hikari.schema=explorer spring.datasource.hikari.maximum-pool-size=40 #explorer.pb-url=http://localhost:9090 +explorer.flow-api-url=grpcs://localhost:50051 explorer.initial-historical-day-count=14 explorer.spotlight-ttl-ms=5000 explorer.upgrade-version-regex=(v[0-9]+.[0-9]+.[0-9]+[-\\w\\d]*) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 76c304f1..1e4e6d25 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -4,6 +4,7 @@ import io.grpc.ManagedChannel import io.grpc.ManagedChannelBuilder import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.domain.models.OsmosisHistoricalPrice +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provlabs.flow.api.NavEvent import io.provlabs.flow.api.NavServiceGrpc @@ -20,18 +21,11 @@ class TokenServiceTest { private lateinit var accountClient: AccountGrpcClient private lateinit var tokenService: TokenService - private lateinit var channel: ManagedChannel - private lateinit var navServiceStub: NavServiceGrpc.NavServiceBlockingStub @BeforeEach fun setUp() { accountClient = AccountGrpcClient(URI("https://www.google.com")) - channel = ManagedChannelBuilder.forAddress("localhost", 50051) - .usePlaintext() - .build() - - navServiceStub = NavServiceGrpc.newBlockingStub(channel) - tokenService = TokenService(accountClient, navServiceStub) + tokenService = TokenService(accountClient, FlowApiGrpcClient(URI("http://localhost:50051"))) } @Test From 34c7ae830a3fb10657d8c71c52ca9e1723d9bb1f Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 25 Sep 2024 08:13:21 -0600 Subject: [PATCH 11/40] add flow-api-url config property to resources --- service/src/main/resources/application-container.properties | 1 + service/src/main/resources/application-development.properties | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/service/src/main/resources/application-container.properties b/service/src/main/resources/application-container.properties index fa6c85e7..83d77da5 100644 --- a/service/src/main/resources/application-container.properties +++ b/service/src/main/resources/application-container.properties @@ -10,6 +10,7 @@ explorer.spotlight-ttl-ms=${SPOTLIGHT_TTL_MS} explorer.initial-historical-day-count=${INITIAL_HIST_DAY_COUNT} explorer.mainnet=${EXPLORER_MAINNET} explorer.pb-url=${EXPLORER_PB_URL} +explorer.flow-api-url=${EXPLORER_FLOW_API_URL} explorer.genesis-version-url=${EXPLORER_GENESIS_VERSION_URL} explorer.upgrade-version-regex=${EXPLORER_UPGRADE_VERSION_REGEX} explorer.upgrade-github-repo=${EXPLORER_UPGRADE_GITHUB_REPO} diff --git a/service/src/main/resources/application-development.properties b/service/src/main/resources/application-development.properties index edddb6d3..993079bd 100644 --- a/service/src/main/resources/application-development.properties +++ b/service/src/main/resources/application-development.properties @@ -7,7 +7,7 @@ spring.datasource.hikari.schema=explorer spring.datasource.hikari.maximum-pool-size=40 #explorer.pb-url=http://localhost:9090 -explorer.flow-api-url=grpcs://localhost:50051 +explorer.flow-api-url=http://localhost:50051 explorer.initial-historical-day-count=14 explorer.spotlight-ttl-ms=5000 explorer.upgrade-version-regex=(v[0-9]+.[0-9]+.[0-9]+[-\\w\\d]*) From c9626040e301f6d33e7f02cc543701314dfb32f9 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 25 Sep 2024 12:16:23 -0600 Subject: [PATCH 12/40] fix lints --- .../io/provenance/explorer/config/FlowApiGrpcClientConfig.kt | 2 +- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 1 - .../kotlin/io/provenance/explorer/service/TokenService.kt | 4 ---- .../kotlin/io/provenance/explorer/service/TokenServiceTest.kt | 3 --- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt b/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt index 12a0dfb5..9242903f 100644 --- a/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt +++ b/service/src/main/kotlin/io/provenance/explorer/config/FlowApiGrpcClientConfig.kt @@ -13,4 +13,4 @@ class FlowApiGrpcClientConfig(val props: ExplorerProperties) { @Bean fun flowApiChannelUri() = URI(props.flowApiUrl) -} \ No newline at end of file +} diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index 7594323e..34ab1293 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -1,7 +1,6 @@ package io.provenance.explorer.grpc.flow import io.grpc.ManagedChannelBuilder -import io.provenance.attribute.v1.QueryGrpcKt import io.provenance.explorer.config.interceptor.GrpcLoggingInterceptor import io.provenance.explorer.domain.core.logger import io.provlabs.flow.api.NavEvent diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 58280454..ecbb1284 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -49,9 +49,6 @@ import io.provenance.explorer.model.base.CoinStr import io.provenance.explorer.model.base.CountStrTotal import io.provenance.explorer.model.base.PagedResults import io.provlabs.flow.api.NavEvent -import io.provlabs.flow.api.NavEventRequest -import io.provlabs.flow.api.NavEventResponse -import io.provlabs.flow.api.NavServiceGrpc import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map @@ -61,7 +58,6 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.joda.time.Duration -import org.joda.time.format.DateTimeFormat import org.springframework.stereotype.Service import java.math.BigDecimal import java.math.RoundingMode diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 1e4e6d25..0717df2d 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -1,13 +1,10 @@ package io.provenance.explorer.service -import io.grpc.ManagedChannel -import io.grpc.ManagedChannelBuilder import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provlabs.flow.api.NavEvent -import io.provlabs.flow.api.NavServiceGrpc import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import org.joda.time.DateTimeZone From cf3f6deb936a7dd7f8cb88f1fc5dfb55edf1822f Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 25 Sep 2024 12:19:31 -0600 Subject: [PATCH 13/40] make temp logging statements --- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 2 ++ .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index 34ab1293..2f1877f9 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -18,6 +18,8 @@ class FlowApiGrpcClient(flowApiChannelUri: URI) { private val navService: NavServiceGrpc.NavServiceBlockingStub init { + // TODO: remove before merging PR + logger().info("initializing flow api service: ${flowApiChannelUri.host} : ${flowApiChannelUri.port}") val channel = ManagedChannelBuilder.forAddress(flowApiChannelUri.host, flowApiChannelUri.port) .also { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index ecbb1284..4685d286 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -291,6 +291,8 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") + // TODO: remove or make debug before merge to main + logger.info("fetching on chain prices for $denom, $priceDenoms, $fromDate, $limit") flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) } From fcf0e112693e1bc2435b48ae018c697d619a2587 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 25 Sep 2024 12:24:10 -0600 Subject: [PATCH 14/40] end file with endline --- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index 2f1877f9..22e41558 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -55,4 +55,4 @@ class FlowApiGrpcClient(flowApiChannelUri: URI) { emptyList() } } -} \ No newline at end of file +} From e44bbc158004a606545287a45994c6cef90c57bb Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Wed, 25 Sep 2024 12:40:18 -0600 Subject: [PATCH 15/40] add component annotation to grpc client --- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index 22e41558..916c30ea 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -10,9 +10,11 @@ import io.provlabs.flow.api.NavServiceGrpc import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat +import org.springframework.stereotype.Component import java.net.URI import java.util.concurrent.TimeUnit +@Component class FlowApiGrpcClient(flowApiChannelUri: URI) { private val navService: NavServiceGrpc.NavServiceBlockingStub From 4541db677fc4267a35eba7fecf6e9346de0f715b Mon Sep 17 00:00:00 2001 From: Carlton Hanna Date: Wed, 25 Sep 2024 13:26:00 -0600 Subject: [PATCH 16/40] add some temp logs --- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 5 +++-- .../kotlin/io/provenance/explorer/service/TokenService.kt | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index 916c30ea..b6b62ec4 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -48,9 +48,10 @@ class FlowApiGrpcClient(flowApiChannelUri: URI) { .setLimit(limit) priceDenoms.forEach { requestBuilder.addPriceDenoms(it) } - + val request = requestBuilder.build() try { - val response: NavEventResponse = navService.getNavEvents(requestBuilder.build()) + logger().info("getMarkerNavByPriceDenoms $request") + val response: NavEventResponse = navService.getNavEvents(request) return@runBlocking response.navEventsList } catch (e: Exception) { logger().error("Error fetching Nav Events: ${e.message}", e) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 4685d286..315391c8 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -237,6 +237,7 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo } fun fetchHistoricalPriceData(fromDate: DateTime?): List = runBlocking { + logger.info("fetchHistoricalPriceData fromDate: $fromDate") val osmosisHistoricalPrices = fetchOsmosisData(fromDate) val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) From 0f040dde85c6f6b0609522b5f75a2290b5bb0b81 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Thu, 26 Sep 2024 07:48:17 -0600 Subject: [PATCH 17/40] add temp logging --- .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 315391c8..4e8adff5 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -263,7 +263,8 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo volume = BigDecimal(navEvent.volume) ) } - + // TODO: remove log before merge to main + logger.info("historical price totals nav: ${navPrices.size} osmosis: ${osmosisPrices.size} ") return@runBlocking osmosisPrices + navPrices } From 5644b3c2858c494a7be3ccc9dab57a964174e93d Mon Sep 17 00:00:00 2001 From: Carlton Hanna Date: Thu, 26 Sep 2024 09:54:15 -0600 Subject: [PATCH 18/40] remove logging --- .../io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt | 2 -- .../kotlin/io/provenance/explorer/service/TokenService.kt | 5 ----- 2 files changed, 7 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt index b6b62ec4..1e83a69d 100644 --- a/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt +++ b/service/src/main/kotlin/io/provenance/explorer/grpc/flow/FlowApiGrpcClient.kt @@ -20,8 +20,6 @@ class FlowApiGrpcClient(flowApiChannelUri: URI) { private val navService: NavServiceGrpc.NavServiceBlockingStub init { - // TODO: remove before merging PR - logger().info("initializing flow api service: ${flowApiChannelUri.host} : ${flowApiChannelUri.port}") val channel = ManagedChannelBuilder.forAddress(flowApiChannelUri.host, flowApiChannelUri.port) .also { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 4e8adff5..210fbf01 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -237,7 +237,6 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo } fun fetchHistoricalPriceData(fromDate: DateTime?): List = runBlocking { - logger.info("fetchHistoricalPriceData fromDate: $fromDate") val osmosisHistoricalPrices = fetchOsmosisData(fromDate) val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) @@ -263,8 +262,6 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo volume = BigDecimal(navEvent.volume) ) } - // TODO: remove log before merge to main - logger.info("historical price totals nav: ${navPrices.size} osmosis: ${osmosisPrices.size} ") return@runBlocking osmosisPrices + navPrices } @@ -293,8 +290,6 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") - // TODO: remove or make debug before merge to main - logger.info("fetching on chain prices for $denom, $priceDenoms, $fromDate, $limit") flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) } From 1c1cc310e5f40a4dc6b4f591e861192f55e90037 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Thu, 26 Sep 2024 13:53:30 -0600 Subject: [PATCH 19/40] convert nhash volume to hash volume --- .../io/provenance/explorer/service/TokenService.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 210fbf01..55534adf 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -252,6 +252,7 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo } val navPrices = onChainNavEvents.map { navEvent -> + val volumeHash = calculateVolumeHash(navEvent.volume) val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) HistoricalPrice( time = navEvent.blockTime, @@ -259,7 +260,7 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo low = BigDecimal(pricePerHash), close = BigDecimal(pricePerHash), open = BigDecimal(pricePerHash), - volume = BigDecimal(navEvent.volume) + volume = volumeHash ) } return@runBlocking osmosisPrices + navPrices @@ -394,12 +395,19 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo * @return The price per hash unit. Returns 0.0 if the volumeNhash is 0 to avoid division by zero. */ fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { - if (volumeNhash == 0L) { + val volumeHash = calculateVolumeHash(volumeNhash) + if (volumeHash == BigDecimal.ZERO) { return 0.0 } - val volumeHash = BigDecimal(volumeNhash).divide(UTILITY_TOKEN_BASE_MULTIPLIER, 10, RoundingMode.HALF_UP) val pricePerHash = BigDecimal(priceAmountMillis).divide(volumeHash, 10, RoundingMode.HALF_UP) return pricePerHash.divide(BigDecimal(1000), 10, RoundingMode.HALF_UP).toDouble() } +fun calculateVolumeHash(volumeNhash: Long): BigDecimal { + if (volumeNhash == 0L) { + return BigDecimal.ZERO + } + return BigDecimal(volumeNhash).divide(UTILITY_TOKEN_BASE_MULTIPLIER, 10, RoundingMode.HALF_UP) +} + fun BigDecimal.asPercentOf(divisor: BigDecimal): BigDecimal = this.divide(divisor, 20, RoundingMode.CEILING) From f963c6892e2d59bce0da396779b9e2a868d5c7c1 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Thu, 26 Sep 2024 14:00:14 -0600 Subject: [PATCH 20/40] add a temp log --- .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 55534adf..cecedb03 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -263,6 +263,7 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo volume = volumeHash ) } + logger.info("fetchHistoricalPriceData navs ${navPrices.size} osmosis ${osmosisPrices.size}") return@runBlocking osmosisPrices + navPrices } From ea8aba0456bc3bf25a421a0c2b04f79cdc744ca5 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Thu, 26 Sep 2024 14:15:25 -0600 Subject: [PATCH 21/40] fix volume amount to hash volume multiplied by hash price --- .../kotlin/io/provenance/explorer/service/TokenService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index cecedb03..3bbb3ada 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -260,10 +260,10 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo low = BigDecimal(pricePerHash), close = BigDecimal(pricePerHash), open = BigDecimal(pricePerHash), - volume = volumeHash + volume = BigDecimal(pricePerHash).multiply(volumeHash) ) } - logger.info("fetchHistoricalPriceData navs ${navPrices.size} osmosis ${osmosisPrices.size}") + logger.info("fetchHistoricalPriceData navs ${navPrices.size} ${navPrices.sumOf { it.volume }} osmosis ${osmosisPrices.size} ${osmosisPrices.sumOf { it.volume }}") return@runBlocking osmosisPrices + navPrices } From e943f3a86b410abc1d7739e1b7e2605fd5a5ff12 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Fri, 27 Sep 2024 08:12:48 -0600 Subject: [PATCH 22/40] add price fetcher strategy pattern --- .../pricing/fetchers/FlowApiPriceFetcher.kt | 62 ++++++++++ .../fetchers/HistoricalPriceFetcher.kt | 8 ++ .../pricing/fetchers/OsmosisPriceFetcher.kt | 110 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt create mode 100644 service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcher.kt create mode 100644 service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt new file mode 100644 index 00000000..74930edb --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -0,0 +1,62 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.config.ExplorerProperties +import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN +import io.provenance.explorer.domain.models.HistoricalPrice +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient +import io.provlabs.flow.api.NavEvent +import kotlinx.coroutines.runBlocking +import org.joda.time.DateTime +import java.math.BigDecimal +import java.math.RoundingMode + +class OnChainNavPriceFetcher( + private val flowApiGrpcClient: FlowApiGrpcClient +) : HistoricalPriceFetcher { + + override fun fetchHistoricalPrice(fromDate: DateTime?): List { + val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) + return onChainNavEvents.map { navEvent -> + val volumeHash = calculateVolumeHash(navEvent.volume) + val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + HistoricalPrice( + time = navEvent.blockTime, + high = BigDecimal(pricePerHash), + low = BigDecimal(pricePerHash), + close = BigDecimal(pricePerHash), + open = BigDecimal(pricePerHash), + volume = BigDecimal(pricePerHash).multiply(volumeHash) + ) + } + } + + fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { + val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") + flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) + } + + fun calculateVolumeHash(volumeNhash: Long): BigDecimal { + if (volumeNhash == 0L) { + return BigDecimal.ZERO + } + return BigDecimal(volumeNhash).divide(ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER, 10, RoundingMode.HALF_UP) + } + + /** + * Calculates the price per hash unit based on the total price in USD (expressed as whole numbers + * where 12345 equals $12.345 USD) and the volume in nHash (nano Hash). + * + * @param priceAmount The total price in whole-number USD cents (e.g., 12345 equals $12.345 USD). + * @param volumeNhash The volume of the transaction in nHash (nano Hash). + * 1 Hash = 1,000,000,000 nHash. + * @return The price per hash unit. Returns 0.0 if the volumeNhash is 0 to avoid division by zero. + */ + fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { + val volumeHash = io.provenance.explorer.service.calculateVolumeHash(volumeNhash) + if (volumeHash == BigDecimal.ZERO) { + return 0.0 + } + val pricePerHash = BigDecimal(priceAmountMillis).divide(volumeHash, 10, RoundingMode.HALF_UP) + return pricePerHash.divide(BigDecimal(1000), 10, RoundingMode.HALF_UP).toDouble() + } +} diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcher.kt new file mode 100644 index 00000000..76ef7f47 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcher.kt @@ -0,0 +1,8 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.domain.models.HistoricalPrice +import org.joda.time.DateTime + +interface HistoricalPriceFetcher { + fun fetchHistoricalPrice(fromDate: DateTime?): List +} diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt new file mode 100644 index 00000000..69b51ad2 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt @@ -0,0 +1,110 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.ktor.client.call.* +import io.ktor.client.plugins.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import io.provenance.explorer.KTOR_CLIENT_JAVA +import io.provenance.explorer.domain.core.logger +import io.provenance.explorer.domain.models.HistoricalPrice +import io.provenance.explorer.domain.models.OsmosisApiResponse +import io.provenance.explorer.domain.models.OsmosisHistoricalPrice +import io.provenance.explorer.service.TokenService +import kotlinx.coroutines.runBlocking +import org.joda.time.DateTime +import org.joda.time.DateTimeZone +import org.joda.time.Duration +import java.net.URLEncoder + +class OsmosisPriceFetcher : HistoricalPriceFetcher { + + protected val logger = logger(OsmosisPriceFetcher::class) + override fun fetchHistoricalPrice(fromDate: DateTime?): List { + val osmosisHistoricalPrices = fetchOsmosisData(fromDate) + return osmosisHistoricalPrices.map { osmosisPrice -> + HistoricalPrice( + time = osmosisPrice.time, + high = osmosisPrice.high, + low = osmosisPrice.low, + close = osmosisPrice.close, + open = osmosisPrice.open, + volume = osmosisPrice.volume + ) + } + } + + fun fetchOsmosisData(fromDate: DateTime?): List = runBlocking { + val input = buildInputQuery(fromDate, determineTimeFrame(fromDate)) + try { + val url = """https://app.osmosis.zone/api/edge-trpc-assets/assets.getAssetHistoricalPrice?input=$input""" + logger.info("Calling $url with fromDate $fromDate") + val response: HttpResponse = KTOR_CLIENT_JAVA.get(url) { + accept(ContentType.Application.Json) + } + + val rawResponse: String = response.bodyAsText() + logger.debug("Osmosis GET: $url Raw Response: $rawResponse") + + val osmosisApiResponse: OsmosisApiResponse = response.body() + osmosisApiResponse.result.data.json + } catch (e: ResponseException) { + logger.error("Error fetching from Osmosis API: ${e.response}", e) + emptyList() + } catch (e: Exception) { + logger.error("Error fetching from Osmosis API: ${e.message}", e) + emptyList() + } + } + + enum class TimeFrame(val minutes: Int) { + FIVE_MINUTES(5), + TWO_HOURS(120), + ONE_DAY(1440) + } + + /** + * Determines the appropriate TimeFrame based on the fromDate. + * + * @param fromDate The starting date to determine the time frame. + * @return The appropriate TimeFrame enum value. + */ + fun determineTimeFrame(fromDate: DateTime?): TimeFrame { + val now = DateTime.now(DateTimeZone.UTC) + val duration = Duration(fromDate, now) + return when { + duration.standardDays <= 14 -> TimeFrame.FIVE_MINUTES + duration.standardDays <= 60 -> TimeFrame.TWO_HOURS + else -> TimeFrame.ONE_DAY + } + } + + /** + * Builds the input query parameter for fetching historical data. + * + * This function constructs a URL-encoded JSON query parameter for fetching historical data based on the given + * `fromDate` and `timeFrame`. The `timeFrame` represents the number of minutes between updates. The allowed values + * for `timeFrame` are defined in the `TimeFrame` enum: + * - FIVE_MINUTES: data goes back 2 weeks. + * - TWO_HOURS: data goes back 2 months. + * - ONE_DAY: data goes back to the beginning of time. + * + * The function calculates the total number of frames (`numRecentFrames`) from the `fromDate` to the current time, + * based on the specified `timeFrame`. + * + * @param fromDate The starting date from which to calculate the number of frames. + * @param timeFrame The time interval between updates, specified as a `TimeFrame` enum value. + * @return A URL-encoded JSON string to be used as a query parameter for fetching historical data. + */ + fun buildInputQuery(fromDate: DateTime?, timeFrame: TimeFrame): String { + val coinDenom = "ibc/CE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2" + val coinMinimalDenom = "ibc/CE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2" + val now = DateTime.now(DateTimeZone.UTC) + val duration = Duration(fromDate, now) + val numRecentFrames = (duration.standardMinutes / timeFrame.minutes).toInt() + return URLEncoder.encode( + """{"json":{"coinDenom":"$coinDenom","coinMinimalDenom":"$coinMinimalDenom","timeFrame":{"custom":{"timeFrame":${timeFrame.minutes},"numRecentFrames":$numRecentFrames}}}}""", + "UTF-8" + ) + } +} From 17eb18d1c8adf7013745e84f1e1355af5292256d Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 13:54:30 -0600 Subject: [PATCH 23/40] finish setting up fetcher pattern wiring --- .../explorer/service/TokenService.kt | 40 ++++++------------- .../pricing/fetchers/FetcherConfiguration.kt | 14 +++++++ .../pricing/fetchers/FlowApiPriceFetcher.kt | 11 ++--- .../fetchers/HistoricalPriceFetcherFactory.kt | 15 +++++++ 4 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FetcherConfiguration.kt create mode 100644 service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 3bbb3ada..306bd26d 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -48,6 +48,8 @@ import io.provenance.explorer.model.TokenSupply import io.provenance.explorer.model.base.CoinStr import io.provenance.explorer.model.base.CountStrTotal import io.provenance.explorer.model.base.PagedResults +import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcher +import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcherFactory import io.provlabs.flow.api.NavEvent import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collect @@ -67,10 +69,16 @@ import java.util.zip.ZipOutputStream import javax.servlet.ServletOutputStream @Service -class TokenService(private val accountClient: AccountGrpcClient, private val flowApiGrpcClient: FlowApiGrpcClient) { +class TokenService(private val accountClient: AccountGrpcClient, + private val flowApiGrpcClient: FlowApiGrpcClient, + private val historicalPriceFetcherFactory: HistoricalPriceFetcherFactory +) { protected val logger = logger(TokenService::class) + private val historicalPriceFetchers: List by lazy { + historicalPriceFetcherFactory.createNhashFetchers() + } fun getTokenDistributionStats() = transaction { TokenDistributionAmountsRecord.getStats() } fun saveResults(records: List) = runBlocking { @@ -237,34 +245,12 @@ class TokenService(private val accountClient: AccountGrpcClient, private val flo } fun fetchHistoricalPriceData(fromDate: DateTime?): List = runBlocking { - val osmosisHistoricalPrices = fetchOsmosisData(fromDate) - val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) - - val osmosisPrices = osmosisHistoricalPrices.map { osmosisPrice -> - HistoricalPrice( - time = osmosisPrice.time, - high = osmosisPrice.high, - low = osmosisPrice.low, - close = osmosisPrice.close, - open = osmosisPrice.open, - volume = osmosisPrice.volume - ) - } + val fetchers = historicalPriceFetcherFactory.createNhashFetchers() - val navPrices = onChainNavEvents.map { navEvent -> - val volumeHash = calculateVolumeHash(navEvent.volume) - val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) - HistoricalPrice( - time = navEvent.blockTime, - high = BigDecimal(pricePerHash), - low = BigDecimal(pricePerHash), - close = BigDecimal(pricePerHash), - open = BigDecimal(pricePerHash), - volume = BigDecimal(pricePerHash).multiply(volumeHash) - ) + val allPrices = fetchers.flatMap { fetcher -> + fetcher.fetchHistoricalPrice(fromDate) } - logger.info("fetchHistoricalPriceData navs ${navPrices.size} ${navPrices.sumOf { it.volume }} osmosis ${osmosisPrices.size} ${osmosisPrices.sumOf { it.volume }}") - return@runBlocking osmosisPrices + navPrices + return@runBlocking allPrices } fun fetchOsmosisData(fromDate: DateTime?): List = runBlocking { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FetcherConfiguration.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FetcherConfiguration.kt new file mode 100644 index 00000000..9f7d47c4 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FetcherConfiguration.kt @@ -0,0 +1,14 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class FetcherConfiguration { + + @Bean + fun historicalPriceFetcherFactory(flowApiGrpcClient: FlowApiGrpcClient): HistoricalPriceFetcherFactory { + return HistoricalPriceFetcherFactory(flowApiGrpcClient) + } +} diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index 74930edb..a6409819 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -10,12 +10,14 @@ import org.joda.time.DateTime import java.math.BigDecimal import java.math.RoundingMode -class OnChainNavPriceFetcher( +class FlowApiPriceFetcher( + private val denom: String, + private val pricingDenoms: List, private val flowApiGrpcClient: FlowApiGrpcClient ) : HistoricalPriceFetcher { override fun fetchHistoricalPrice(fromDate: DateTime?): List { - val onChainNavEvents = fetchOnChainNavData(UTILITY_TOKEN, fromDate, 17800) + val onChainNavEvents = flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, pricingDenoms, fromDate, 17800) return onChainNavEvents.map { navEvent -> val volumeHash = calculateVolumeHash(navEvent.volume) val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) @@ -30,11 +32,6 @@ class OnChainNavPriceFetcher( } } - fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { - val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") - flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) - } - fun calculateVolumeHash(volumeNhash: Long): BigDecimal { if (volumeNhash == 0L) { return BigDecimal.ZERO diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt new file mode 100644 index 00000000..e886ece8 --- /dev/null +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt @@ -0,0 +1,15 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient + +class HistoricalPriceFetcherFactory( + private val flowApiGrpcClient: FlowApiGrpcClient +) { + fun createNhashFetchers(): List { + return listOf( + OsmosisPriceFetcher(), + FlowApiPriceFetcher(UTILITY_TOKEN, listOf("uusd.trading", "uusdc.figure.se"), flowApiGrpcClient) + ) + } +} From f5d411d3c9238b0b0c77d5ac685054b410127b4a Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 14:02:34 -0600 Subject: [PATCH 24/40] fix lints --- .../io/provenance/explorer/service/TokenService.kt | 10 +++++----- .../service/pricing/fetchers/FlowApiPriceFetcher.kt | 3 --- .../service/pricing/fetchers/OsmosisPriceFetcher.kt | 13 +++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 306bd26d..3e040ffa 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -69,16 +69,16 @@ import java.util.zip.ZipOutputStream import javax.servlet.ServletOutputStream @Service -class TokenService(private val accountClient: AccountGrpcClient, - private val flowApiGrpcClient: FlowApiGrpcClient, - private val historicalPriceFetcherFactory: HistoricalPriceFetcherFactory +class TokenService( + private val accountClient: AccountGrpcClient, + private val flowApiGrpcClient: FlowApiGrpcClient, + private val historicalPriceFetcherFactory: HistoricalPriceFetcherFactory ) { - protected val logger = logger(TokenService::class) - private val historicalPriceFetchers: List by lazy { historicalPriceFetcherFactory.createNhashFetchers() } + fun getTokenDistributionStats() = transaction { TokenDistributionAmountsRecord.getStats() } fun saveResults(records: List) = runBlocking { diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index a6409819..96ebd704 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -1,11 +1,8 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties -import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient -import io.provlabs.flow.api.NavEvent -import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import java.math.BigDecimal import java.math.RoundingMode diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt index 69b51ad2..7d2e5b3b 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt @@ -1,16 +1,17 @@ package io.provenance.explorer.service.pricing.fetchers -import io.ktor.client.call.* -import io.ktor.client.plugins.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* +import io.ktor.client.call.body +import io.ktor.client.plugins.ResponseException +import io.ktor.client.request.accept +import io.ktor.client.request.get +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsText +import io.ktor.http.ContentType import io.provenance.explorer.KTOR_CLIENT_JAVA import io.provenance.explorer.domain.core.logger import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.OsmosisApiResponse import io.provenance.explorer.domain.models.OsmosisHistoricalPrice -import io.provenance.explorer.service.TokenService import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import org.joda.time.DateTimeZone From 658b2daab9b3c7e38340b197c35288c0f20d97eb Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 14:17:21 -0600 Subject: [PATCH 25/40] add legacy/deprecated fetcher for removal in future PR --- .../models/explorer/HistoricalPriceModels.kt | 9 ++ .../explorer/service/TokenService.kt | 117 ++---------------- .../service/async/ScheduledTaskService.kt | 5 +- .../fetchers/HistoricalPriceFetcherFactory.kt | 6 + 4 files changed, 30 insertions(+), 107 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt b/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt index 2903acc7..37d58b43 100644 --- a/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt +++ b/service/src/main/kotlin/io/provenance/explorer/domain/models/explorer/HistoricalPriceModels.kt @@ -11,6 +11,15 @@ data class HistoricalPrice( val volume: BigDecimal ) +fun HistoricalPrice.toCsv(): List = listOf( + "$time", + "$open", + "$high", + "$low", + "$close", + "$volume" +) + data class OsmosisHistoricalPrice( val time: Long, val high: BigDecimal, diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 3e040ffa..6f5c2679 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -2,14 +2,6 @@ package io.provenance.explorer.service import com.fasterxml.jackson.module.kotlin.readValue import cosmos.auth.v1beta1.Auth -import io.ktor.client.call.body -import io.ktor.client.plugins.ResponseException -import io.ktor.client.request.accept -import io.ktor.client.request.get -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.bodyAsText -import io.ktor.http.ContentType -import io.provenance.explorer.KTOR_CLIENT_JAVA import io.provenance.explorer.VANILLA_MAPPER import io.provenance.explorer.config.ExplorerProperties.Companion.PROV_ACC_PREFIX import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN @@ -34,9 +26,8 @@ import io.provenance.explorer.domain.extensions.toCoinStr import io.provenance.explorer.domain.extensions.toOffset import io.provenance.explorer.domain.extensions.toPercentage import io.provenance.explorer.domain.models.HistoricalPrice -import io.provenance.explorer.domain.models.OsmosisApiResponse -import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.domain.models.explorer.TokenHistoricalDataRequest +import io.provenance.explorer.domain.models.toCsv import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provenance.explorer.model.AssetHolder @@ -50,7 +41,6 @@ import io.provenance.explorer.model.base.CountStrTotal import io.provenance.explorer.model.base.PagedResults import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcher import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcherFactory -import io.provlabs.flow.api.NavEvent import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map @@ -58,12 +48,9 @@ import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.jetbrains.exposed.sql.transactions.transaction import org.joda.time.DateTime -import org.joda.time.DateTimeZone -import org.joda.time.Duration import org.springframework.stereotype.Service import java.math.BigDecimal import java.math.RoundingMode -import java.net.URLEncoder import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream import javax.servlet.ServletOutputStream @@ -75,10 +62,15 @@ class TokenService( private val historicalPriceFetcherFactory: HistoricalPriceFetcherFactory ) { protected val logger = logger(TokenService::class) + private val historicalPriceFetchers: List by lazy { historicalPriceFetcherFactory.createNhashFetchers() } + private val deprecatedHistoricalPricingFetchers : List by lazy { + historicalPriceFetcherFactory.createOsmosisPriceFetcher() + } + fun getTokenDistributionStats() = transaction { TokenDistributionAmountsRecord.getStats() } fun saveResults(records: List) = runBlocking { @@ -245,91 +237,17 @@ class TokenService( } fun fetchHistoricalPriceData(fromDate: DateTime?): List = runBlocking { - val fetchers = historicalPriceFetcherFactory.createNhashFetchers() - - val allPrices = fetchers.flatMap { fetcher -> + val allPrices = historicalPriceFetchers.flatMap { fetcher -> fetcher.fetchHistoricalPrice(fromDate) } return@runBlocking allPrices } - fun fetchOsmosisData(fromDate: DateTime?): List = runBlocking { - val input = buildInputQuery(fromDate, determineTimeFrame(fromDate)) - try { - val url = """https://app.osmosis.zone/api/edge-trpc-assets/assets.getAssetHistoricalPrice?input=$input""" - logger.info("Calling $url with fromDate $fromDate") - val response: HttpResponse = KTOR_CLIENT_JAVA.get(url) { - accept(ContentType.Application.Json) - } - - val rawResponse: String = response.bodyAsText() - logger.debug("Osmosis GET: $url Raw Response: $rawResponse") - - val osmosisApiResponse: OsmosisApiResponse = response.body() - osmosisApiResponse.result.data.json - } catch (e: ResponseException) { - logger.error("Error fetching from Osmosis API: ${e.response}", e) - emptyList() - } catch (e: Exception) { - logger.error("Error fetching from Osmosis API: ${e.message}", e) - emptyList() - } - } - - fun fetchOnChainNavData(denom: String, fromDate: DateTime?, limit: Int = 100): List = runBlocking { - val priceDenoms = listOf("uusd.trading", "uusdc.figure.se") - flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, priceDenoms, fromDate, limit) - } - - enum class TimeFrame(val minutes: Int) { - FIVE_MINUTES(5), - TWO_HOURS(120), - ONE_DAY(1440) - } - - /** - * Determines the appropriate TimeFrame based on the fromDate. - * - * @param fromDate The starting date to determine the time frame. - * @return The appropriate TimeFrame enum value. - */ - fun determineTimeFrame(fromDate: DateTime?): TimeFrame { - val now = DateTime.now(DateTimeZone.UTC) - val duration = Duration(fromDate, now) - return when { - duration.standardDays <= 14 -> TimeFrame.FIVE_MINUTES - duration.standardDays <= 60 -> TimeFrame.TWO_HOURS - else -> TimeFrame.ONE_DAY + fun fetchLegacyHistoricalPriceData(fromDate: DateTime?): List = runBlocking { + val allPrices = deprecatedHistoricalPricingFetchers.flatMap { fetcher -> + fetcher.fetchHistoricalPrice(fromDate) } - } - - /** - * Builds the input query parameter for fetching historical data. - * - * This function constructs a URL-encoded JSON query parameter for fetching historical data based on the given - * `fromDate` and `timeFrame`. The `timeFrame` represents the number of minutes between updates. The allowed values - * for `timeFrame` are defined in the `TimeFrame` enum: - * - FIVE_MINUTES: data goes back 2 weeks. - * - TWO_HOURS: data goes back 2 months. - * - ONE_DAY: data goes back to the beginning of time. - * - * The function calculates the total number of frames (`numRecentFrames`) from the `fromDate` to the current time, - * based on the specified `timeFrame`. - * - * @param fromDate The starting date from which to calculate the number of frames. - * @param timeFrame The time interval between updates, specified as a `TimeFrame` enum value. - * @return A URL-encoded JSON string to be used as a query parameter for fetching historical data. - */ - fun buildInputQuery(fromDate: DateTime?, timeFrame: TimeFrame): String { - val coinDenom = "ibc/CE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2" - val coinMinimalDenom = "ibc/CE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2" - val now = DateTime.now(DateTimeZone.UTC) - val duration = Duration(fromDate, now) - val numRecentFrames = (duration.standardMinutes / timeFrame.minutes).toInt() - return URLEncoder.encode( - """{"json":{"coinDenom":"$coinDenom","coinMinimalDenom":"$coinMinimalDenom","timeFrame":{"custom":{"timeFrame":${timeFrame.minutes},"numRecentFrames":$numRecentFrames}}}}""", - "UTF-8" - ) + return@runBlocking allPrices } fun getHashPricingDataDownload(filters: TokenHistoricalDataRequest, resp: ServletOutputStream): ZipOutputStream { @@ -337,7 +255,7 @@ class TokenService( val baseFileName = filters.getFileNameBase() val fileList = runBlocking { - val data = fetchOsmosisData(filters.fromDate) + val data = fetchLegacyHistoricalPriceData(filters.fromDate) listOf( CsvData( "TokenHistoricalData", @@ -359,17 +277,6 @@ class TokenService( zos.close() return zos } - - private fun OsmosisHistoricalPrice.toCsv(): List { - return listOf( - time.toString(), - open.toString(), - high.toString(), - low.toString(), - close.toString(), - volume.toString() - ) - } } /** diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index f0d315d1..d3ec707c 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -40,6 +40,7 @@ import io.provenance.explorer.domain.extensions.percentChange import io.provenance.explorer.domain.extensions.startOfDay import io.provenance.explorer.domain.extensions.toDateTime import io.provenance.explorer.domain.extensions.toThirdDecimal +import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.grpc.extensions.getMsgSubTypes import io.provenance.explorer.grpc.extensions.getMsgType @@ -312,12 +313,12 @@ class ScheduledTaskService( if (latest != null) { startDate = latest.timestamp.minusDays(1).startOfDay() } - val dlobRes = tokenService.fetchOsmosisData(startDate) ?: return + val dlobRes = tokenService.fetchLegacyHistoricalPriceData(startDate) ?: return logger.info("Updating token historical data starting from $startDate with ${dlobRes.size} buy records for roll-up.") val baseMap = Interval(startDate, today) .let { int -> generateSequence(int.start) { dt -> dt.plusDays(1) }.takeWhile { dt -> dt < int.end } } - .map { it to emptyList() }.toMap().toMutableMap() + .map { it to emptyList() }.toMap().toMutableMap() var prevPrice = TokenHistoricalDailyRecord.lastKnownPriceForDate(startDate) baseMap.putAll( diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt index e886ece8..27f388ba 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt @@ -12,4 +12,10 @@ class HistoricalPriceFetcherFactory( FlowApiPriceFetcher(UTILITY_TOKEN, listOf("uusd.trading", "uusdc.figure.se"), flowApiGrpcClient) ) } + + fun createOsmosisPriceFetcher(): List { + return listOf( + OsmosisPriceFetcher() + ) + } } From c7223abaaaf127c4605acf42be31b087bef286a8 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 14:33:41 -0600 Subject: [PATCH 26/40] fix lints --- .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 2 +- .../provenance/explorer/service/async/ScheduledTaskService.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 6f5c2679..f4361d8a 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -67,7 +67,7 @@ class TokenService( historicalPriceFetcherFactory.createNhashFetchers() } - private val deprecatedHistoricalPricingFetchers : List by lazy { + private val deprecatedHistoricalPricingFetchers: List by lazy { historicalPriceFetcherFactory.createOsmosisPriceFetcher() } diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index d3ec707c..04866a6a 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -41,7 +41,6 @@ import io.provenance.explorer.domain.extensions.startOfDay import io.provenance.explorer.domain.extensions.toDateTime import io.provenance.explorer.domain.extensions.toThirdDecimal import io.provenance.explorer.domain.models.HistoricalPrice -import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import io.provenance.explorer.grpc.extensions.getMsgSubTypes import io.provenance.explorer.grpc.extensions.getMsgType import io.provenance.explorer.model.CmcHistoricalQuote From 684104aa892472687766b480f3526aa0bc00918a Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 15:03:10 -0600 Subject: [PATCH 27/40] add fetcher tests remove old ones from token service --- .../pricing/fetchers/FlowApiPriceFetcher.kt | 7 +- .../explorer/service/TokenServiceTest.kt | 73 ------------------- .../fetchers/FlowApiPriceFetcherTest.kt | 56 ++++++++++++++ .../fetchers/OsmosisPriceFetcherTest.kt | 60 +++++++++++++++ 4 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt create mode 100644 service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index 96ebd704..c7eacaa9 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -3,6 +3,7 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient +import io.provlabs.flow.api.NavEvent import org.joda.time.DateTime import java.math.BigDecimal import java.math.RoundingMode @@ -14,7 +15,7 @@ class FlowApiPriceFetcher( ) : HistoricalPriceFetcher { override fun fetchHistoricalPrice(fromDate: DateTime?): List { - val onChainNavEvents = flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, pricingDenoms, fromDate, 17800) + val onChainNavEvents = getMarkerNavByPriceDenoms(fromDate, 17800) return onChainNavEvents.map { navEvent -> val volumeHash = calculateVolumeHash(navEvent.volume) val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) @@ -29,6 +30,10 @@ class FlowApiPriceFetcher( } } + fun getMarkerNavByPriceDenoms(fromDate: DateTime?, limit: Int): List{ + return flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, pricingDenoms, fromDate, limit) + } + fun calculateVolumeHash(volumeNhash: Long): BigDecimal { if (volumeNhash == 0L) { return BigDecimal.ZERO diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 0717df2d..36e25451 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -22,78 +22,5 @@ class TokenServiceTest { @BeforeEach fun setUp() { accountClient = AccountGrpcClient(URI("https://www.google.com")) - tokenService = TokenService(accountClient, FlowApiGrpcClient(URI("http://localhost:50051"))) - } - - @Test - @Disabled("Test was used to manually call the endpoint") - fun `test fetchOsmosisData and print results`() = runBlocking { - val fromDate = DateTime.parse("2024-05-08") - - val result: List = tokenService.fetchOsmosisData(fromDate) - - result.forEach { - println("Time: ${DateTime(it.time * 1000)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") - } - } - - @Test - fun `test determineTimeFrame`() { - val now = DateTime.now(DateTimeZone.UTC) - - val fromDate1 = now.minusDays(10) - val timeFrame1 = tokenService.determineTimeFrame(fromDate1) - assertEquals(TokenService.TimeFrame.FIVE_MINUTES, timeFrame1) - - val fromDate2 = now.minusDays(30) - val timeFrame2 = tokenService.determineTimeFrame(fromDate2) - assertEquals(TokenService.TimeFrame.TWO_HOURS, timeFrame2) - - val fromDate3 = now.minusDays(90) - val timeFrame3 = tokenService.determineTimeFrame(fromDate3) - assertEquals(TokenService.TimeFrame.ONE_DAY, timeFrame3) - } - - @Test - fun `test buildInputQuery`() { - val now = DateTime.now(DateTimeZone.UTC) - - val fromDate1 = now.minusDays(10) - val timeFrame1 = TokenService.TimeFrame.FIVE_MINUTES - val inputQuery1 = tokenService.buildInputQuery(fromDate1, timeFrame1) - val expectedQuery1 = """%7B%22json%22%3A%7B%22coinDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22coinMinimalDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22timeFrame%22%3A%7B%22custom%22%3A%7B%22timeFrame%22%3A5%2C%22numRecentFrames%22%3A2880%7D%7D%7D%7D""" - assertEquals(expectedQuery1, inputQuery1) - } - - @Test - @Disabled("Test was used to manually call the endpoint") - fun `test fetchOnChainNavData`() { - val denom = "nhash" - val fromDate = DateTime.now().minusDays(7) - val limit = 100 - - val result: List = tokenService.fetchOnChainNavData(denom, fromDate, limit) - - val groupedByPriceDenom = result.groupBy { it.priceDenom } - - groupedByPriceDenom.forEach { (priceDenom, events) -> - println("PriceDenom: $priceDenom, Count: ${events.size}") - } - - result.forEach { navEvent -> - val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) - println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000, DateTimeZone.getDefault())}, PriceDenom=${navEvent.priceDenom}, Hash Price: $pricePerHash") - } - - assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } - } - - @Test - fun `test calculatePricePerHash with multiple scenarios`() { - var result = calculatePricePerHash(12345L, ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER.toLong()) - assertEquals(12.345, result, "price per hash calculation is incorrect") - - result = calculatePricePerHash(12345L, 0L) - assertEquals(0.0, result, "Should return 0.0 when volume is 0") } } diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt new file mode 100644 index 00000000..78644d03 --- /dev/null +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt @@ -0,0 +1,56 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.config.ExplorerProperties +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient +import io.provlabs.flow.api.NavEvent +import org.joda.time.DateTime +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import java.net.URI + +class FlowApiPriceFetcherTest { + + private lateinit var flowApiPriceFetcher: FlowApiPriceFetcher + + @BeforeEach + fun setUp() { + flowApiPriceFetcher = FlowApiPriceFetcher( + ExplorerProperties.UTILITY_TOKEN, + listOf("uusd.trading", "uusdc.figure.se"), + FlowApiGrpcClient(URI("http://localhost:50051")) + ) + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test fetchOnChainNavData and print results`() { + val fromDate = DateTime.now().minusDays(7) + val limit = 100 + + val result: List = flowApiPriceFetcher.getMarkerNavByPriceDenoms(fromDate, limit) + + val groupedByPriceDenom = result.groupBy { it.priceDenom } + + groupedByPriceDenom.forEach { (priceDenom, events) -> + println("PriceDenom: $priceDenom, Count: ${events.size}") + } + + result.forEach { navEvent -> + val pricePerHash = flowApiPriceFetcher.calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000)}, PriceDenom=${navEvent.priceDenom}, Hash Price: $pricePerHash") + } + + assert(result.isNotEmpty()) { "Expected non-empty NavEvent list" } + } + + @Test + fun `test calculatePricePerHash with multiple scenarios`() { + var result = flowApiPriceFetcher.calculatePricePerHash(12345L, ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER.toLong()) + assertEquals(12.345, result, "Price per hash calculation is incorrect") + + result = flowApiPriceFetcher.calculatePricePerHash(12345L, 0L) + assertEquals(0.0, result, "Should return 0.0 when volume is 0") + } +} diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt new file mode 100644 index 00000000..57d22304 --- /dev/null +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt @@ -0,0 +1,60 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.domain.models.OsmosisHistoricalPrice +import org.joda.time.DateTime +import org.joda.time.DateTimeZone +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Assertions.assertEquals + +class OsmosisPriceFetcherTest { + + private lateinit var osmosisPriceFetcher: OsmosisPriceFetcher + + @BeforeEach + fun setUp() { + osmosisPriceFetcher = OsmosisPriceFetcher() + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test fetchOsmosisData and print results`() = runBlocking { + val fromDate = DateTime.parse("2024-05-08") + + val result: List = osmosisPriceFetcher.fetchOsmosisData(fromDate) + + result.forEach { + println("Time: ${DateTime(it.time * 1000)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") + } + } + + @Test + fun `test determineTimeFrame`() { + val now = DateTime.now(DateTimeZone.UTC) + + val fromDate1 = now.minusDays(10) + val timeFrame1 = osmosisPriceFetcher.determineTimeFrame(fromDate1) + assertEquals(OsmosisPriceFetcher.TimeFrame.FIVE_MINUTES, timeFrame1) + + val fromDate2 = now.minusDays(30) + val timeFrame2 = osmosisPriceFetcher.determineTimeFrame(fromDate2) + assertEquals(OsmosisPriceFetcher.TimeFrame.TWO_HOURS, timeFrame2) + + val fromDate3 = now.minusDays(90) + val timeFrame3 = osmosisPriceFetcher.determineTimeFrame(fromDate3) + assertEquals(OsmosisPriceFetcher.TimeFrame.ONE_DAY, timeFrame3) + } + + @Test + fun `test buildInputQuery`() { + val now = DateTime.now(DateTimeZone.UTC) + + val fromDate1 = now.minusDays(10) + val timeFrame1 = OsmosisPriceFetcher.TimeFrame.FIVE_MINUTES + val inputQuery1 = osmosisPriceFetcher.buildInputQuery(fromDate1, timeFrame1) + val expectedQuery1 = """%7B%22json%22%3A%7B%22coinDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22coinMinimalDenom%22%3A%22ibc%2FCE5BFF1D9BADA03BB5CCA5F56939392A761B53A10FBD03B37506669C3218D3B2%22%2C%22timeFrame%22%3A%7B%22custom%22%3A%7B%22timeFrame%22%3A5%2C%22numRecentFrames%22%3A2880%7D%7D%7D%7D""" + assertEquals(expectedQuery1, inputQuery1) + } +} From 376ebafe07e11040020fa4e971b41ad19c63bc7d Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 15:19:26 -0600 Subject: [PATCH 28/40] add a few more tests --- .../pricing/fetchers/FlowApiPriceFetcher.kt | 4 +- .../explorer/service/TokenServiceTest.kt | 76 +++++++++++++++++-- .../HistoricalPriceFetcherFactoryTest.kt | 40 ++++++++++ 3 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index c7eacaa9..67cd97ff 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -9,8 +9,8 @@ import java.math.BigDecimal import java.math.RoundingMode class FlowApiPriceFetcher( - private val denom: String, - private val pricingDenoms: List, + val denom: String, + val pricingDenoms: List, private val flowApiGrpcClient: FlowApiGrpcClient ) : HistoricalPriceFetcher { diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 36e25451..f4691dd3 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -1,13 +1,11 @@ package io.provenance.explorer.service -import io.provenance.explorer.config.ExplorerProperties -import io.provenance.explorer.domain.models.OsmosisHistoricalPrice +import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient -import io.provlabs.flow.api.NavEvent +import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcherFactory import kotlinx.coroutines.runBlocking import org.joda.time.DateTime -import org.joda.time.DateTimeZone import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled @@ -17,10 +15,78 @@ import java.net.URI class TokenServiceTest { private lateinit var accountClient: AccountGrpcClient + private lateinit var flowApiGrpcClient: FlowApiGrpcClient + private lateinit var historicalPriceFetcherFactory: HistoricalPriceFetcherFactory private lateinit var tokenService: TokenService @BeforeEach fun setUp() { - accountClient = AccountGrpcClient(URI("https://www.google.com")) + accountClient = AccountGrpcClient(URI("http://localhost:26657")) + flowApiGrpcClient = FlowApiGrpcClient(URI("http://localhost:50051")) + historicalPriceFetcherFactory = HistoricalPriceFetcherFactory(flowApiGrpcClient) // Set the factory as needed + tokenService = TokenService(accountClient, flowApiGrpcClient, historicalPriceFetcherFactory) + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test fetchHistoricalPriceData`() = runBlocking { + val fromDate = DateTime.now().minusDays(7) + + val result: List = tokenService.fetchHistoricalPriceData(fromDate) + + result.forEach { + println("Time: ${DateTime(it.time)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") + } + + assert(result.isNotEmpty()) { "Expected non-empty list of HistoricalPrice" } + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test fetchLegacyHistoricalPriceData`() = runBlocking { + val fromDate = DateTime.now().minusDays(7) + + val result: List = tokenService.fetchLegacyHistoricalPriceData(fromDate) + + result.forEach { + println("Time: ${DateTime(it.time)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") + } + + assert(result.isNotEmpty()) { "Expected non-empty list of HistoricalPrice" } + } + + @Test + fun `test calculatePricePerHash`() { + val priceAmount = 12345L + val volume = 1000000000000L // 1 Hash = 1,000,000,000 nHash + + val result = calculatePricePerHash(priceAmount, volume) + assertEquals(12.345, result, "Price per hash calculation is incorrect") + } + + @Test + fun `test calculateVolumeHash`() { + val volumeNhash = 1000000000000L // 1 Hash = 1,000,000,000 nHash + + val result = calculateVolumeHash(volumeNhash) + assertEquals(1.toBigDecimal(), result, "Volume hash calculation is incorrect") + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test getTokenDistributionStats`() { + val result = tokenService.getTokenDistributionStats() + println(result) + assert(result.isNotEmpty()) { "Expected non-empty token distribution stats" } + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test getTokenBreakdown`() = runBlocking { + val result = tokenService.getTokenBreakdown() + println("Max supply: ${result.maxSupply}") + println("Community pool supply: ${result.communityPool}") + println("Bonded supply: ${result.bonded}") + println("Burned supply: ${result.burned}") } } diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt new file mode 100644 index 00000000..d7910dae --- /dev/null +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt @@ -0,0 +1,40 @@ +package io.provenance.explorer.service.pricing.fetchers + +import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN +import io.provenance.explorer.grpc.flow.FlowApiGrpcClient +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import java.net.URI + +class HistoricalPriceFetcherFactoryTest { + + private lateinit var flowApiGrpcClient: FlowApiGrpcClient + private lateinit var factory: HistoricalPriceFetcherFactory + + @BeforeEach + fun setUp() { + flowApiGrpcClient = FlowApiGrpcClient(URI("http://localhost:50051")) + factory = HistoricalPriceFetcherFactory(flowApiGrpcClient) + } + + @Test + fun `test createNhashFetchers`() { + val fetchers = factory.createNhashFetchers() + assertEquals(2, fetchers.size) + assertTrue(fetchers[0] is OsmosisPriceFetcher) + assertTrue(fetchers[1] is FlowApiPriceFetcher) + + val flowApiPriceFetcher = fetchers[1] as FlowApiPriceFetcher + assertEquals(UTILITY_TOKEN, flowApiPriceFetcher.denom) + assertEquals(listOf("uusd.trading", "uusdc.figure.se"), flowApiPriceFetcher.pricingDenoms) + } + + @Test + fun `test createOsmosisPriceFetcher`() { + val fetchers = factory.createOsmosisPriceFetcher() + assertEquals(1, fetchers.size) + assertTrue(fetchers[0] is OsmosisPriceFetcher) + } +} From 4a022c1ea6b749b294f1512249142029165c314c Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 16:02:00 -0600 Subject: [PATCH 29/40] fix lints --- .../explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt | 2 +- .../service/pricing/fetchers/OsmosisPriceFetcherTest.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index 67cd97ff..8b4f72e5 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -30,7 +30,7 @@ class FlowApiPriceFetcher( } } - fun getMarkerNavByPriceDenoms(fromDate: DateTime?, limit: Int): List{ + fun getMarkerNavByPriceDenoms(fromDate: DateTime?, limit: Int): List { return flowApiGrpcClient.getMarkerNavByPriceDenoms(denom, pricingDenoms, fromDate, limit) } diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt index 57d22304..97d6da5f 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt @@ -3,11 +3,12 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.domain.models.OsmosisHistoricalPrice import org.joda.time.DateTime import org.joda.time.DateTimeZone +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.Assertions.assertEquals + class OsmosisPriceFetcherTest { From d00ce02e2b04921b159bd7185fdde91d9c4dfe26 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Mon, 30 Sep 2024 17:15:27 -0600 Subject: [PATCH 30/40] fre more lint fixes --- .../pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt | 4 ++-- .../service/pricing/fetchers/OsmosisPriceFetcherTest.kt | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt index d7910dae..550dba22 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt @@ -2,10 +2,10 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN import io.provenance.explorer.grpc.flow.FlowApiGrpcClient -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test import java.net.URI class HistoricalPriceFetcherFactoryTest { diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt index 97d6da5f..6f13b924 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt @@ -1,14 +1,13 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.domain.models.OsmosisHistoricalPrice +import kotlinx.coroutines.runBlocking import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import kotlinx.coroutines.runBlocking - class OsmosisPriceFetcherTest { From f939fa6ff00e92bca6964c7bbbebabf71d97bcde Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 12:07:43 -0600 Subject: [PATCH 31/40] fix price per hash calculation, refactor and add better tests --- .../explorer/service/TokenService.kt | 49 +++++++++---------- .../service/async/ScheduledTaskService.kt | 23 +++------ .../pricing/fetchers/FlowApiPriceFetcher.kt | 33 +++++++------ .../explorer/service/TokenServiceTest.kt | 17 ------- .../fetchers/FlowApiPriceFetcherTest.kt | 43 +++++++++++++--- .../fetchers/OsmosisPriceFetcherTest.kt | 5 +- 6 files changed, 86 insertions(+), 84 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index f4361d8a..720ab407 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -20,11 +20,13 @@ import io.provenance.explorer.domain.entities.vestingAccountTypes import io.provenance.explorer.domain.exceptions.validate import io.provenance.explorer.domain.extensions.CsvData import io.provenance.explorer.domain.extensions.pageCountOfResults +import io.provenance.explorer.domain.extensions.percentChange import io.provenance.explorer.domain.extensions.roundWhole import io.provenance.explorer.domain.extensions.startOfDay import io.provenance.explorer.domain.extensions.toCoinStr import io.provenance.explorer.domain.extensions.toOffset import io.provenance.explorer.domain.extensions.toPercentage +import io.provenance.explorer.domain.extensions.toThirdDecimal import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.explorer.TokenHistoricalDataRequest import io.provenance.explorer.domain.models.toCsv @@ -32,6 +34,7 @@ import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provenance.explorer.model.AssetHolder import io.provenance.explorer.model.CmcLatestDataAbbrev +import io.provenance.explorer.model.CmcLatestQuoteAbbrev import io.provenance.explorer.model.RichAccount import io.provenance.explorer.model.TokenDistribution import io.provenance.explorer.model.TokenDistributionAmount @@ -39,6 +42,7 @@ import io.provenance.explorer.model.TokenSupply import io.provenance.explorer.model.base.CoinStr import io.provenance.explorer.model.base.CountStrTotal import io.provenance.explorer.model.base.PagedResults +import io.provenance.explorer.model.base.USD_UPPER import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcher import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcherFactory import kotlinx.coroutines.flow.asFlow @@ -250,6 +254,26 @@ class TokenService( return@runBlocking allPrices } + fun processLatestTokenData(list: List, today: DateTime): CmcLatestDataAbbrev? { + val prevRecord = list.firstOrNull() ?: return null + val price = list.last().close.toThirdDecimal() + val percentChg = price.percentChange(prevRecord.close.toThirdDecimal()) + val vol24Hr = list.sumOf { it.volume.toThirdDecimal() }.stripTrailingZeros() + val marketCap = price.multiply(totalSupply().divide(UTILITY_TOKEN_BASE_MULTIPLIER)).toThirdDecimal() + + return CmcLatestDataAbbrev( + today, + mapOf(USD_UPPER to CmcLatestQuoteAbbrev(price, percentChg, vol24Hr, marketCap, today)) + ) + } + + fun cacheLatestTokenData(data: CmcLatestDataAbbrev) { + CacheUpdateRecord.updateCacheByKey( + CacheKeys.UTILITY_TOKEN_LATEST.key, + VANILLA_MAPPER.writeValueAsString(data) + ) + } + fun getHashPricingDataDownload(filters: TokenHistoricalDataRequest, resp: ServletOutputStream): ZipOutputStream { validate(filters.datesValidation()) val baseFileName = filters.getFileNameBase() @@ -279,29 +303,4 @@ class TokenService( } } -/** - * Calculates the price per hash unit based on the total price in USD (expressed as whole numbers - * where 12345 equals $12.345 USD) and the volume in nHash (nano Hash). - * - * @param priceAmount The total price in whole-number USD cents (e.g., 12345 equals $12.345 USD). - * @param volumeNhash The volume of the transaction in nHash (nano Hash). - * 1 Hash = 1,000,000,000 nHash. - * @return The price per hash unit. Returns 0.0 if the volumeNhash is 0 to avoid division by zero. - */ -fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { - val volumeHash = calculateVolumeHash(volumeNhash) - if (volumeHash == BigDecimal.ZERO) { - return 0.0 - } - val pricePerHash = BigDecimal(priceAmountMillis).divide(volumeHash, 10, RoundingMode.HALF_UP) - return pricePerHash.divide(BigDecimal(1000), 10, RoundingMode.HALF_UP).toDouble() -} - -fun calculateVolumeHash(volumeNhash: Long): BigDecimal { - if (volumeNhash == 0L) { - return BigDecimal.ZERO - } - return BigDecimal(volumeNhash).divide(UTILITY_TOKEN_BASE_MULTIPLIER, 10, RoundingMode.HALF_UP) -} - fun BigDecimal.asPercentOf(divisor: BigDecimal): BigDecimal = this.divide(divisor, 20, RoundingMode.CEILING) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index 04866a6a..0ece1310 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -360,23 +360,14 @@ class ScheduledTaskService( fun updateTokenLatest() { val today = DateTime.now().withZone(DateTimeZone.UTC) val startDate = today.minusDays(1) - tokenService.fetchHistoricalPriceData(startDate) - ?.sortedBy { it.time } - ?.let { list -> - val prevRecord = list.firstOrNull() ?: return - val price = list.last().close.toThirdDecimal() - val percentChg = price.percentChange(prevRecord.close.toThirdDecimal()) - val vol24Hr = list.sumOf { it.volume.toThirdDecimal() }.stripTrailingZeros() - val marketCap = price.multiply(tokenService.totalSupply().divide(UTILITY_TOKEN_BASE_MULTIPLIER)).toThirdDecimal() - val rec = CmcLatestDataAbbrev( - today, - mapOf(USD_UPPER to CmcLatestQuoteAbbrev(price, percentChg, vol24Hr, marketCap, today)) - ) - CacheUpdateRecord.updateCacheByKey( - CacheKeys.UTILITY_TOKEN_LATEST.key, - VANILLA_MAPPER.writeValueAsString(rec) - ) + val list = tokenService.fetchHistoricalPriceData(startDate)?.sortedBy { it.time } + + list?.let { + val latestData = tokenService.processLatestTokenData(it, today) + latestData?.let { data -> + tokenService.cacheLatestTokenData(data) } + } } // Remove once the ranges have been updated diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index 8b4f72e5..c437bd77 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -18,14 +18,14 @@ class FlowApiPriceFetcher( val onChainNavEvents = getMarkerNavByPriceDenoms(fromDate, 17800) return onChainNavEvents.map { navEvent -> val volumeHash = calculateVolumeHash(navEvent.volume) - val pricePerHash = calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + val pricePerHash = getPricePerHashFromMicroUsd(navEvent.priceAmount, navEvent.volume) HistoricalPrice( time = navEvent.blockTime, - high = BigDecimal(pricePerHash), - low = BigDecimal(pricePerHash), - close = BigDecimal(pricePerHash), - open = BigDecimal(pricePerHash), - volume = BigDecimal(pricePerHash).multiply(volumeHash) + high = pricePerHash, + low = pricePerHash, + close = pricePerHash, + open = pricePerHash, + volume = pricePerHash.multiply(volumeHash) ) } } @@ -42,20 +42,21 @@ class FlowApiPriceFetcher( } /** - * Calculates the price per hash unit based on the total price in USD (expressed as whole numbers - * where 12345 equals $12.345 USD) and the volume in nHash (nano Hash). + * Calculates the price per hash unit based on the total price in micro-USD and the volume in nHash. * - * @param priceAmount The total price in whole-number USD cents (e.g., 12345 equals $12.345 USD). + * @param priceAmountMicros The total price in micro-USD (e.g., 123456789 equals $123.456789 USD). * @param volumeNhash The volume of the transaction in nHash (nano Hash). * 1 Hash = 1,000,000,000 nHash. - * @return The price per hash unit. Returns 0.0 if the volumeNhash is 0 to avoid division by zero. + * @return The price per hash unit in USD, rounded down to 3 decimal places. + * Returns 0.0 if the volumeNhash is 0 to avoid division by zero. */ - fun calculatePricePerHash(priceAmountMillis: Long, volumeNhash: Long): Double { - val volumeHash = io.provenance.explorer.service.calculateVolumeHash(volumeNhash) - if (volumeHash == BigDecimal.ZERO) { - return 0.0 + fun getPricePerHashFromMicroUsd(priceAmountMicros: Long, volumeNhash: Long): BigDecimal { + if (volumeNhash == 0L) { + return BigDecimal.ZERO } - val pricePerHash = BigDecimal(priceAmountMillis).divide(volumeHash, 10, RoundingMode.HALF_UP) - return pricePerHash.divide(BigDecimal(1000), 10, RoundingMode.HALF_UP).toDouble() + val volumeHash = calculateVolumeHash(volumeNhash) + val priceInUsd = BigDecimal(priceAmountMicros).divide(BigDecimal(1_000_000), 10, RoundingMode.HALF_UP) + val pricePerHash = priceInUsd.divide(volumeHash, 10, RoundingMode.HALF_UP) + return pricePerHash.setScale(3, RoundingMode.FLOOR) } } diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index f4691dd3..e9e64741 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -55,23 +55,6 @@ class TokenServiceTest { assert(result.isNotEmpty()) { "Expected non-empty list of HistoricalPrice" } } - @Test - fun `test calculatePricePerHash`() { - val priceAmount = 12345L - val volume = 1000000000000L // 1 Hash = 1,000,000,000 nHash - - val result = calculatePricePerHash(priceAmount, volume) - assertEquals(12.345, result, "Price per hash calculation is incorrect") - } - - @Test - fun `test calculateVolumeHash`() { - val volumeNhash = 1000000000000L // 1 Hash = 1,000,000,000 nHash - - val result = calculateVolumeHash(volumeNhash) - assertEquals(1.toBigDecimal(), result, "Volume hash calculation is incorrect") - } - @Test @Disabled("Test was used to manually call the endpoint") fun `test getTokenDistributionStats`() { diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt index 78644d03..bd03ebec 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt @@ -1,6 +1,7 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties +import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provlabs.flow.api.NavEvent import org.joda.time.DateTime @@ -8,6 +9,7 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import java.math.BigDecimal import java.net.URI class FlowApiPriceFetcherTest { @@ -25,8 +27,22 @@ class FlowApiPriceFetcherTest { @Test @Disabled("Test was used to manually call the endpoint") - fun `test fetchOnChainNavData and print results`() { - val fromDate = DateTime.now().minusDays(7) + fun `test fetchHistoricalPrice and print results`() { + val fromDate = DateTime.now().minusDays(1) + + val result: List = flowApiPriceFetcher.fetchHistoricalPrice(fromDate) + result.forEach { + println("Time: ${DateTime(it.time * 1000)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") + } + + val totalVolume = result.sumOf { it.volume } + println("Total Volume: $totalVolume") + } + + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test getMarkerNavByPriceDenoms and print results`() { + val fromDate = DateTime.now().minusDays(1) val limit = 100 val result: List = flowApiPriceFetcher.getMarkerNavByPriceDenoms(fromDate, limit) @@ -38,7 +54,7 @@ class FlowApiPriceFetcherTest { } result.forEach { navEvent -> - val pricePerHash = flowApiPriceFetcher.calculatePricePerHash(navEvent.priceAmount, navEvent.volume) + val pricePerHash = flowApiPriceFetcher.getPricePerHashFromMicroUsd(navEvent.priceAmount, navEvent.volume) println("NavEvent: Time=${DateTime(navEvent.blockTime * 1000)}, PriceDenom=${navEvent.priceDenom}, Hash Price: $pricePerHash") } @@ -46,11 +62,22 @@ class FlowApiPriceFetcherTest { } @Test - fun `test calculatePricePerHash with multiple scenarios`() { - var result = flowApiPriceFetcher.calculatePricePerHash(12345L, ExplorerProperties.UTILITY_TOKEN_BASE_MULTIPLIER.toLong()) - assertEquals(12.345, result, "Price per hash calculation is incorrect") + fun `test calculatePricePerHashFromMicroUsd`() { + var result = flowApiPriceFetcher.getPricePerHashFromMicroUsd( + 4800000000L, + 300000000000000 + ) + assertEquals(BigDecimal("0.016"), result, "Price per hash calculation is incorrect") + + result = flowApiPriceFetcher.getPricePerHashFromMicroUsd(12345L, 0L) + assertEquals(BigDecimal.ZERO, result, "Should return 0.0 when volume is 0") + } + + @Test + fun `test calculateVolumeHash`() { + val volumeNhash = 1000000000000L - result = flowApiPriceFetcher.calculatePricePerHash(12345L, 0L) - assertEquals(0.0, result, "Should return 0.0 when volume is 0") + val result = flowApiPriceFetcher.calculateVolumeHash(volumeNhash) + assertEquals(1.toBigDecimal(), result, "Volume hash calculation is incorrect") } } diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt index 6f13b924..7cb0bec0 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcherTest.kt @@ -21,13 +21,14 @@ class OsmosisPriceFetcherTest { @Test @Disabled("Test was used to manually call the endpoint") fun `test fetchOsmosisData and print results`() = runBlocking { - val fromDate = DateTime.parse("2024-05-08") + val fromDate = DateTime.parse("2024-10-01") val result: List = osmosisPriceFetcher.fetchOsmosisData(fromDate) - result.forEach { println("Time: ${DateTime(it.time * 1000)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") } + val totalVolume = result.sumOf { it.volume } + println("Total Volume: $totalVolume") } @Test From b2265cc0f1f0f43403299b4dec0fe63579118e44 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 12:14:22 -0600 Subject: [PATCH 32/40] fix linting --- .../explorer/service/async/ScheduledTaskService.kt | 5 ----- .../io/provenance/explorer/service/TokenServiceTest.kt | 1 - 2 files changed, 6 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt index 0ece1310..25f46998 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/async/ScheduledTaskService.kt @@ -3,7 +3,6 @@ package io.provenance.explorer.service.async import cosmos.authz.v1beta1.msgExec import cosmos.authz.v1beta1.msgGrant import cosmos.authz.v1beta1.msgRevoke -import io.provenance.explorer.VANILLA_MAPPER import io.provenance.explorer.config.ExplorerProperties import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN import io.provenance.explorer.config.ExplorerProperties.Companion.UTILITY_TOKEN_BASE_DECIMAL_PLACES @@ -13,7 +12,6 @@ import io.provenance.explorer.domain.entities.BlockCacheRecord import io.provenance.explorer.domain.entities.BlockTxCountsCacheRecord import io.provenance.explorer.domain.entities.BlockTxRetryRecord import io.provenance.explorer.domain.entities.CacheKeys -import io.provenance.explorer.domain.entities.CacheUpdateRecord import io.provenance.explorer.domain.entities.ChainMarketRateStatsRecord import io.provenance.explorer.domain.entities.GovProposalRecord import io.provenance.explorer.domain.entities.ProcessQueueRecord @@ -36,7 +34,6 @@ import io.provenance.explorer.domain.entities.ValidatorStateRecord import io.provenance.explorer.domain.extensions.getType import io.provenance.explorer.domain.extensions.height import io.provenance.explorer.domain.extensions.monthToQuarter -import io.provenance.explorer.domain.extensions.percentChange import io.provenance.explorer.domain.extensions.startOfDay import io.provenance.explorer.domain.extensions.toDateTime import io.provenance.explorer.domain.extensions.toThirdDecimal @@ -44,8 +41,6 @@ import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.extensions.getMsgSubTypes import io.provenance.explorer.grpc.extensions.getMsgType import io.provenance.explorer.model.CmcHistoricalQuote -import io.provenance.explorer.model.CmcLatestDataAbbrev -import io.provenance.explorer.model.CmcLatestQuoteAbbrev import io.provenance.explorer.model.CmcQuote import io.provenance.explorer.model.base.USD_UPPER import io.provenance.explorer.service.AccountService diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index e9e64741..adaed208 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -6,7 +6,6 @@ import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provenance.explorer.service.pricing.fetchers.HistoricalPriceFetcherFactory import kotlinx.coroutines.runBlocking import org.joda.time.DateTime -import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test From b7e7a62007e237bd55b264c0779023bdf531941b Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 12:29:52 -0600 Subject: [PATCH 33/40] fix tests, add temp logging --- .../explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt | 3 +++ .../explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt | 3 ++- .../service/pricing/fetchers/FlowApiPriceFetcherTest.kt | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index c437bd77..8d34733d 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -1,6 +1,7 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties +import io.provenance.explorer.domain.core.logger import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provlabs.flow.api.NavEvent @@ -14,7 +15,9 @@ class FlowApiPriceFetcher( private val flowApiGrpcClient: FlowApiGrpcClient ) : HistoricalPriceFetcher { + val logger = logger(FlowApiPriceFetcher::class) override fun fetchHistoricalPrice(fromDate: DateTime?): List { + logger.info("fetching navs from $fromDate") val onChainNavEvents = getMarkerNavByPriceDenoms(fromDate, 17800) return onChainNavEvents.map { navEvent -> val volumeHash = calculateVolumeHash(navEvent.volume) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt index 7d2e5b3b..e159a74d 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt @@ -20,8 +20,9 @@ import java.net.URLEncoder class OsmosisPriceFetcher : HistoricalPriceFetcher { - protected val logger = logger(OsmosisPriceFetcher::class) + val logger = logger(OsmosisPriceFetcher::class) override fun fetchHistoricalPrice(fromDate: DateTime?): List { + logger.info("fetching osmosis prices from $fromDate") val osmosisHistoricalPrices = fetchOsmosisData(fromDate) return osmosisHistoricalPrices.map { osmosisPrice -> HistoricalPrice( diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt index bd03ebec..a9a8dac3 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt @@ -76,8 +76,9 @@ class FlowApiPriceFetcherTest { @Test fun `test calculateVolumeHash`() { val volumeNhash = 1000000000000L - val result = flowApiPriceFetcher.calculateVolumeHash(volumeNhash) - assertEquals(1.toBigDecimal(), result, "Volume hash calculation is incorrect") + val expected = 1000.0.toBigDecimal().setScale(10) + assertEquals(expected, result, "Volume hash calculation is incorrect") } + } From 81148ddfb818621ac99b5c5905f7f2824802189e Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 12:32:42 -0600 Subject: [PATCH 34/40] fix lint --- .../explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt index a9a8dac3..f1669505 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcherTest.kt @@ -80,5 +80,4 @@ class FlowApiPriceFetcherTest { val expected = 1000.0.toBigDecimal().setScale(10) assertEquals(expected, result, "Volume hash calculation is incorrect") } - } From 1fa03da5b9a468208637587776cb29ce9869f322 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:28:02 -0600 Subject: [PATCH 35/40] add a manual test --- .../explorer/service/TokenServiceTest.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index adaed208..88390526 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -40,6 +40,22 @@ class TokenServiceTest { assert(result.isNotEmpty()) { "Expected non-empty list of HistoricalPrice" } } + @Test + @Disabled("Test was used to manually call the endpoint") + fun `test fetchHistoricalPriceData and process `() = runBlocking { + val fromDate = DateTime.now().minusDays(1) + + val result: List = tokenService.fetchHistoricalPriceData(fromDate) + + tokenService.processLatestTokenData(result, fromDate) + + result.forEach { + println("Time: ${DateTime(it.time)}, Open: ${it.open}, High: ${it.high}, Low: ${it.low}, Close: ${it.close}, Volume: ${it.volume}") + } + + assert(result.isNotEmpty()) { "Expected non-empty list of HistoricalPrice" } + } + @Test @Disabled("Test was used to manually call the endpoint") fun `test fetchLegacyHistoricalPriceData`() = runBlocking { From 454314e114640a7a890943ac4a9cba4fdc725036 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:29:37 -0600 Subject: [PATCH 36/40] remove some logging --- .../explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt | 3 --- .../explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt index 8d34733d..c437bd77 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/FlowApiPriceFetcher.kt @@ -1,7 +1,6 @@ package io.provenance.explorer.service.pricing.fetchers import io.provenance.explorer.config.ExplorerProperties -import io.provenance.explorer.domain.core.logger import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provlabs.flow.api.NavEvent @@ -15,9 +14,7 @@ class FlowApiPriceFetcher( private val flowApiGrpcClient: FlowApiGrpcClient ) : HistoricalPriceFetcher { - val logger = logger(FlowApiPriceFetcher::class) override fun fetchHistoricalPrice(fromDate: DateTime?): List { - logger.info("fetching navs from $fromDate") val onChainNavEvents = getMarkerNavByPriceDenoms(fromDate, 17800) return onChainNavEvents.map { navEvent -> val volumeHash = calculateVolumeHash(navEvent.volume) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt index e159a74d..52d40faf 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/OsmosisPriceFetcher.kt @@ -22,7 +22,6 @@ class OsmosisPriceFetcher : HistoricalPriceFetcher { val logger = logger(OsmosisPriceFetcher::class) override fun fetchHistoricalPrice(fromDate: DateTime?): List { - logger.info("fetching osmosis prices from $fromDate") val osmosisHistoricalPrices = fetchOsmosisData(fromDate) return osmosisHistoricalPrices.map { osmosisPrice -> HistoricalPrice( @@ -40,7 +39,7 @@ class OsmosisPriceFetcher : HistoricalPriceFetcher { val input = buildInputQuery(fromDate, determineTimeFrame(fromDate)) try { val url = """https://app.osmosis.zone/api/edge-trpc-assets/assets.getAssetHistoricalPrice?input=$input""" - logger.info("Calling $url with fromDate $fromDate") + logger.debug("Calling $url with fromDate $fromDate") val response: HttpResponse = KTOR_CLIENT_JAVA.get(url) { accept(ContentType.Application.Json) } From 7a20c3fcb4b6eee5c5aeec1e46471395b756ddd4 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:37:14 -0600 Subject: [PATCH 37/40] add change log --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d8bd3e1..37a6a466 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +### Features +* Add hash price support for nav values from on chain events [#543](https://github.com/provenance-io/explorer-service/pull/543) + ### Improvements * Add limit of 1 to missing block queries [#544](https://github.com/provenance-io/explorer-service/pull/544) From 5d132b9909fa8472b54b4e71ae37e98f200dea00 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:41:24 -0600 Subject: [PATCH 38/40] remove unused injection, add uusdt.figure.se to historical price fetcher --- .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 1 - .../service/pricing/fetchers/HistoricalPriceFetcherFactory.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index 720ab407..ca3ccf23 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -62,7 +62,6 @@ import javax.servlet.ServletOutputStream @Service class TokenService( private val accountClient: AccountGrpcClient, - private val flowApiGrpcClient: FlowApiGrpcClient, private val historicalPriceFetcherFactory: HistoricalPriceFetcherFactory ) { protected val logger = logger(TokenService::class) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt index 27f388ba..8fd4302e 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactory.kt @@ -9,7 +9,7 @@ class HistoricalPriceFetcherFactory( fun createNhashFetchers(): List { return listOf( OsmosisPriceFetcher(), - FlowApiPriceFetcher(UTILITY_TOKEN, listOf("uusd.trading", "uusdc.figure.se"), flowApiGrpcClient) + FlowApiPriceFetcher(UTILITY_TOKEN, listOf("uusd.trading", "uusdc.figure.se", "uusdt.figure.se"), flowApiGrpcClient) ) } From 63fb800ee280d182ea349b47726efed16c383bc0 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:43:09 -0600 Subject: [PATCH 39/40] fix lint --- .../main/kotlin/io/provenance/explorer/service/TokenService.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt index ca3ccf23..c6f68491 100644 --- a/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt +++ b/service/src/main/kotlin/io/provenance/explorer/service/TokenService.kt @@ -30,7 +30,6 @@ import io.provenance.explorer.domain.extensions.toThirdDecimal import io.provenance.explorer.domain.models.HistoricalPrice import io.provenance.explorer.domain.models.explorer.TokenHistoricalDataRequest import io.provenance.explorer.domain.models.toCsv -import io.provenance.explorer.grpc.flow.FlowApiGrpcClient import io.provenance.explorer.grpc.v1.AccountGrpcClient import io.provenance.explorer.model.AssetHolder import io.provenance.explorer.model.CmcLatestDataAbbrev From 30e5a868c077cbb6a67c4fdf0b48199c6fd1a745 Mon Sep 17 00:00:00 2001 From: Carlton N Hanna Date: Tue, 1 Oct 2024 13:51:24 -0600 Subject: [PATCH 40/40] update test with new uusdt --- .../kotlin/io/provenance/explorer/service/TokenServiceTest.kt | 2 +- .../pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt index 88390526..277ce959 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/TokenServiceTest.kt @@ -23,7 +23,7 @@ class TokenServiceTest { accountClient = AccountGrpcClient(URI("http://localhost:26657")) flowApiGrpcClient = FlowApiGrpcClient(URI("http://localhost:50051")) historicalPriceFetcherFactory = HistoricalPriceFetcherFactory(flowApiGrpcClient) // Set the factory as needed - tokenService = TokenService(accountClient, flowApiGrpcClient, historicalPriceFetcherFactory) + tokenService = TokenService(accountClient, historicalPriceFetcherFactory) } @Test diff --git a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt index 550dba22..de0ea8b5 100644 --- a/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt +++ b/service/src/test/kotlin/io/provenance/explorer/service/pricing/fetchers/HistoricalPriceFetcherFactoryTest.kt @@ -28,7 +28,7 @@ class HistoricalPriceFetcherFactoryTest { val flowApiPriceFetcher = fetchers[1] as FlowApiPriceFetcher assertEquals(UTILITY_TOKEN, flowApiPriceFetcher.denom) - assertEquals(listOf("uusd.trading", "uusdc.figure.se"), flowApiPriceFetcher.pricingDenoms) + assertEquals(listOf("uusd.trading", "uusdc.figure.se", "uusdt.figure.se"), flowApiPriceFetcher.pricingDenoms) } @Test