Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 28 additions & 115 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,25 @@ jobs:
outputs:
IMAGE_TAG: ${{ steps.ct_image_tag.outputs.IMAGE_TAG }}
IMAGE_PATH_0: ghcr.io/${{ github.repository }}
ROSETTA_BRANCH: ${{ steps.ct_image_tag.outputs.ROSETTA_BRANCH }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- id: ct_image_tag
run: |
TAG_NORMALIZED=$(echo ${GITHUB_REF#refs/*/} | sed "s/[^[:alpha:]0-9.-]/-/g")
# For pull requests, use GITHUB_HEAD_REF (source branch of PR)
# For push events, extract branch name from GITHUB_REF
if [ -n "$GITHUB_HEAD_REF" ]; then
BRANCH_NAME=$GITHUB_HEAD_REF
else
BRANCH_NAME=${GITHUB_REF#refs/*/}
fi
TAG_NORMALIZED=$(echo "$BRANCH_NAME" | sed "s/[^[:alpha:]0-9.-]/-/g")
if [[ "$TAG_NORMALIZED" == "main" ]]; then echo "IMAGE_TAG=latest" >> $GITHUB_OUTPUT
else echo "IMAGE_TAG=$TAG_NORMALIZED" >> $GITHUB_OUTPUT
fi
echo "ROSETTA_BRANCH=$BRANCH_NAME" >> $GITHUB_OUTPUT

build-container:
runs-on: ubuntu-latest
Expand All @@ -49,7 +58,7 @@ jobs:
- name: Build and push container image
shell: bash
run: |
docker build --progress=plain --no-cache --build-arg ROSETTA_SRC=. --tag ${{ needs.define-env.outputs.IMAGE_PATH_0 }}:${{ needs.define-env.outputs.IMAGE_TAG }} -f ./server/Dockerfile .
docker build --progress=plain --no-cache --build-arg ROSETTA_SRC=. --build-arg ROSETTA_BRANCH=${{ needs.define-env.outputs.ROSETTA_BRANCH }} --tag ${{ needs.define-env.outputs.IMAGE_PATH_0 }}:${{ needs.define-env.outputs.IMAGE_TAG }} -f ./server/Dockerfile .
docker push ${{ needs.define-env.outputs.IMAGE_PATH_0 }}:${{ needs.define-env.outputs.IMAGE_TAG }}
- name: get image sha256
id: image_sha256
Expand All @@ -58,135 +67,39 @@ jobs:
export IMAGE_SHA256_0_FULL=$(docker image inspect --format='{{json .RepoDigests}}' ${{ needs.define-env.outputs.IMAGE_PATH_0 }}:${{ needs.define-env.outputs.IMAGE_TAG }} | jq --raw-output '.[0]')
echo "IMAGE_SHA256_0=${IMAGE_SHA256_0_FULL#*@}" >> $GITHUB_OUTPUT


test-container-localflare-online:
test-localflare:
runs-on: ubuntu-latest
needs:
- build-container
- define-env
strategy:
fail-fast: false
matrix:
index: [1, 2, 3, 4, 5]
START_ROSETTA_SERVER_AFTER_BOOTSTRAP: [true, false]
services:
flare_node:
image: ${{ needs.define-env.outputs.IMAGE_PATH_0 }}@${{ needs.build-container.outputs.IMAGE_SHA256_0 }}
ports:
- 9650:9650
- 9651:9651
- 8080:8080
env:
DEBUG: true
NETWORK_ID: localflare
FLARE_LOCAL_TXS_ENABLED: true
START_ROSETTA_SERVER_AFTER_BOOTSTRAP: ${{ matrix.START_ROSETTA_SERVER_AFTER_BOOTSTRAP }}
EXTRA_ARGUMENTS: --staking-tls-cert-file=/app/flare/staking/local/staker1.crt --staking-tls-key-file=/app/flare/staking/local/staker1.key
options: >-
--health-interval 15s
--health-timeout 15s
--health-retries 10
--health-start-period 30s
steps:
- uses: actions/checkout@v3

- uses: actions/setup-go@v3
with:
go-version: ${{ env.go_version }}
- run: sudo apt update -y && sudo apt install curl -y

- name: Wait for go-flare to bind to port
shell: bash
run: curl -s --retry 6 --retry-delay 10 --retry-connrefused http://localhost:9650 || exit 1

- name: Import testnet
shell: bash
run: |
curl -s -o /tmp/test_pchain_import.sh https://raw.githubusercontent.com/flare-foundation/go-flare/114017731f4f8f6192a4df2748da914c0257e16b/avalanchego/scripts/test_pchain_import.sh
sed -i 's/localhost/127.0.0.1/g' /tmp/test_pchain_import.sh
sed -i 's/ | jq .//g' /tmp/test_pchain_import.sh
bash /tmp/test_pchain_import.sh
while [[ "$(curl -X POST --data '{ "jsonrpc": "2.0", "method": "platform.getHeight", "params": {}, "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P | jq -r .result.height)" != "2" ]]
do
echo "Block height not reached.. Block Height:" $(curl -X POST --data '{ "jsonrpc": "2.0", "method": "platform.getHeight", "params": {}, "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/P | jq -r .result.height)
sleep 1
done
- name: Wait for rosetta to bind to port
shell: bash
run: curl -s --retry 6 --retry-delay 10 --retry-connrefused http://localhost:8080 || exit 1

- name: List networks Rosetta API lists
shell: bash
run: |
curl -s --location --request POST 'http://127.0.0.1:8080/network/list' \
--header 'Content-Type: application/json' \
--data-raw '{ "metadata" : {} }' \
--fail || exit 1
- name: Install rosetta cli
shell: bash
run: |
mkdir -p /tmp/rosetta
curl -o /tmp/rosetta/install.sh -sSfL https://raw.githubusercontent.com/coinbase/mesh-cli/refs/tags/v0.10.4/scripts/install.sh
sed -i 's/REPO="rosetta-cli"/REPO="mesh-cli"/g' /tmp/rosetta/install.sh
bash /tmp/rosetta/install.sh -b /tmp/rosetta/ v0.10.4
- name: Run rosetta-cli check:construction
timeout-minutes: 5
shell: bash
run: |
pushd server/rosetta-cli-conf/localflare
/tmp/rosetta/rosetta-cli --configuration-file=./config.json check:construction
popd

- name: Set up Docker Compose
uses: docker/setup-compose-action@v1


test-container-localflare-offline:
runs-on: ubuntu-latest
needs:
- build-container
- define-env
strategy:
fail-fast: false
matrix:
index: [1, 2, 3, 4, 5]
services:
flare_node:
image: ${{ needs.define-env.outputs.IMAGE_PATH_0 }}@${{ needs.build-container.outputs.IMAGE_SHA256_0 }}
ports:
- 9650:9650
- 9651:9651
- 8080:8080
env:
DEBUG: true
NETWORK_ID: localflare
FLARE_LOCAL_TXS_ENABLED: true
MODE: offline
EXTRA_ARGUMENTS: --staking-tls-cert-file=/app/flare/staking/local/staker1.crt --staking-tls-key-file=/app/flare/staking/local/staker1.key
options: >-
--health-interval 15s
--health-timeout 15s
--health-retries 10
--health-start-period 30s
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
- uses: actions/setup-node@v6
with:
go-version: ${{ env.go_version }}
- run: sudo apt update -y && sudo apt install curl -y
node-version: 20

- name: Wait for rosetta to bind to port
shell: bash
run: curl -s --retry 6 --retry-delay 10 --retry-connrefused http://localhost:8080 || exit 1
- run: sudo apt update -y && sudo apt install curl jq -y

- name: List networks Rosetta API lists
- name: Install yarn
run: npm install -g yarn

- name: Run localflare test script
env:
CI: true
ROSETTA_IMAGE: ${{ needs.define-env.outputs.IMAGE_PATH_0 }}@${{ needs.build-container.outputs.IMAGE_SHA256_0 }}
START_ROSETTA_SERVER_AFTER_BOOTSTRAP: true
MODE: online
shell: bash
run: |
curl -s --location --request POST 'http://127.0.0.1:8080/network/list' \
--header 'Content-Type: application/json' \
--data-raw '{ "metadata" : {} }' \
--fail || exit 1




./test-localflare.sh

test-make_build:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ data
__debug_bin*
build_docker.sh
.idea
tmp/
7 changes: 4 additions & 3 deletions server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ FROM golang:1.22 AS flare

WORKDIR /app

ARG GO_FLARE_VERSION=v1.11.0
ARG GO_FLARE_VERSION=v1.11.13-rc0
ARG GO_FLARE_REPO=https://github.com/flare-foundation/go-flare

RUN git clone --branch "$GO_FLARE_VERSION" "${GO_FLARE_REPO}" .
Expand All @@ -20,8 +20,9 @@ RUN cd avalanchego && \
# ------------------------------------------------------------------------------
FROM golang:1.22 AS rosetta

ARG ROSETTA_SRC=https://github.com/flare-foundation/flare-rosetta/archive/refs/heads/main.zip
ARG ROSETTA_SRC_ZIP_SUBFOLDER=flare-rosetta-main
ARG ROSETTA_BRANCH=main
ARG ROSETTA_SRC=https://github.com/flare-foundation/flare-rosetta/archive/refs/heads/${ROSETTA_BRANCH}.zip
ARG ROSETTA_SRC_ZIP_SUBFOLDER=flare-rosetta-${ROSETTA_BRANCH}

WORKDIR /tmp

Expand Down
85 changes: 27 additions & 58 deletions server/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,54 @@ package client

import (
"context"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/peer"
"github.com/ava-labs/avalanchego/utils/json"
"math/big"
"strings"

"github.com/ava-labs/avalanchego/api/info"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/rpc"
ethtypes "github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/interfaces"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ava-labs/coreth/plugin/evm"
"github.com/ethereum/go-ethereum/common"

"github.com/ava-labs/avalanche-rosetta/constants"
)

// Interface compliance
var _ Client = &client{}

type Client interface {
IsBootstrapped(context.Context, string, ...rpc.Option) (bool, error)
// info.Client methods
InfoClient

ChainID(context.Context) (*big.Int, error)
BlockByHash(context.Context, ethcommon.Hash) (*ethtypes.Block, error)
BlockByNumber(context.Context, *big.Int) (*ethtypes.Block, error)
HeaderByHash(context.Context, ethcommon.Hash) (*ethtypes.Header, error)
HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error)
TransactionByHash(context.Context, ethcommon.Hash) (*ethtypes.Transaction, bool, error)
TransactionReceipt(context.Context, ethcommon.Hash) (*ethtypes.Receipt, error)
BlockByHash(context.Context, common.Hash) (*types.Block, error)
BlockByNumber(context.Context, *big.Int) (*types.Block, error)
HeaderByHash(context.Context, common.Hash) (*types.Header, error)
HeaderByNumber(context.Context, *big.Int) (*types.Header, error)
TransactionByHash(context.Context, common.Hash) (*types.Transaction, bool, error)
TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error)
TraceTransaction(context.Context, string) (*Call, []*FlatCall, error)
TraceBlockByHash(context.Context, string) ([]*Call, [][]*FlatCall, error)
SendTransaction(context.Context, *ethtypes.Transaction) error
BalanceAt(context.Context, ethcommon.Address, *big.Int) (*big.Int, error)
NonceAt(context.Context, ethcommon.Address, *big.Int) (uint64, error)
SendTransaction(context.Context, *types.Transaction) error
BalanceAt(context.Context, common.Address, *big.Int) (*big.Int, error)
NonceAt(context.Context, common.Address, *big.Int) (uint64, error)
SuggestGasPrice(context.Context) (*big.Int, error)
EstimateGas(context.Context, interfaces.CallMsg) (uint64, error)
TxPoolContent(context.Context) (*TxPoolContent, error)
GetNetworkName(context.Context, ...rpc.Option) (string, error)
Peers(context.Context, ...rpc.Option) ([]info.Peer, error)
// Peers_v1_11 enables info.peers RPC call compatible with v1.11.
// Once the dependencies are upgraded, this should be replaced with Peers.
Peers_v1_11(context.Context, []ids.NodeID, ...rpc.Option) ([]Peer_v1_11, error)
GetContractInfo(ethcommon.Address, bool) (string, uint8, error)
GetContractInfo(common.Address, bool) (string, uint8, error)
CallContract(context.Context, interfaces.CallMsg, *big.Int) ([]byte, error)
IssueTx(ctx context.Context, txBytes []byte, options ...rpc.Option) (ids.ID, error)
GetAtomicUTXOs(ctx context.Context, addrs []ids.ShortID, sourceChain string, limit uint32, startAddress ids.ShortID, startUTXOID ids.ID, options ...rpc.Option) ([][]byte, ids.ShortID, ids.ID, error)
EstimateBaseFee(ctx context.Context) (*big.Int, error)
}

type clientFix struct {
requester rpc.EndpointRequester
}

func newClientFix(uri string) *clientFix {
return &clientFix{
requester: rpc.NewEndpointRequester(
uri+"/ext/info",
"info",
),
}
}

type Peer_v1_11 struct {
peer.Info

Benched []string `json:"benched"`
}

type PeersReply_v1_11 struct {
// Number of elements in [Peers]
NumPeers json.Uint64 `json:"numPeers"`
// Each element is a peer
Peers []Peer_v1_11 `json:"peers"`
}

func (cf *clientFix) Peers_v1_11(ctx context.Context, nodeIDs []ids.NodeID, options ...rpc.Option) ([]Peer_v1_11, error) {
res := &PeersReply_v1_11{}
err := cf.requester.SendRequest(ctx, "peers", &info.PeersArgs{
NodeIDs: nodeIDs,
}, res, options...)
return res.Peers, err
}
type EvmClient evm.Client

type client struct {
info.Client
*clientFix
EvmClient
*EthClient
*ContractClient
}
Expand All @@ -94,10 +63,10 @@ func NewClient(ctx context.Context, endpoint string) (Client, error) {
return nil, err
}

return client{
return &client{
Client: info.NewClient(endpoint),
clientFix: newClientFix(endpoint),
EvmClient: evm.NewClient(endpoint, constants.CChain.String()),
EthClient: eth,
ContractClient: NewContractClient(eth.Client),
}, nil
}
}
17 changes: 8 additions & 9 deletions server/client/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,28 @@ const (
// ContractClient is a client for the calling contract information
type ContractClient struct {
ethClient ethclient.Client
cache *cache.LRU
cache *cache.LRU[common.Address, *ContractInfo]
}

type ContractInfo struct {
Symbol string
Decimals uint8
}

// NewContractClient returns a new ContractInfo client
func NewContractClient(c ethclient.Client) *ContractClient {
return &ContractClient{
ethClient: c,
cache: &cache.LRU{Size: contractCacheSize},
cache: &cache.LRU[common.Address, *ContractInfo]{Size: contractCacheSize},
}
}

// GetContractInfo returns the symbol and decimals for [addr].
func (c *ContractClient) GetContractInfo(addr common.Address, erc20 bool) (string, uint8, error) {
// We don't define another struct because this is never used outside of this
// function.
type ContractInfo struct {
Symbol string
Decimals uint8
}

if currency, cached := c.cache.Get(addr); cached {
cast := currency.(*ContractInfo)
return cast.Symbol, cast.Decimals, nil
return currency.Symbol, currency.Decimals, nil
}

token, err := NewContractInfoToken(addr, c.ethClient)
Expand Down
3 changes: 1 addition & 2 deletions server/client/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package client

import (
"context"
"fmt"

"github.com/ava-labs/coreth/eth/tracers"
"github.com/ava-labs/coreth/ethclient"
Expand All @@ -24,7 +23,7 @@ type EthClient struct {

// NewEthClient returns a new EVM client
func NewEthClient(ctx context.Context, endpoint string) (*EthClient, error) {
endpointURL := fmt.Sprintf("%s%s", endpoint, prefixEth)
endpointURL := endpoint + prefixEth

c, err := rpc.DialContext(ctx, endpointURL)
if err != nil {
Expand Down
Loading