Skip to content

Commit

Permalink
Feature/scripts for updating bridge config (#624)
Browse files Browse the repository at this point in the history
* Adding scripts for preparing update config msg transaction, signing transaction and submitting transaction.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing 'prepare-update-config.go' script.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Adding documentation for scripts.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Moving prepare-update-config.go to bridge/update-config/

Signed-off-by: Nikolay Nedkov <[email protected]>

* Moving sign and submit scripts to corresponding packages.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing comments.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing more comments.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing refactoring shitness.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Updating docs for scripts

Signed-off-by: Nikolay Nedkov <[email protected]>

* Adding implementation for reading and loading bridge config from HCS Messages.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Merging 'main'.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing bridge.yml

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing main.go

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing merge changes.

Signed-off-by: Nikolay Nedkov <[email protected]>

* fixing alice config.yml

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing check for starting BridgeConfigWatcher.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing comments.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing 'read-only/nft/fee/handler_test.go'.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing comments.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing not updating parsedBridge cfg on start bug.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Removing redundant bridge config global vars.

Signed-off-by: Nikolay Nedkov <[email protected]>

* Fixing tests.

Signed-off-by: Nikolay Nedkov <[email protected]>
  • Loading branch information
Nikolay Nedkov authored May 28, 2022
1 parent 96df903 commit 84b7c8a
Show file tree
Hide file tree
Showing 59 changed files with 1,822 additions and 303 deletions.
15 changes: 6 additions & 9 deletions app/clients/coin-gecko/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@
package coin_gecko

import (
"bytes"
"encoding/json"
"errors"
httpHelper "github.com/limechain/hedera-eth-bridge-validator/app/helper/http"
"github.com/limechain/hedera-eth-bridge-validator/config"
testConstants "github.com/limechain/hedera-eth-bridge-validator/test/constants"
"github.com/limechain/hedera-eth-bridge-validator/test/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io/ioutil"
"net/http"
"testing"
)
Expand All @@ -49,15 +47,14 @@ func Test_NewClient(t *testing.T) {

func Test_GetUsdPrices(t *testing.T) {
setup()

encodedResponseBuffer := new(bytes.Buffer)
encodeErr := json.NewEncoder(encodedResponseBuffer).Encode(testConstants.SimplePriceResponse)
encodedResponseReader := bytes.NewReader(encodedResponseBuffer.Bytes())
encodedResponseReaderCloser := ioutil.NopCloser(encodedResponseReader)
encodedResponseReaderCloser, encodeErr := httpHelper.EncodeBodyContent(testConstants.SimplePriceResponse)
if encodeErr != nil {
t.Fatal(encodeErr)
}
mocks.MHTTPClient.On("Do", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedResponseReaderCloser}, nilErr)

result, err := c.GetUsdPrices(testConstants.CoinGeckoIds)

assert.Nil(t, encodeErr)
assert.Nil(t, err)
assert.Equal(t, testConstants.UsdPrices, result)
}
Expand Down
14 changes: 6 additions & 8 deletions app/clients/coin-market-cap/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@
package coin_market_cap

import (
"bytes"
"encoding/json"
"errors"
httpHelper "github.com/limechain/hedera-eth-bridge-validator/app/helper/http"
"github.com/limechain/hedera-eth-bridge-validator/config"
testConstants "github.com/limechain/hedera-eth-bridge-validator/test/constants"
"github.com/limechain/hedera-eth-bridge-validator/test/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io/ioutil"
"net/http"
"testing"
)
Expand All @@ -50,11 +48,11 @@ func Test_NewClient(t *testing.T) {
func Test_GetUsdPrices(t *testing.T) {
setup()

encodedResponseBuffer := new(bytes.Buffer)
encodeErr := json.NewEncoder(encodedResponseBuffer).Encode(testConstants.CoinMarketCapResponse)
encodedResponseReader := bytes.NewReader(encodedResponseBuffer.Bytes())
encodedResponseReaderCloser := ioutil.NopCloser(encodedResponseReader)
mocks.MHTTPClient.On("Do", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedResponseReaderCloser}, nilErr)
encodedContent, encodeErr := httpHelper.EncodeBodyContent(testConstants.CoinMarketCapResponse)
if encodeErr != nil {
t.Fatal(encodeErr)
}
mocks.MHTTPClient.On("Do", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedContent}, nilErr)
result, err := c.GetUsdPrices(testConstants.CoinMarketCapIds)

assert.Nil(t, encodeErr)
Expand Down
55 changes: 51 additions & 4 deletions app/clients/hedera/mirror-node/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type Client struct {
mirrorAPIAddress string
httpClient client.HttpClient
pollingInterval time.Duration
queryMaxLimit int64
queryDefaultLimit int64
fullHederaGetHbarUsdPriceUrl string
logger *log.Entry
}
Expand All @@ -56,6 +58,8 @@ func NewClient(mirrorNode config.MirrorNode) *Client {
return &Client{
mirrorAPIAddress: mirrorNode.ApiAddress,
pollingInterval: mirrorNode.PollingInterval,
queryMaxLimit: mirrorNode.QueryMaxLimit,
queryDefaultLimit: mirrorNode.QueryDefaultLimit,
fullHederaGetHbarUsdPriceUrl: strings.Join([]string{mirrorNode.ApiAddress, TransactionsGetHBARUsdPrice}, ""),
httpClient: new(http.Client),
logger: config.GetLoggerFor("Mirror Node Client"),
Expand Down Expand Up @@ -138,14 +142,58 @@ func (c Client) GetAccountCreditTransactionsBetween(accountId hedera.AccountID,
}

// GetMessagesAfterTimestamp returns all Topic messages after the given timestamp
func (c Client) GetMessagesAfterTimestamp(topicId hedera.TopicID, from int64) ([]message.Message, error) {
messagesQuery := fmt.Sprintf("/%s/messages?timestamp=gt:%s",
func (c Client) GetMessagesAfterTimestamp(topicId hedera.TopicID, from int64, limit int64) ([]message.Message, error) {
messagesQuery := fmt.Sprintf("/%s/messages?timestamp=gt:%s&limit=%d",
topicId.String(),
timestampHelper.String(from))
timestampHelper.String(from),
limit)

return c.getTopicMessagesByQuery(messagesQuery)
}

// GetMessageBySequenceNumber returns message from given topic with provided sequence number
func (c Client) GetMessageBySequenceNumber(topicId hedera.TopicID, sequenceNumber int64) (*message.Message, error) {
messagesQuery := fmt.Sprintf("%s%s/%s/messages/%d",
c.mirrorAPIAddress,
"topics",
topicId.String(),
sequenceNumber)

response, e := c.get(messagesQuery)
if e != nil {
return nil, e
}

bodyBytes, e := readResponseBody(response)
if e != nil {
return nil, e
}

var message *message.Message
e = json.Unmarshal(bodyBytes, &message)
if e != nil {
return nil, e
}

return message, nil
}

// GetLatestMessages returns latest Topic messages
func (c Client) GetLatestMessages(topicId hedera.TopicID, limit int64) ([]message.Message, error) {
latestMessagesQuery := fmt.Sprintf("/%s/messages?order=desc&limit=%d", topicId.String(), limit)
return c.getTopicMessagesByQuery(latestMessagesQuery)
}

// GetQueryDefaultLimit returns the default records limit per query
func (c Client) QueryDefaultLimit() int64 {
return c.queryDefaultLimit
}

// GetQueryMaxLimit returns the maximum allowed limit per messages query
func (c Client) QueryMaxLimit() int64 {
return c.queryMaxLimit
}

// GetMessagesForTopicBetween returns all Topic messages for the specified topic between timestamp `from` and `to` excluded
func (c Client) GetMessagesForTopicBetween(topicId hedera.TopicID, from, to int64) ([]message.Message, error) {
transactionsDownloadQuery := fmt.Sprintf("/%s/messages?timestamp=gt:%s",
Expand Down Expand Up @@ -510,7 +558,6 @@ func (c Client) getTopicMessagesByQuery(query string) ([]message.Message, error)
if e != nil {
return nil, e
}

var messages *message.Messages
e = json.Unmarshal(bodyBytes, &messages)
if e != nil {
Expand Down
119 changes: 107 additions & 12 deletions app/clients/hedera/mirror-node/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
package mirror_node

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/hashgraph/hedera-sdk-go/v2"
"github.com/limechain/hedera-eth-bridge-validator/app/clients/hedera/mirror-node/model/message"
httpHelper "github.com/limechain/hedera-eth-bridge-validator/app/helper/http"
"github.com/limechain/hedera-eth-bridge-validator/config"
testConstants "github.com/limechain/hedera-eth-bridge-validator/test/constants"
"github.com/limechain/hedera-eth-bridge-validator/test/mocks"
Expand All @@ -41,7 +42,10 @@ var (
ApiAddress: mirrorAPIAddress,
PollingInterval: pollingInterval,
}
logger = config.GetLoggerFor("Mirror Node Client")
queryDefaultLimit = int64(1)
queryMaxLimit = int64(2)
sequenceNumber = int64(3)
logger = config.GetLoggerFor("Mirror Node Client")

accountId = hedera.AccountID{
Shard: 0,
Expand All @@ -67,10 +71,12 @@ var (
func setup() {
mocks.Setup()
c = &Client{
mirrorAPIAddress: mirrorAPIAddress,
httpClient: mocks.MHTTPClient,
pollingInterval: 5 * time.Second,
logger: logger,
mirrorAPIAddress: mirrorAPIAddress,
httpClient: mocks.MHTTPClient,
pollingInterval: 5 * time.Second,
queryDefaultLimit: queryDefaultLimit,
queryMaxLimit: queryMaxLimit,
logger: logger,
}
}

Expand Down Expand Up @@ -184,7 +190,7 @@ func Test_GetAccountTokenBurnTransactionsAfterTimestamp(t *testing.T) {
func Test_GetMessagesAfterTimestamp(t *testing.T) {
setup()
mocks.MHTTPClient.On("Get", mock.Anything).Return(nil, errors.New("some-error"))
response, err := c.GetMessagesAfterTimestamp(topicId, time.Now().UnixNano())
response, err := c.GetMessagesAfterTimestamp(topicId, time.Now().UnixNano(), queryDefaultLimit)
assert.Error(t, errors.New("some-error"), err)
assert.Nil(t, response)
}
Expand Down Expand Up @@ -249,16 +255,105 @@ func Test_GetAccountCreditTransactionsBetween(t *testing.T) {
assert.Nil(t, response)
}

func Test_GetHBARUsdPrice(t *testing.T) {
func Test_QueryDefaultLimit(t *testing.T) {
setup()

actual := c.QueryDefaultLimit()

assert.Equal(t, queryDefaultLimit, actual)
}

func Test_QueryMaxLimit(t *testing.T) {
setup()

actual := c.QueryMaxLimit()

assert.Equal(t, queryMaxLimit, actual)
}

func Test_GetLatestMessages(t *testing.T) {
setup()
expectedMsg := message.Message{
ConsensusTimestamp: "1",
TopicId: "1",
Contents: "1",
RunningHash: "1",
SequenceNumber: 1,
ChunkInfo: nil,
}
content := message.Messages{
Messages: []message.Message{expectedMsg},
}
encodedContent, err := httpHelper.EncodeBodyContent(content)
if err != nil {
t.Fatal(err)
}
mocks.MHTTPClient.On("Get", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedContent}, nil)

encodedResponseBuffer := new(bytes.Buffer)
encodeErr := json.NewEncoder(encodedResponseBuffer).Encode(testConstants.ParsedTransactionResponse)
response, err := c.GetLatestMessages(topicId, queryDefaultLimit)

assert.Equal(t, expectedMsg, response[0])
assert.Len(t, response, 1)
assert.Nil(t, err)
}

func Test_GetMessageBySequenceNumber(t *testing.T) {
setup()

expectedMsg := &message.Message{
ConsensusTimestamp: "1",
TopicId: "1",
Contents: "1",
RunningHash: "1",
SequenceNumber: sequenceNumber,
ChunkInfo: nil,
}
encodedContent, err := httpHelper.EncodeBodyContent(expectedMsg)
if err != nil {
t.Fatal(err)
}
mocks.MHTTPClient.On("Get", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedContent}, nil)

response, err := c.GetMessageBySequenceNumber(topicId, sequenceNumber)

assert.Equal(t, expectedMsg, response)
assert.Nil(t, err)
}

func Test_GetMessageBySequenceNumber_HttpErr(t *testing.T) {
setup()
expectedErr := errors.New("some error")
mocks.MHTTPClient.On("Get", mock.Anything).Return(nil, expectedErr)

response, err := c.GetMessageBySequenceNumber(topicId, sequenceNumber)

assert.Error(t, err, expectedErr)
assert.Nil(t, response)
}

func Test_GetMessageBySequenceNumber_JsonErr(t *testing.T) {
setup()
expectedErr := json.UnmarshalTypeError{
Value: "string",
}
encodedContent, err := httpHelper.EncodeBodyContent("invalid-content")
if err != nil {
t.Fatal(err)
}
mocks.MHTTPClient.On("Get", mock.Anything).Return(&http.Response{StatusCode: 200, Body: encodedContent}, nil)

response, err := c.GetMessageBySequenceNumber(topicId, sequenceNumber)

assert.Error(t, err, expectedErr)
assert.Nil(t, response)
}

func Test_GetHBARUsdPrice(t *testing.T) {
setup()
encodedResponseReaderCloser, encodeErr := httpHelper.EncodeBodyContent(testConstants.ParsedTransactionResponse)
if encodeErr != nil {
t.Fatal(encodeErr)
}
encodedResponseReader := bytes.NewReader(encodedResponseBuffer.Bytes())
encodedResponseReaderCloser := ioutil.NopCloser(encodedResponseReader)
response := &http.Response{
StatusCode: 200,
Body: encodedResponseReaderCloser,
Expand Down
24 changes: 19 additions & 5 deletions app/clients/hedera/mirror-node/model/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,27 @@
package message

type (
InitialTransactionId struct {
AccountId string `json:"account_id"`
Nonce uint64 `json:"nonce"`
Scheduled bool `json:"scheduled"`
TransactionValidStart string `json:"transaction_valid_start"`
}

ChunkInfo struct {
InitialTransactionId InitialTransactionId `json:"initial_transaction_id"`
Number int64 `json:"number"`
Total int64 `json:"total"`
}

// Message struct used by the Hedera Mirror node REST API to represent Topic Message
Message struct {
ConsensusTimestamp string `json:"consensus_timestamp"`
TopicId string `json:"topic_id"`
Contents string `json:"message"`
RunningHash string `json:"running_hash"`
SequenceNumber int `json:"sequence_number"`
ConsensusTimestamp string `json:"consensus_timestamp"`
TopicId string `json:"topic_id"`
Contents string `json:"message"`
RunningHash string `json:"running_hash"`
SequenceNumber int64 `json:"sequence_number"`
ChunkInfo *ChunkInfo `json:"chunk_info"`
}
// Messages struct used by the Hedera Mirror node REST API and returned once
// Topic Messages are queried
Expand Down
10 changes: 9 additions & 1 deletion app/domain/client/mirror-node.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ type MirrorNode interface {
// GetAccountCreditTransactionsBetween returns all incoming Transfers for the specified account between timestamp `from` and `to` excluded
GetAccountCreditTransactionsBetween(accountId hedera.AccountID, from, to int64) ([]transaction.Transaction, error)
// GetMessagesAfterTimestamp returns all topic messages after the given timestamp
GetMessagesAfterTimestamp(topicId hedera.TopicID, from int64) ([]message.Message, error)
GetMessagesAfterTimestamp(topicId hedera.TopicID, from int64, limit int64) ([]message.Message, error)
// GetMessageBySequenceNumber returns message from given topic with provided sequence number
GetMessageBySequenceNumber(topicId hedera.TopicID, sequenceNumber int64) (*message.Message, error)
// GetLatestMessages returns latest Topic messages
GetLatestMessages(topicId hedera.TopicID, limit int64) ([]message.Message, error)
// GetMessagesForTopicBetween returns all topic messages for a given topic between timestamp `from` included and `to` excluded
GetMessagesForTopicBetween(topicId hedera.TopicID, from, to int64) ([]message.Message, error)
// GetNftTransactions returns the nft transactions for tokenID and serialNum
Expand Down Expand Up @@ -77,4 +81,8 @@ type MirrorNode interface {
WaitForScheduledTransaction(txId string, onSuccess, onFailure func())
// GetHBARUsdPrice Returns USD price for HBAR
GetHBARUsdPrice() (price decimal.Decimal, err error)
// QueryDefaultLimit returns the default records limit per query
QueryDefaultLimit() int64
// QueryMaxLimit returns the maximum allowed records limit per query
QueryMaxLimit() int64
}
Loading

0 comments on commit 84b7c8a

Please sign in to comment.