[WIP] Add a service to fill indexing gap for watched addresses #135
31
.github/workflows/on-pr.yaml
vendored
31
.github/workflows/on-pr.yaml
vendored
@ -91,3 +91,34 @@ jobs:
|
|||||||
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
|
||||||
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
|
||||||
make integrationtest
|
make integrationtest
|
||||||
|
|
||||||
|
integrationtest_watchedaddress_gapfillingservice:
|
||||||
|
name: Run integration tests for watched addresses with gap filling service enabled
|
||||||
|
env:
|
||||||
|
GOPATH: /tmp/go
|
||||||
|
DB_WRITE: true
|
||||||
|
ETH_FORWARD_ETH_CALLS: false
|
||||||
|
ETH_PROXY_ON_ERROR: false
|
||||||
|
ETH_HTTP_PATH: ""
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED: true
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL: 2
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.16.x]
|
||||||
|
os: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Create GOPATH
|
||||||
|
run: mkdir -p /tmp/go
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Run database
|
||||||
|
run: docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
|
||||||
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
|
||||||
|
make integrationtest
|
||||||
|
1
Makefile
1
Makefile
@ -77,6 +77,7 @@ integrationtest_local: | $(GINKGO) $(GOOSE)
|
|||||||
go fmt ./...
|
go fmt ./...
|
||||||
./scripts/run_integration_test.sh
|
./scripts/run_integration_test.sh
|
||||||
./scripts/run_integration_test_forward_eth_calls.sh
|
./scripts/run_integration_test_forward_eth_calls.sh
|
||||||
|
./scripts/run_integration_test_watched_address_gap_filler.sh
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
|
19
cmd/serve.go
19
cmd/serve.go
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/vulcanize/gap-filler/pkg/mux"
|
"github.com/vulcanize/gap-filler/pkg/mux"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
|
fill "github.com/vulcanize/ipld-eth-server/pkg/fill"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/graphql"
|
"github.com/vulcanize/ipld-eth-server/pkg/graphql"
|
||||||
srpc "github.com/vulcanize/ipld-eth-server/pkg/rpc"
|
srpc "github.com/vulcanize/ipld-eth-server/pkg/rpc"
|
||||||
s "github.com/vulcanize/ipld-eth-server/pkg/serve"
|
s "github.com/vulcanize/ipld-eth-server/pkg/serve"
|
||||||
@ -100,6 +101,14 @@ func serve() {
|
|||||||
logWithCommand.Info("state validator disabled")
|
logWithCommand.Info("state validator disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if serverConfig.WatchedAddressGapFillerEnabled {
|
||||||
|
service := fill.New(serverConfig)
|
||||||
|
go service.Start()
|
||||||
|
logWithCommand.Info("watched address gap filler enabled")
|
||||||
|
} else {
|
||||||
|
logWithCommand.Info("watched address gap filler disabled")
|
||||||
|
}
|
||||||
|
|
||||||
shutdown := make(chan os.Signal, 1)
|
shutdown := make(chan os.Signal, 1)
|
||||||
signal.Notify(shutdown, os.Interrupt)
|
signal.Notify(shutdown, os.Interrupt)
|
||||||
<-shutdown
|
<-shutdown
|
||||||
@ -133,7 +142,7 @@ func startServers(server s.Server, settings *s.Config) error {
|
|||||||
|
|
||||||
if settings.HTTPEnabled {
|
if settings.HTTPEnabled {
|
||||||
logWithCommand.Info("starting up HTTP server")
|
logWithCommand.Info("starting up HTTP server")
|
||||||
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"eth", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
|
_, err := srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"vdb", "eth", "net"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -360,6 +369,10 @@ func init() {
|
|||||||
serveCmd.PersistentFlags().Bool("validator-enabled", false, "turn on the state validator")
|
serveCmd.PersistentFlags().Bool("validator-enabled", false, "turn on the state validator")
|
||||||
serveCmd.PersistentFlags().Uint("validator-every-nth-block", 1500, "only validate every Nth block")
|
serveCmd.PersistentFlags().Uint("validator-every-nth-block", 1500, "only validate every Nth block")
|
||||||
|
|
||||||
|
// watched address gap filler flags
|
||||||
|
serveCmd.PersistentFlags().Bool("watched-address-gap-filler-enabled", false, "turn on the watched address gap filler")
|
||||||
|
serveCmd.PersistentFlags().Int("watched-address-gap-filler-interval", 60, "watched address gap fill interval in secs")
|
||||||
|
|
||||||
// and their bindings
|
// and their bindings
|
||||||
// eth graphql server
|
// eth graphql server
|
||||||
viper.BindPFlag("eth.server.graphql", serveCmd.PersistentFlags().Lookup("eth-server-graphql"))
|
viper.BindPFlag("eth.server.graphql", serveCmd.PersistentFlags().Lookup("eth-server-graphql"))
|
||||||
@ -408,4 +421,8 @@ func init() {
|
|||||||
// state validator flags
|
// state validator flags
|
||||||
viper.BindPFlag("validator.enabled", serveCmd.PersistentFlags().Lookup("validator-enabled"))
|
viper.BindPFlag("validator.enabled", serveCmd.PersistentFlags().Lookup("validator-enabled"))
|
||||||
viper.BindPFlag("validator.everyNthBlock", serveCmd.PersistentFlags().Lookup("validator-every-nth-block"))
|
viper.BindPFlag("validator.everyNthBlock", serveCmd.PersistentFlags().Lookup("validator-every-nth-block"))
|
||||||
|
|
||||||
|
// watched address gap filler flags
|
||||||
|
viper.BindPFlag("watch.fill.enabled", serveCmd.PersistentFlags().Lookup("watched-address-gap-filler-enabled"))
|
||||||
|
viper.BindPFlag("watch.fill.interval", serveCmd.PersistentFlags().Lookup("watched-address-gap-filler-interval"))
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package eth_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -32,7 +31,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer"
|
"github.com/ethereum/go-ethereum/statediff/indexer"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/node"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@ -40,6 +38,7 @@ import (
|
|||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -183,19 +182,6 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupDB is use to setup a db for watcher tests
|
|
||||||
func SetupDB() (*postgres.DB, error) {
|
|
||||||
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
|
|
||||||
uri := postgres.DbConnectionString(postgres.ConnectionParams{
|
|
||||||
User: os.Getenv("DATABASE_USER"),
|
|
||||||
Password: os.Getenv("DATABASE_PASSWORD"),
|
|
||||||
Hostname: os.Getenv("DATABASE_HOSTNAME"),
|
|
||||||
Name: os.Getenv("DATABASE_NAME"),
|
|
||||||
Port: port,
|
|
||||||
})
|
|
||||||
return postgres.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Describe("API", func() {
|
var _ = Describe("API", func() {
|
||||||
var (
|
var (
|
||||||
db *postgres.DB
|
db *postgres.DB
|
||||||
@ -210,7 +196,7 @@ var _ = Describe("API", func() {
|
|||||||
tx *indexer.BlockTx
|
tx *indexer.BlockTx
|
||||||
)
|
)
|
||||||
|
|
||||||
db, err = SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
indexAndPublisher, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
indexAndPublisher, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
||||||
@ -269,7 +255,7 @@ var _ = Describe("API", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Single test db tear down at end of all tests
|
// Single test db tear down at end of all tests
|
||||||
defer It("test teardown", func() { eth.TearDownDB(db) })
|
defer It("test teardown", func() { shared.TearDownDB(db) })
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Headers and blocks
|
Headers and blocks
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -217,7 +218,7 @@ var _ = Describe("Retriever", func() {
|
|||||||
)
|
)
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
var err error
|
var err error
|
||||||
db, err = SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
diffIndexer, err = indexer.NewStateDiffIndexer(params.TestChainConfig, db)
|
diffIndexer, err = indexer.NewStateDiffIndexer(params.TestChainConfig, db)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -225,7 +226,7 @@ var _ = Describe("Retriever", func() {
|
|||||||
retriever = eth.NewCIDRetriever(db)
|
retriever = eth.NewCIDRetriever(db)
|
||||||
})
|
})
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
eth.TearDownDB(db)
|
shared.TearDownDB(db)
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Retrieve", func() {
|
Describe("Retrieve", func() {
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
It("test init", func() {
|
It("test init", func() {
|
||||||
// db and type initializations
|
// db and type initializations
|
||||||
var err error
|
var err error
|
||||||
db, err = SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
transformer, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
transformer, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
||||||
@ -183,7 +184,7 @@ var _ = Describe("eth state reading tests", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
defer It("test teardown", func() {
|
defer It("test teardown", func() {
|
||||||
eth.TearDownDB(db)
|
shared.TearDownDB(db)
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("IPLDFetcher", func() {
|
var _ = Describe("IPLDFetcher", func() {
|
||||||
@ -39,7 +40,7 @@ var _ = Describe("IPLDFetcher", func() {
|
|||||||
err error
|
err error
|
||||||
tx *indexer.BlockTx
|
tx *indexer.BlockTx
|
||||||
)
|
)
|
||||||
db, err = SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
pubAndIndexer, err = indexer.NewStateDiffIndexer(params.TestChainConfig, db)
|
pubAndIndexer, err = indexer.NewStateDiffIndexer(params.TestChainConfig, db)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -56,7 +57,7 @@ var _ = Describe("IPLDFetcher", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
eth.TearDownDB(db)
|
shared.TearDownDB(db)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Fetches and returns IPLDs for the CIDs provided in the CIDWrapper", func() {
|
It("Fetches and returns IPLDs for the CIDs provided in the CIDWrapper", func() {
|
||||||
|
@ -16,35 +16,7 @@
|
|||||||
|
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import "github.com/ethereum/go-ethereum/statediff/indexer/models"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/models"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TearDownDB is used to tear down the watcher dbs after tests
|
|
||||||
func TearDownDB(db *postgres.DB) {
|
|
||||||
tx, err := db.Beginx()
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.state_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM blocks`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
|
|
||||||
err = tx.Commit()
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TxModelsContainsCID used to check if a list of TxModels contains a specific cid string
|
// TxModelsContainsCID used to check if a list of TxModels contains a specific cid string
|
||||||
func TxModelsContainsCID(txs []models.TxModel, cid string) bool {
|
func TxModelsContainsCID(txs []models.TxModel, cid string) bool {
|
||||||
|
29
pkg/fill/fill_suite_test.go
Normal file
29
pkg/fill/fill_suite_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 Vulcanize
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package fill_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFill(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "ipld eth server fill test suite")
|
||||||
|
}
|
185
pkg/fill/service.go
Normal file
185
pkg/fill/service.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 Vulcanize
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package fill
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/serve"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WatchedAddress type is used to process currently watched addresses
|
||||||
|
type WatchedAddress struct {
|
||||||
|
Address string `db:"address"`
|
||||||
|
CreatedAt uint64 `db:"created_at"`
|
||||||
|
WatchedAt uint64 `db:"watched_at"`
|
||||||
|
LastFilledAt uint64 `db:"last_filled_at"`
|
||||||
|
|
||||||
|
StartBlock uint64
|
||||||
|
EndBlock uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service is the underlying struct for the watched address gap filling service
|
||||||
|
type Service struct {
|
||||||
|
db *postgres.DB
|
||||||
|
client *rpc.Client
|
||||||
|
interval int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer creates a new Service
|
||||||
|
func New(config *serve.Config) *Service {
|
||||||
|
return &Service{
|
||||||
|
db: config.DB,
|
||||||
|
client: config.Client,
|
||||||
|
interval: config.WatchedAddressGapFillInterval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is used to begin the service
|
||||||
|
func (s *Service) Start() {
|
||||||
|
for {
|
||||||
|
// Wait for specified interval duration
|
||||||
|
time.Sleep(time.Duration(s.interval) * time.Second)
|
||||||
|
|
||||||
|
// Get watched addresses from the db
|
||||||
|
rows := s.fetchWatchedAddresses()
|
||||||
|
|
||||||
|
// Get the block number to start fill at
|
||||||
|
// Get the block number to end fill at
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := s.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
if len(fillWatchedAddresses) > 0 {
|
||||||
|
log.Infof("running watched address gap filler for block range: (%d, %d)", minStartBlock, maxEndBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the missing diffs
|
||||||
|
for blockNumber := minStartBlock; blockNumber <= maxEndBlock; blockNumber++ {
|
||||||
|
params := statediff.Params{
|
||||||
|
IntermediateStateNodes: true,
|
||||||
|
IntermediateStorageNodes: true,
|
||||||
|
IncludeBlock: true,
|
||||||
|
IncludeReceipts: true,
|
||||||
|
IncludeTD: true,
|
||||||
|
IncludeCode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
fillAddresses := []interface{}{}
|
||||||
|
for _, fillWatchedAddress := range fillWatchedAddresses {
|
||||||
|
if blockNumber >= fillWatchedAddress.StartBlock && blockNumber <= fillWatchedAddress.EndBlock {
|
||||||
|
params.WatchedAddresses = append(params.WatchedAddresses, common.HexToAddress(fillWatchedAddress.Address))
|
||||||
|
fillAddresses = append(fillAddresses, fillWatchedAddress.Address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fillAddresses) > 0 {
|
||||||
|
s.writeStateDiffAt(blockNumber, params)
|
||||||
|
s.UpdateLastFilledAt(blockNumber, fillAddresses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFillAddresses finds the encompassing range to perform fill for the given watched addresses
|
||||||
|
// it also sets the address specific fill range
|
||||||
|
func (s *Service) GetFillAddresses(rows []WatchedAddress) ([]WatchedAddress, uint64, uint64) {
|
||||||
|
fillWatchedAddresses := []WatchedAddress{}
|
||||||
|
minStartBlock := uint64(math.MaxUint64)
|
||||||
|
maxEndBlock := uint64(0)
|
||||||
|
|
||||||
|
for _, row := range rows {
|
||||||
|
// Check for a gap between created_at and watched_at
|
||||||
|
// CreatedAt and WatchedAt being equal is considered a gap of one block
|
||||||
|
if row.CreatedAt > row.WatchedAt {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
startBlock := uint64(0)
|
||||||
|
endBlock := uint64(0)
|
||||||
|
|
||||||
|
// Check if some of the gap was filled earlier
|
||||||
|
if row.LastFilledAt > 0 {
|
||||||
|
if row.LastFilledAt < row.WatchedAt {
|
||||||
|
startBlock = row.LastFilledAt + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startBlock = row.CreatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the address for filling
|
||||||
|
if startBlock > 0 {
|
||||||
|
row.StartBlock = startBlock
|
||||||
|
if startBlock < minStartBlock {
|
||||||
|
minStartBlock = startBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
endBlock = row.WatchedAt
|
||||||
|
row.EndBlock = endBlock
|
||||||
|
if endBlock > maxEndBlock {
|
||||||
|
maxEndBlock = endBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
fillWatchedAddresses = append(fillWatchedAddresses, row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fillWatchedAddresses, minStartBlock, maxEndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLastFilledAt updates the fill status for the provided addresses in the db
|
||||||
|
func (s *Service) UpdateLastFilledAt(blockNumber uint64, fillAddresses []interface{}) {
|
||||||
|
// Prepare the query
|
||||||
|
query := "UPDATE eth_meta.watched_addresses SET last_filled_at=? WHERE address IN (?" + strings.Repeat(",?", len(fillAddresses)-1) + ")"
|
||||||
|
query = s.db.Rebind(query)
|
||||||
|
|
||||||
|
args := []interface{}{blockNumber}
|
||||||
|
args = append(args, fillAddresses...)
|
||||||
|
|
||||||
|
// Execute the update query
|
||||||
|
_, err := s.db.Exec(query, args...)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchWatchedAddresses fetches watched addresses from the db
|
||||||
|
func (s *Service) fetchWatchedAddresses() []WatchedAddress {
|
||||||
|
rows := []WatchedAddress{}
|
||||||
|
pgStr := "SELECT * FROM eth_meta.watched_addresses"
|
||||||
|
|
||||||
|
err := s.db.Select(&rows, pgStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error fetching watched addreesses: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeStateDiffAt makes a RPC call to writeout statediffs at a blocknumber with the given params
|
||||||
|
func (s *Service) writeStateDiffAt(blockNumber uint64, params statediff.Params) {
|
||||||
|
err := s.client.Call(nil, "statediff_writeStateDiffAt", blockNumber, params)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error making a RPC call to write statediff at block number %d: %s", blockNumber, err.Error())
|
||||||
|
}
|
||||||
|
}
|
405
pkg/fill/service_test.go
Normal file
405
pkg/fill/service_test.go
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
// VulcanizeDB
|
||||||
|
// Copyright © 2022 Vulcanize
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package fill_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
|
||||||
|
fill "github.com/vulcanize/ipld-eth-server/pkg/fill"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/serve"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Service", func() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
db *postgres.DB
|
||||||
|
watchedAddressGapFiller *fill.Service
|
||||||
|
statediffIndexer *indexer.StateDiffIndexer
|
||||||
|
err error
|
||||||
|
|
||||||
|
contract1Address = "0x5d663F5269090bD2A7DC2390c911dF6083D7b28F"
|
||||||
|
contract2Address = "0x6Eb7e5C66DB8af2E96159AC440cbc8CDB7fbD26B"
|
||||||
|
contract3Address = "0xcfeB164C328CA13EFd3C77E1980d94975aDfedfc"
|
||||||
|
)
|
||||||
|
|
||||||
|
It("test init", func() {
|
||||||
|
// db initialization
|
||||||
|
db, err = shared.SetupDB()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// indexer initialization
|
||||||
|
statediffIndexer, err = indexer.NewStateDiffIndexer(nil, db)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// fill service intialization
|
||||||
|
watchedAddressGapFiller = fill.New(&serve.Config{
|
||||||
|
DB: db,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
defer It("test teardown", func() {
|
||||||
|
shared.TearDownDB(db)
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("GetFillAddresses", func() {
|
||||||
|
Context("overlapping fill ranges", func() {
|
||||||
|
It("gives the range to run fill for each address", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: 30,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 40,
|
||||||
|
EndBlock: 70,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: 30,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 20,
|
||||||
|
EndBlock: 30,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(70)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("non-overlapping fill ranges", func() {
|
||||||
|
It("gives the range to run fill for each address", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 70,
|
||||||
|
WatchedAt: 90,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 70,
|
||||||
|
WatchedAt: 90,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 70,
|
||||||
|
EndBlock: 90,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(90)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("a contract watched before it was created", func() {
|
||||||
|
It("gives no range for an address when it is watched before it's created", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 90,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(50)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("a contract having some of the gap filled earlier", func() {
|
||||||
|
It("gives the remaining range for an address to run fill for", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 50,
|
||||||
|
StartBlock: 51,
|
||||||
|
EndBlock: 70,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(70)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("gives no range for an address when the gap is already filled", func() {
|
||||||
|
// input data
|
||||||
|
rows := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 40,
|
||||||
|
WatchedAt: 70,
|
||||||
|
LastFilledAt: 70,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected output data
|
||||||
|
expectedOutputAddresses := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: 50,
|
||||||
|
LastFilledAt: 0,
|
||||||
|
StartBlock: 10,
|
||||||
|
EndBlock: 50,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedOutputStartBlock := uint64(10)
|
||||||
|
expectedOutputEndBlock := uint64(50)
|
||||||
|
|
||||||
|
fillWatchedAddresses, minStartBlock, maxEndBlock := watchedAddressGapFiller.GetFillAddresses(rows)
|
||||||
|
|
||||||
|
Expect(fillWatchedAddresses).To(Equal(expectedOutputAddresses))
|
||||||
|
Expect(minStartBlock).To(Equal(expectedOutputStartBlock))
|
||||||
|
Expect(maxEndBlock).To(Equal(expectedOutputEndBlock))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Describe("UpdateLastFilledAt", func() {
|
||||||
|
pgStr := "SELECT * FROM eth_meta.watched_addresses"
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
shared.TearDownDB(db)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("updates last filled at for a single address", func() {
|
||||||
|
// fill db with watched addresses
|
||||||
|
watchedAddresses := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
watchedAt := uint64(50)
|
||||||
|
err = statediffIndexer.InsertWatchedAddresses(watchedAddresses, big.NewInt(int64(watchedAt)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// update last filled at block in the db
|
||||||
|
fillAddresses := []interface{}{
|
||||||
|
contract1Address,
|
||||||
|
}
|
||||||
|
fillAt := uint64(12)
|
||||||
|
watchedAddressGapFiller.UpdateLastFilledAt(fillAt, fillAddresses)
|
||||||
|
|
||||||
|
// expected data
|
||||||
|
expectedData := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []fill.WatchedAddress{}
|
||||||
|
err = db.Select(&rows, pgStr)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(rows).To(Equal(expectedData))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("updates last filled at for multiple address", func() {
|
||||||
|
// fill db with watched addresses
|
||||||
|
watchedAddresses := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 30,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
watchedAt := uint64(50)
|
||||||
|
err = statediffIndexer.InsertWatchedAddresses(watchedAddresses, big.NewInt(int64(watchedAt)))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// update last filled at block in the db
|
||||||
|
fillAddresses := []interface{}{
|
||||||
|
contract1Address,
|
||||||
|
contract2Address,
|
||||||
|
contract3Address,
|
||||||
|
}
|
||||||
|
fillAt := uint64(50)
|
||||||
|
watchedAddressGapFiller.UpdateLastFilledAt(fillAt, fillAddresses)
|
||||||
|
|
||||||
|
// expected data
|
||||||
|
expectedData := []fill.WatchedAddress{
|
||||||
|
{
|
||||||
|
Address: contract1Address,
|
||||||
|
CreatedAt: 10,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract2Address,
|
||||||
|
CreatedAt: 20,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3Address,
|
||||||
|
CreatedAt: 30,
|
||||||
|
WatchedAt: watchedAt,
|
||||||
|
LastFilledAt: fillAt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := []fill.WatchedAddress{}
|
||||||
|
err = db.Select(&rows, pgStr)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(rows).To(Equal(expectedData))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -20,8 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
@ -33,7 +31,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer"
|
"github.com/ethereum/go-ethereum/statediff/indexer"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/node"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@ -42,22 +39,10 @@ import (
|
|||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth/test_helpers"
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/graphql"
|
"github.com/vulcanize/ipld-eth-server/pkg/graphql"
|
||||||
|
"github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
ethServerShared "github.com/vulcanize/ipld-eth-server/pkg/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupDB is use to setup a db for watcher tests
|
|
||||||
func SetupDB() (*postgres.DB, error) {
|
|
||||||
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
|
|
||||||
uri := postgres.DbConnectionString(postgres.ConnectionParams{
|
|
||||||
User: os.Getenv("DATABASE_USER"),
|
|
||||||
Password: os.Getenv("DATABASE_PASSWORD"),
|
|
||||||
Hostname: os.Getenv("DATABASE_HOSTNAME"),
|
|
||||||
Name: os.Getenv("DATABASE_NAME"),
|
|
||||||
Port: port,
|
|
||||||
})
|
|
||||||
return postgres.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Describe("GraphQL", func() {
|
var _ = Describe("GraphQL", func() {
|
||||||
const (
|
const (
|
||||||
gqlEndPoint = "127.0.0.1:8083"
|
gqlEndPoint = "127.0.0.1:8083"
|
||||||
@ -82,7 +67,7 @@ var _ = Describe("GraphQL", func() {
|
|||||||
|
|
||||||
It("test init", func() {
|
It("test init", func() {
|
||||||
var err error
|
var err error
|
||||||
db, err = SetupDB()
|
db, err = shared.SetupDB()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
transformer, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
transformer, err := indexer.NewStateDiffIndexer(chainConfig, db)
|
||||||
@ -186,7 +171,7 @@ var _ = Describe("GraphQL", func() {
|
|||||||
defer It("test teardown", func() {
|
defer It("test teardown", func() {
|
||||||
err := graphQLServer.Stop()
|
err := graphQLServer.Stop()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
eth.TearDownDB(db)
|
shared.TearDownDB(db)
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -20,7 +20,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/shared"
|
"github.com/ethereum/go-ethereum/statediff/indexer/shared"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
"github.com/vulcanize/ipld-eth-server/pkg/eth"
|
||||||
@ -34,13 +36,15 @@ const APIVersion = "0.0.1"
|
|||||||
|
|
||||||
// PublicServerAPI is the public api for the watcher
|
// PublicServerAPI is the public api for the watcher
|
||||||
type PublicServerAPI struct {
|
type PublicServerAPI struct {
|
||||||
w Server
|
w Server
|
||||||
|
rpc *rpc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPublicServerAPI creates a new PublicServerAPI with the provided underlying Server process
|
// NewPublicServerAPI creates a new PublicServerAPI with the provided underlying Server process
|
||||||
func NewPublicServerAPI(w Server) *PublicServerAPI {
|
func NewPublicServerAPI(w Server, client *rpc.Client) *PublicServerAPI {
|
||||||
return &PublicServerAPI{
|
return &PublicServerAPI{
|
||||||
w: w,
|
w: w,
|
||||||
|
rpc: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,3 +91,13 @@ func (api *PublicServerAPI) Stream(ctx context.Context, params eth.SubscriptionS
|
|||||||
func (api *PublicServerAPI) Chain() shared.ChainType {
|
func (api *PublicServerAPI) Chain() shared.ChainType {
|
||||||
return shared.Ethereum
|
return shared.Ethereum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WatchAddress makes a geth WatchAddress API call with the given operation and args
|
||||||
|
func (api *PublicServerAPI) WatchAddress(operation statediff.OperationType, args []sdtypes.WatchAddressArg) error {
|
||||||
|
err := api.rpc.Call(nil, "statediff_watchAddress", operation, args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -53,6 +53,9 @@ const (
|
|||||||
|
|
||||||
VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
|
VALIDATOR_ENABLED = "VALIDATOR_ENABLED"
|
||||||
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
|
VALIDATOR_EVERY_NTH_BLOCK = "VALIDATOR_EVERY_NTH_BLOCK"
|
||||||
|
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_ENABLED = "WATCHED_ADDRESS_GAP_FILLER_ENABLED"
|
||||||
|
WATCHED_ADDRESS_GAP_FILLER_INTERVAL = "WATCHED_ADDRESS_GAP_FILLER_INTERVAL"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct
|
// Config struct
|
||||||
@ -93,6 +96,9 @@ type Config struct {
|
|||||||
|
|
||||||
StateValidationEnabled bool
|
StateValidationEnabled bool
|
||||||
StateValidationEveryNthBlock uint64
|
StateValidationEveryNthBlock uint64
|
||||||
|
|
||||||
|
WatchedAddressGapFillerEnabled bool
|
||||||
|
WatchedAddressGapFillInterval int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig is used to initialize a watcher config from a .toml file
|
// NewConfig is used to initialize a watcher config from a .toml file
|
||||||
@ -228,6 +234,8 @@ func NewConfig() (*Config, error) {
|
|||||||
|
|
||||||
c.loadValidatorConfig()
|
c.loadValidatorConfig()
|
||||||
|
|
||||||
|
c.loadWatchedAddressGapFillerConfig()
|
||||||
|
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,3 +298,11 @@ func (c *Config) loadValidatorConfig() {
|
|||||||
c.StateValidationEnabled = viper.GetBool("validator.enabled")
|
c.StateValidationEnabled = viper.GetBool("validator.enabled")
|
||||||
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")
|
c.StateValidationEveryNthBlock = viper.GetUint64("validator.everyNthBlock")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) loadWatchedAddressGapFillerConfig() {
|
||||||
|
viper.BindEnv("watch.fill.enabled", WATCHED_ADDRESS_GAP_FILLER_ENABLED)
|
||||||
|
viper.BindEnv("watch.fill.interval", WATCHED_ADDRESS_GAP_FILLER_INTERVAL)
|
||||||
|
|
||||||
|
c.WatchedAddressGapFillerEnabled = viper.GetBool("watch.fill.enabled")
|
||||||
|
c.WatchedAddressGapFillInterval = viper.GetInt("watch.fill.interval")
|
||||||
|
}
|
||||||
|
@ -126,7 +126,7 @@ func (sap *Service) APIs() []rpc.API {
|
|||||||
{
|
{
|
||||||
Namespace: APIName,
|
Namespace: APIName,
|
||||||
Version: APIVersion,
|
Version: APIVersion,
|
||||||
Service: NewPublicServerAPI(sap),
|
Service: NewPublicServerAPI(sap, sap.client),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -18,8 +18,14 @@ package shared
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/indexer/ipfs"
|
"github.com/ethereum/go-ethereum/statediff/indexer/ipfs"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/node"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/indexer/postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPLDsContainBytes used to check if a list of strings contains a particular string
|
// IPLDsContainBytes used to check if a list of strings contains a particular string
|
||||||
@ -31,3 +37,42 @@ func IPLDsContainBytes(iplds []ipfs.BlockModel, b []byte) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetupDB is use to setup a db for watcher tests
|
||||||
|
func SetupDB() (*postgres.DB, error) {
|
||||||
|
port, _ := strconv.Atoi(os.Getenv("DATABASE_PORT"))
|
||||||
|
uri := postgres.DbConnectionString(postgres.ConnectionParams{
|
||||||
|
User: os.Getenv("DATABASE_USER"),
|
||||||
|
Password: os.Getenv("DATABASE_PASSWORD"),
|
||||||
|
Hostname: os.Getenv("DATABASE_HOSTNAME"),
|
||||||
|
Name: os.Getenv("DATABASE_NAME"),
|
||||||
|
Port: port,
|
||||||
|
})
|
||||||
|
return postgres.NewDB(uri, postgres.ConnectionConfig{}, node.Info{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TearDownDB is used to tear down the watcher dbs after tests
|
||||||
|
func TearDownDB(db *postgres.DB) {
|
||||||
|
tx, err := db.Beginx()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.header_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.transaction_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.receipt_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.state_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.storage_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM blocks`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth.log_cids`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = tx.Exec(`DELETE FROM eth_meta.watched_addresses`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ export ETH_FORWARD_ETH_CALLS=false
|
|||||||
export DB_WRITE=true
|
export DB_WRITE=true
|
||||||
export ETH_HTTP_PATH=""
|
export ETH_HTTP_PATH=""
|
||||||
export ETH_PROXY_ON_ERROR=false
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false
|
||||||
|
|
||||||
# Clear up existing docker images and volume.
|
# Clear up existing docker images and volume.
|
||||||
docker-compose down --remove-orphans --volumes
|
docker-compose down --remove-orphans --volumes
|
||||||
|
@ -5,6 +5,7 @@ export ETH_FORWARD_ETH_CALLS=true
|
|||||||
export DB_WRITE=false
|
export DB_WRITE=false
|
||||||
export ETH_HTTP_PATH="dapptools:8545"
|
export ETH_HTTP_PATH="dapptools:8545"
|
||||||
export ETH_PROXY_ON_ERROR=false
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=false
|
||||||
|
|
||||||
# Clear up existing docker images and volume.
|
# Clear up existing docker images and volume.
|
||||||
docker-compose down --remove-orphans --volumes
|
docker-compose down --remove-orphans --volumes
|
||||||
|
28
scripts/run_integration_test_watched_address_gap_filler.sh
Normal file
28
scripts/run_integration_test_watched_address_gap_filler.sh
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
set -e
|
||||||
|
set -o xtrace
|
||||||
|
|
||||||
|
export ETH_FORWARD_ETH_CALLS=false
|
||||||
|
export DB_WRITE=true
|
||||||
|
export ETH_HTTP_PATH=""
|
||||||
|
export ETH_PROXY_ON_ERROR=false
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_ENABLED=true
|
||||||
|
export WATCHED_ADDRESS_GAP_FILLER_INTERVAL=5
|
||||||
|
|
||||||
|
# Clear up existing docker images and volume.
|
||||||
|
docker-compose down --remove-orphans --volumes
|
||||||
|
|
||||||
|
# Build and start the containers.
|
||||||
|
# Note: Build only if `ipld-eth-server` or other container code is modified. Otherwise comment this line.
|
||||||
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml build eth-server
|
||||||
|
docker-compose -f docker-compose.test.yml -f docker-compose.yml up -d ipld-eth-db dapptools contract eth-server
|
||||||
|
|
||||||
|
export PGPASSWORD=password
|
||||||
|
export DATABASE_USER=vdbm
|
||||||
|
export DATABASE_PORT=8077
|
||||||
|
export DATABASE_PASSWORD=password
|
||||||
|
export DATABASE_HOSTNAME=127.0.0.1
|
||||||
|
|
||||||
|
# Wait for containers to be up and execute the integration test.
|
||||||
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8081)" != "200" ]; do echo "waiting for ipld-eth-server..." && sleep 5; done && \
|
||||||
|
while [ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8545)" != "200" ]; do echo "waiting for geth-statediff..." && sleep 5; done && \
|
||||||
|
make integrationtest
|
25
test/contract/contracts/SLVToken.sol
Normal file
25
test/contract/contracts/SLVToken.sol
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// SPDX-License-Identifier: AGPL-3.0
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
|
contract SLVToken is ERC20 {
|
||||||
|
uint256 private countA;
|
||||||
|
uint256 private countB;
|
||||||
|
|
||||||
|
constructor() ERC20("Silver", "SLV") {}
|
||||||
|
|
||||||
|
function incrementCountA() public {
|
||||||
|
countA = countA + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementCountB() public {
|
||||||
|
countB = countB + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
receive() external payable {}
|
||||||
|
|
||||||
|
function destroy() public {
|
||||||
|
selfdestruct(payable(msg.sender));
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,18 @@ task("accounts", "Prints the list of accounts", async () => {
|
|||||||
* @type import('hardhat/config').HardhatUserConfig
|
* @type import('hardhat/config').HardhatUserConfig
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
solidity: "0.8.0",
|
solidity: {
|
||||||
|
version: "0.8.0",
|
||||||
|
settings: {
|
||||||
|
outputSelection: {
|
||||||
|
'*': {
|
||||||
|
'*': [
|
||||||
|
'abi', 'storageLayout',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
networks: {
|
networks: {
|
||||||
local: {
|
local: {
|
||||||
url: 'http://127.0.0.1:8545',
|
url: 'http://127.0.0.1:8545',
|
||||||
|
136
test/contract/package-lock.json
generated
136
test/contract/package-lock.json
generated
@ -11,7 +11,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openzeppelin/contracts": "^4.0.0",
|
"@openzeppelin/contracts": "^4.0.0",
|
||||||
"fastify": "^3.14.2",
|
"fastify": "^3.14.2",
|
||||||
"hardhat": "^2.2.0"
|
"hardhat": "^2.2.0",
|
||||||
|
"solidity-create2-deployer": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
@ -469,7 +470,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
|
||||||
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
|
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -496,7 +496,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
|
||||||
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
|
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -521,7 +520,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
|
||||||
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
|
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -544,7 +542,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
|
||||||
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
|
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -567,7 +564,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
|
||||||
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
|
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -586,7 +582,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
|
||||||
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
|
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -606,7 +601,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
|
||||||
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
|
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -627,7 +621,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
|
||||||
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
|
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -646,7 +639,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
|
||||||
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
|
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -665,7 +657,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
|
||||||
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
|
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -693,7 +684,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
|
||||||
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
|
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -719,7 +709,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
|
||||||
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
|
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -749,7 +738,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
|
||||||
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
|
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -780,7 +768,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
|
||||||
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
|
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -799,14 +786,12 @@
|
|||||||
"node_modules/@ethersproject/keccak256/node_modules/js-sha3": {
|
"node_modules/@ethersproject/keccak256/node_modules/js-sha3": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
|
||||||
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=",
|
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@ethersproject/logger": {
|
"node_modules/@ethersproject/logger": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
|
||||||
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==",
|
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -822,7 +807,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
|
||||||
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
|
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -841,7 +825,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
|
||||||
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
|
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -861,7 +844,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
|
||||||
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
|
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -880,7 +862,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
|
||||||
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
|
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -917,7 +898,6 @@
|
|||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
||||||
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
|
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
@ -938,7 +918,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
|
||||||
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
|
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -958,7 +937,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
|
||||||
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
|
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -978,7 +956,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
|
||||||
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
|
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -999,7 +976,6 @@
|
|||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
|
||||||
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
|
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"minimalistic-assert": "^1.0.0"
|
"minimalistic-assert": "^1.0.0"
|
||||||
@ -1009,7 +985,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
|
||||||
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
|
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1032,7 +1007,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
|
||||||
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
|
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1055,7 +1029,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
|
||||||
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
|
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1076,7 +1049,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
|
||||||
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
|
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1103,7 +1075,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
|
||||||
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
|
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1124,7 +1095,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
|
||||||
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
|
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1157,7 +1127,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
|
||||||
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
|
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1180,7 +1149,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
|
||||||
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
|
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -1630,8 +1598,7 @@
|
|||||||
"node_modules/aes-js": {
|
"node_modules/aes-js": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
||||||
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=",
|
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
@ -1870,8 +1837,7 @@
|
|||||||
"node_modules/bech32": {
|
"node_modules/bech32": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
|
||||||
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==",
|
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
@ -2774,7 +2740,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
|
||||||
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
|
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -5427,7 +5392,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "2.1.2",
|
||||||
"whatwg-fetch": "2.0.4"
|
"whatwg-fetch": "2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -7533,7 +7498,7 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-fetch": "^2.6.7"
|
"node-fetch": "~1.7.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": {
|
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/is-stream": {
|
||||||
@ -7545,7 +7510,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": {
|
"node_modules/ganache-core/node_modules/fetch-ponyfill/node_modules/node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "1.7.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -8639,6 +8604,8 @@
|
|||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/keccak": {
|
"node_modules/ganache-core/node_modules/keccak": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
@ -9212,12 +9179,14 @@
|
|||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/node-addon-api": {
|
"node_modules/ganache-core/node_modules/node-addon-api": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/node-fetch": {
|
"node_modules/ganache-core/node_modules/node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.1.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -9226,6 +9195,8 @@
|
|||||||
},
|
},
|
||||||
"node_modules/ganache-core/node_modules/node-gyp-build": {
|
"node_modules/ganache-core/node_modules/node-gyp-build": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -14740,6 +14711,17 @@
|
|||||||
"semver": "bin/semver"
|
"semver": "bin/semver"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/solidity-create2-deployer": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/solidity-create2-deployer/-/solidity-create2-deployer-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-bB5d8fPt4dWsOoRodrsyfWKcjiv77IFl84+e6EckMMGYlfL2ZFqUoMz6tnqqiUFrM9abF1p6dWFOgJ/3zVc8yQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ethers": "^5.0.14"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sonic-boom": {
|
"node_modules/sonic-boom": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
|
||||||
@ -16056,7 +16038,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.0.tgz",
|
||||||
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
|
"integrity": "sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/address": "^5.1.0",
|
"@ethersproject/address": "^5.1.0",
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
@ -16073,7 +16054,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz",
|
||||||
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
|
"integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
@ -16088,7 +16068,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz",
|
||||||
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
|
"integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-provider": "^5.1.0",
|
"@ethersproject/abstract-provider": "^5.1.0",
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
@ -16101,7 +16080,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz",
|
||||||
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
|
"integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
@ -16114,7 +16092,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz",
|
||||||
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
|
"integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0"
|
"@ethersproject/bytes": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -16123,7 +16100,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz",
|
||||||
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
|
"integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/properties": "^5.1.0"
|
"@ethersproject/properties": "^5.1.0"
|
||||||
@ -16133,7 +16109,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.0.tgz",
|
||||||
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
|
"integrity": "sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/logger": "^5.1.0",
|
"@ethersproject/logger": "^5.1.0",
|
||||||
@ -16144,7 +16119,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz",
|
||||||
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
|
"integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/logger": "^5.1.0"
|
"@ethersproject/logger": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -16153,7 +16127,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz",
|
||||||
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
|
"integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bignumber": "^5.1.0"
|
"@ethersproject/bignumber": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -16162,7 +16135,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.0.tgz",
|
||||||
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
|
"integrity": "sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abi": "^5.1.0",
|
"@ethersproject/abi": "^5.1.0",
|
||||||
"@ethersproject/abstract-provider": "^5.1.0",
|
"@ethersproject/abstract-provider": "^5.1.0",
|
||||||
@ -16180,7 +16152,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz",
|
||||||
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
|
"integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-signer": "^5.1.0",
|
"@ethersproject/abstract-signer": "^5.1.0",
|
||||||
"@ethersproject/address": "^5.1.0",
|
"@ethersproject/address": "^5.1.0",
|
||||||
@ -16196,7 +16167,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz",
|
||||||
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
|
"integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-signer": "^5.1.0",
|
"@ethersproject/abstract-signer": "^5.1.0",
|
||||||
"@ethersproject/basex": "^5.1.0",
|
"@ethersproject/basex": "^5.1.0",
|
||||||
@ -16216,7 +16186,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz",
|
||||||
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
|
"integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-signer": "^5.1.0",
|
"@ethersproject/abstract-signer": "^5.1.0",
|
||||||
"@ethersproject/address": "^5.1.0",
|
"@ethersproject/address": "^5.1.0",
|
||||||
@ -16237,7 +16206,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz",
|
||||||
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
|
"integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"js-sha3": "0.5.7"
|
"js-sha3": "0.5.7"
|
||||||
@ -16246,22 +16214,19 @@
|
|||||||
"js-sha3": {
|
"js-sha3": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz",
|
||||||
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=",
|
"integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@ethersproject/logger": {
|
"@ethersproject/logger": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz",
|
||||||
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==",
|
"integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@ethersproject/networks": {
|
"@ethersproject/networks": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz",
|
||||||
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
|
"integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/logger": "^5.1.0"
|
"@ethersproject/logger": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -16270,7 +16235,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz",
|
||||||
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
|
"integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/sha2": "^5.1.0"
|
"@ethersproject/sha2": "^5.1.0"
|
||||||
@ -16280,7 +16244,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz",
|
||||||
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
|
"integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/logger": "^5.1.0"
|
"@ethersproject/logger": "^5.1.0"
|
||||||
}
|
}
|
||||||
@ -16289,7 +16252,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.0.tgz",
|
||||||
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
|
"integrity": "sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-provider": "^5.1.0",
|
"@ethersproject/abstract-provider": "^5.1.0",
|
||||||
"@ethersproject/abstract-signer": "^5.1.0",
|
"@ethersproject/abstract-signer": "^5.1.0",
|
||||||
@ -16316,7 +16278,6 @@
|
|||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
||||||
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
|
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {}
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -16325,7 +16286,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz",
|
||||||
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
|
"integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/logger": "^5.1.0"
|
"@ethersproject/logger": "^5.1.0"
|
||||||
@ -16335,7 +16295,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz",
|
||||||
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
|
"integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/logger": "^5.1.0"
|
"@ethersproject/logger": "^5.1.0"
|
||||||
@ -16345,7 +16304,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz",
|
||||||
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
|
"integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/logger": "^5.1.0",
|
"@ethersproject/logger": "^5.1.0",
|
||||||
@ -16356,7 +16314,6 @@
|
|||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
|
||||||
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
|
"integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"minimalistic-assert": "^1.0.0"
|
"minimalistic-assert": "^1.0.0"
|
||||||
@ -16368,7 +16325,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz",
|
||||||
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
|
"integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/logger": "^5.1.0",
|
"@ethersproject/logger": "^5.1.0",
|
||||||
@ -16381,7 +16337,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz",
|
||||||
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
|
"integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
@ -16394,7 +16349,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz",
|
||||||
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
|
"integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/constants": "^5.1.0",
|
"@ethersproject/constants": "^5.1.0",
|
||||||
@ -16405,7 +16359,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.0.tgz",
|
||||||
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
|
"integrity": "sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/address": "^5.1.0",
|
"@ethersproject/address": "^5.1.0",
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
@ -16422,7 +16375,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz",
|
||||||
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
|
"integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bignumber": "^5.1.0",
|
"@ethersproject/bignumber": "^5.1.0",
|
||||||
"@ethersproject/constants": "^5.1.0",
|
"@ethersproject/constants": "^5.1.0",
|
||||||
@ -16433,7 +16385,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz",
|
||||||
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
|
"integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abstract-provider": "^5.1.0",
|
"@ethersproject/abstract-provider": "^5.1.0",
|
||||||
"@ethersproject/abstract-signer": "^5.1.0",
|
"@ethersproject/abstract-signer": "^5.1.0",
|
||||||
@ -16456,7 +16407,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz",
|
||||||
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
|
"integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/base64": "^5.1.0",
|
"@ethersproject/base64": "^5.1.0",
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
@ -16469,7 +16419,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz",
|
||||||
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
|
"integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/bytes": "^5.1.0",
|
"@ethersproject/bytes": "^5.1.0",
|
||||||
"@ethersproject/hash": "^5.1.0",
|
"@ethersproject/hash": "^5.1.0",
|
||||||
@ -16871,8 +16820,7 @@
|
|||||||
"aes-js": {
|
"aes-js": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
||||||
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=",
|
"integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"agent-base": {
|
"agent-base": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
@ -17059,8 +17007,7 @@
|
|||||||
"bech32": {
|
"bech32": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
|
||||||
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==",
|
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
@ -17807,7 +17754,6 @@
|
|||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.0.tgz",
|
||||||
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
|
"integrity": "sha512-2L6Ge6wMBw02FlRoCLg4E0Elt3khMNlW6ULawa10mMeeZToYJ5+uCfiuTuB+XZ6om1Y7wuO9ZzezP8FsU2M/+g==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethersproject/abi": "5.1.0",
|
"@ethersproject/abi": "5.1.0",
|
||||||
"@ethersproject/abstract-provider": "5.1.0",
|
"@ethersproject/abstract-provider": "5.1.0",
|
||||||
@ -19810,7 +19756,7 @@
|
|||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "2.1.2",
|
||||||
"whatwg-fetch": "2.0.4"
|
"whatwg-fetch": "2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -21621,7 +21567,7 @@
|
|||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-fetch": "^2.6.7"
|
"node-fetch": "~1.7.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-stream": {
|
"is-stream": {
|
||||||
@ -21629,7 +21575,7 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "1.7.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"encoding": "^0.1.11",
|
"encoding": "^0.1.11",
|
||||||
@ -22392,6 +22338,8 @@
|
|||||||
},
|
},
|
||||||
"keccak": {
|
"keccak": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -22823,15 +22771,19 @@
|
|||||||
},
|
},
|
||||||
"node-addon-api": {
|
"node-addon-api": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.1.2",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-gyp-build": {
|
"node-gyp-build": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
@ -26969,6 +26921,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"solidity-create2-deployer": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/solidity-create2-deployer/-/solidity-create2-deployer-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-bB5d8fPt4dWsOoRodrsyfWKcjiv77IFl84+e6EckMMGYlfL2ZFqUoMz6tnqqiUFrM9abF1p6dWFOgJ/3zVc8yQ==",
|
||||||
|
"requires": {
|
||||||
|
"ethers": "^5.0.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sonic-boom": {
|
"sonic-boom": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz",
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openzeppelin/contracts": "^4.0.0",
|
"@openzeppelin/contracts": "^4.0.0",
|
||||||
"fastify": "^3.14.2",
|
"fastify": "^3.14.2",
|
||||||
"hardhat": "^2.2.0"
|
"hardhat": "^2.2.0",
|
||||||
|
"solidity-create2-deployer": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
const fastify = require('fastify')({ logger: true });
|
const fastify = require('fastify')({ logger: true });
|
||||||
const hre = require("hardhat");
|
const hre = require("hardhat");
|
||||||
|
const {
|
||||||
|
deployContract,
|
||||||
|
isDeployed
|
||||||
|
} = require("solidity-create2-deployer");
|
||||||
|
|
||||||
|
const { getStorageSlotKey, deployCreate2Factory } = require('./utils');
|
||||||
|
|
||||||
|
const CREATE2_FACTORY_ADDRESS = '0x4a27c059FD7E383854Ea7DE6Be9c390a795f6eE3'
|
||||||
|
|
||||||
// readiness check
|
// readiness check
|
||||||
fastify.get('/v1/healthz', async (req, reply) => {
|
fastify.get('/v1/healthz', async (req, reply) => {
|
||||||
@ -63,6 +70,109 @@ fastify.get('/v1/sendEth', async (req, reply) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/deploySLVContract', async (req, reply) => {
|
||||||
|
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||||
|
const token = await SLVToken.deploy();
|
||||||
|
const receipt = await token.deployTransaction.wait();
|
||||||
|
|
||||||
|
return {
|
||||||
|
address: token.address,
|
||||||
|
txHash: token.deployTransaction.hash,
|
||||||
|
blockNumber: receipt.blockNumber,
|
||||||
|
blockHash: receipt.blockHash,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/destroySLVContract', async (req, reply) => {
|
||||||
|
const addr = req.query.addr;
|
||||||
|
|
||||||
|
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||||
|
const token = SLVToken.attach(addr);
|
||||||
|
|
||||||
|
const tx = await token.destroy();
|
||||||
|
const receipt = await tx.wait();
|
||||||
|
|
||||||
|
return {
|
||||||
|
blockNumber: receipt.blockNumber,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
fastify.get('/v1/incrementCountA', async (req, reply) => {
|
||||||
|
const addr = req.query.addr;
|
||||||
|
|
||||||
|
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||||
|
const token = await SLVToken.attach(addr);
|
||||||
|
|
||||||
|
const tx = await token.incrementCountA();
|
||||||
|
const receipt = await tx.wait();
|
||||||
|
|
||||||
|
return {
|
||||||
|
blockNumber: receipt.blockNumber,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/incrementCountB', async (req, reply) => {
|
||||||
|
const addr = req.query.addr;
|
||||||
|
|
||||||
|
const SLVToken = await hre.ethers.getContractFactory("SLVToken");
|
||||||
|
const token = await SLVToken.attach(addr);
|
||||||
|
|
||||||
|
const tx = await token.incrementCountB();
|
||||||
|
const receipt = await tx.wait();
|
||||||
|
|
||||||
|
return {
|
||||||
|
blockNumber: receipt.blockNumber,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/getStorageKey', async (req, reply) => {
|
||||||
|
const contract = req.query.contract;
|
||||||
|
const label = req.query.label;
|
||||||
|
|
||||||
|
const key = await getStorageSlotKey(contract, label)
|
||||||
|
|
||||||
|
return {
|
||||||
|
key
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/v1/create2Contract', async (req, reply) => {
|
||||||
|
const contract = req.query.contract;
|
||||||
|
const salt = req.query.salt;
|
||||||
|
|
||||||
|
const provider = hre.ethers.provider;
|
||||||
|
const signer = await hre.ethers.getSigner();
|
||||||
|
const isFactoryDeployed = await isDeployed(CREATE2_FACTORY_ADDRESS, provider);
|
||||||
|
|
||||||
|
if (!isFactoryDeployed) {
|
||||||
|
await deployCreate2Factory(provider, signer)
|
||||||
|
}
|
||||||
|
|
||||||
|
const contractFactory = await hre.ethers.getContractFactory(contract);
|
||||||
|
const bytecode = contractFactory.bytecode;
|
||||||
|
const constructorTypes = [];
|
||||||
|
const constructorArgs = [];
|
||||||
|
|
||||||
|
const { txHash, address, receipt } = await deployContract({
|
||||||
|
salt,
|
||||||
|
contractBytecode: bytecode,
|
||||||
|
constructorTypes: constructorTypes,
|
||||||
|
constructorArgs: constructorArgs,
|
||||||
|
signer
|
||||||
|
});
|
||||||
|
|
||||||
|
const success = await isDeployed(address, provider);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
return {
|
||||||
|
address,
|
||||||
|
txHash,
|
||||||
|
blockNumber: receipt.blockNumber,
|
||||||
|
blockHash: receipt.blockHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
await fastify.listen(3000, '0.0.0.0');
|
await fastify.listen(3000, '0.0.0.0');
|
||||||
|
54
test/contract/src/utils.js
Normal file
54
test/contract/src/utils.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
const { artifacts } = require("hardhat")
|
||||||
|
const { utils, BigNumber } = require("ethers")
|
||||||
|
const { deployFactory } = require("solidity-create2-deployer");
|
||||||
|
|
||||||
|
const CREATE2_FACTORY_ACCOUNT = '0x2287Fa6efdEc6d8c3E0f4612ce551dEcf89A357A';
|
||||||
|
|
||||||
|
async function getStorageLayout(contractName) {
|
||||||
|
const artifact = await artifacts.readArtifact(contractName);
|
||||||
|
const buildInfo = await artifacts.getBuildInfo(`${artifact.sourceName}:${artifact.contractName}`);
|
||||||
|
|
||||||
|
if (!buildInfo) {
|
||||||
|
throw new Error('storageLayout not present in compiler output.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = buildInfo.output;
|
||||||
|
const { storageLayout } = output.contracts[artifact.sourceName][artifact.contractName];
|
||||||
|
|
||||||
|
if (!storageLayout) {
|
||||||
|
throw new Error('Contract hasn\'t been compiled.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return storageLayout;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getStorageSlotKey(contractName, variableName) {
|
||||||
|
storageLayout = await getStorageLayout(contractName)
|
||||||
|
|
||||||
|
const { storage } = storageLayout;
|
||||||
|
const targetState = storage.find((state) => state.label === variableName);
|
||||||
|
|
||||||
|
// Throw if state variable could not be found in storage layout.
|
||||||
|
if (!targetState) {
|
||||||
|
throw new Error('Variable not present in storage layout.');
|
||||||
|
}
|
||||||
|
|
||||||
|
key = utils.hexlify(BigNumber.from(targetState.slot));
|
||||||
|
return key
|
||||||
|
};
|
||||||
|
|
||||||
|
async function deployCreate2Factory(provider, signer) {
|
||||||
|
// Send eth to account as required to deploy create2 factory contract.
|
||||||
|
let tx = {
|
||||||
|
to: CREATE2_FACTORY_ACCOUNT,
|
||||||
|
value: utils.parseEther('0.01')
|
||||||
|
}
|
||||||
|
|
||||||
|
const txResponse = await signer.sendTransaction(tx);
|
||||||
|
await txResponse.wait()
|
||||||
|
|
||||||
|
// Deploy create2 factory contract.
|
||||||
|
await deployFactory(provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { getStorageSlotKey, deployCreate2Factory }
|
@ -20,6 +20,8 @@ import (
|
|||||||
var _ = Describe("Integration test", func() {
|
var _ = Describe("Integration test", func() {
|
||||||
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
gethHttpPath := "http://127.0.0.1:8545"
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
gethClient, err := ethclient.Dial(gethHttpPath)
|
gethClient, err := ethclient.Dial(gethHttpPath)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -38,11 +40,14 @@ var _ = Describe("Integration test", func() {
|
|||||||
var txErr error
|
var txErr error
|
||||||
sleepInterval := 2 * time.Second
|
sleepInterval := 2 * time.Second
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
if !directProxyEthCalls || watchedAddressServiceEnabled {
|
||||||
|
Skip("skipping direct-proxy-forwarding integration tests")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
Describe("get Block", func() {
|
Describe("get Block", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -94,9 +99,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Transaction", func() {
|
Describe("Transaction", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -122,9 +124,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Receipt", func() {
|
Describe("Receipt", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -142,9 +141,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("FilterLogs", func() {
|
Describe("FilterLogs", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -174,9 +170,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("CodeAt", func() {
|
Describe("CodeAt", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -224,9 +217,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
Describe("Get balance", func() {
|
Describe("Get balance", func() {
|
||||||
address := "0x1111111111111111111111111111111111111112"
|
address := "0x1111111111111111111111111111111111111112"
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
tx, txErr = integration.SendEth(address, "0.01")
|
tx, txErr = integration.SendEth(address, "0.01")
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -286,9 +276,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Get Storage", func() {
|
Describe("Get Storage", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
@ -392,9 +379,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("eth call", func() {
|
Describe("eth call", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
@ -445,9 +429,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Chain ID", func() {
|
Describe("Chain ID", func() {
|
||||||
It("Check chain id", func() {
|
It("Check chain id", func() {
|
||||||
if !directProxyEthCalls {
|
|
||||||
Skip("skipping direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
_, err := gethClient.ChainID(ctx)
|
_, err := gethClient.ChainID(ctx)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
110
test/helper.go
110
test/helper.go
@ -5,6 +5,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContractDeployed struct {
|
type ContractDeployed struct {
|
||||||
@ -27,6 +32,14 @@ type Tx struct {
|
|||||||
BlockHash string `json:"blockHash"`
|
BlockHash string `json:"blockHash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StorageKey struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CountIncremented struct {
|
||||||
|
BlockNumber int64 `json:"blockNumber"`
|
||||||
|
}
|
||||||
|
|
||||||
const srvUrl = "http://localhost:3000"
|
const srvUrl = "http://localhost:3000"
|
||||||
|
|
||||||
func DeployContract() (*ContractDeployed, error) {
|
func DeployContract() (*ContractDeployed, error) {
|
||||||
@ -77,3 +90,100 @@ func SendEth(to string, value string) (*Tx, error) {
|
|||||||
|
|
||||||
return &tx, nil
|
return &tx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeploySLVContract() (*ContractDeployed, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/deploySLVContract", srvUrl))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var contract ContractDeployed
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
err = decoder.Decode(&contract)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &contract, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DestroySLVContract(addr string) (*ContractDestroyed, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/destroySLVContract?addr=%s", srvUrl, addr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data ContractDestroyed
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
|
||||||
|
return &data, decoder.Decode(&data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IncrementCount(addr string, count string) (*CountIncremented, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/incrementCount%s?addr=%s", srvUrl, count, addr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockNumber CountIncremented
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
err = decoder.Decode(&blockNumber)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &blockNumber, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStorageSlotKey(contract string, label string) (*StorageKey, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/getStorageKey?contract=%s&label=%s", srvUrl, contract, label))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var key StorageKey
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
err = decoder.Decode(&key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClearWatchedAddresses(gethRPCClient *rpc.Client) error {
|
||||||
|
gethMethod := "statediff_watchAddress"
|
||||||
|
args := []sdtypes.WatchAddressArg{}
|
||||||
|
|
||||||
|
// Clear watched addresses
|
||||||
|
gethErr := gethRPCClient.Call(nil, gethMethod, statediff.Clear, args)
|
||||||
|
if gethErr != nil {
|
||||||
|
return gethErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Create2Contract(contractName string, salt string) (*ContractDeployed, error) {
|
||||||
|
res, err := http.Get(fmt.Sprintf("%s/v1/create2Contract?contract=%s&salt=%s", srvUrl, contractName, salt))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var contract ContractDeployed
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(res.Body)
|
||||||
|
err = decoder.Decode(&contract)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &contract, nil
|
||||||
|
}
|
||||||
|
@ -31,6 +31,8 @@ var (
|
|||||||
var _ = Describe("Integration test", func() {
|
var _ = Describe("Integration test", func() {
|
||||||
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
directProxyEthCalls, err := strconv.ParseBool(os.Getenv("ETH_FORWARD_ETH_CALLS"))
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
gethHttpPath := "http://127.0.0.1:8545"
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
gethClient, err := ethclient.Dial(gethHttpPath)
|
gethClient, err := ethclient.Dial(gethHttpPath)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -49,11 +51,14 @@ var _ = Describe("Integration test", func() {
|
|||||||
var txErr error
|
var txErr error
|
||||||
sleepInterval := 2 * time.Second
|
sleepInterval := 2 * time.Second
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
if directProxyEthCalls || watchedAddressServiceEnabled {
|
||||||
|
Skip("skipping no-direct-proxy-forwarding integration tests")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
Describe("get Block", func() {
|
Describe("get Block", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -123,9 +128,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Transaction", func() {
|
Describe("Transaction", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -157,9 +159,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Receipt", func() {
|
Describe("Receipt", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -187,9 +186,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("FilterLogs", func() {
|
Describe("FilterLogs", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -220,9 +216,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("CodeAt", func() {
|
Describe("CodeAt", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -270,9 +263,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
Describe("Get balance", func() {
|
Describe("Get balance", func() {
|
||||||
address := "0x1111111111111111111111111111111111111112"
|
address := "0x1111111111111111111111111111111111111112"
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
tx, txErr = integration.SendEth(address, "0.01")
|
tx, txErr = integration.SendEth(address, "0.01")
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
})
|
})
|
||||||
@ -335,10 +325,12 @@ var _ = Describe("Integration test", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Describe("Get Storage", func() {
|
Describe("Get Storage", func() {
|
||||||
|
var slvContract *integration.ContractDeployed
|
||||||
|
var slvCountA *big.Int
|
||||||
|
|
||||||
|
contractSalt := "SLVContractSalt"
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
@ -418,12 +410,48 @@ var _ = Describe("Integration test", func() {
|
|||||||
Expect(gethStorage).To(Equal(ipldStorage))
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("get storage for SLV countA", func() {
|
||||||
|
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
countAIndex := "0x5"
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethCountA := new(big.Int).SetBytes(gethStorage)
|
||||||
|
slvCountA = gethCountA
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCountA := new(big.Int).SetBytes(ipldStorage)
|
||||||
|
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
|
||||||
|
|
||||||
|
_, txErr = integration.IncrementCount(slvContract.Address, "A")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
slvCountA.Add(slvCountA, big.NewInt(1))
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
|
||||||
|
ipldStorage, err = ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCountA = new(big.Int).SetBytes(ipldStorage)
|
||||||
|
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
|
||||||
|
})
|
||||||
|
|
||||||
It("get storage after self destruct", func() {
|
It("get storage after self destruct", func() {
|
||||||
totalSupplyIndex := "0x2"
|
totalSupplyIndex := "0x2"
|
||||||
|
countAIndex := "0x5"
|
||||||
|
|
||||||
tx, err := integration.DestroyContract(contract.Address)
|
tx, err := integration.DestroyContract(contract.Address)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
slvTx, err := integration.DestroyContract(slvContract.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
time.Sleep(sleepInterval)
|
time.Sleep(sleepInterval)
|
||||||
|
|
||||||
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
|
gethStorage1, err := gethClient.StorageAt(ctx, common.HexToAddress(contract.Address), common.HexToHash(totalSupplyIndex), big.NewInt(tx.BlockNumber-1))
|
||||||
@ -447,14 +475,44 @@ var _ = Describe("Integration test", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
Expect(ipldStorage2).To(Equal(ipldStorage3))
|
Expect(ipldStorage2).To(Equal(ipldStorage3))
|
||||||
|
|
||||||
|
// Check for SLV contract
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(gethStorage).To(Equal(eth.EmptyNodeValue))
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), big.NewInt(slvTx.BlockNumber))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(ipldStorage).To(Equal(gethStorage))
|
||||||
|
|
||||||
|
slvCountA.Set(big.NewInt(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
XIt("get storage after redeploying", func() {
|
||||||
|
slvContract, contractErr = integration.Create2Contract("SLVToken", contractSalt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
|
||||||
|
countAIndex := "0x5"
|
||||||
|
|
||||||
|
gethStorage, err := gethClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
gethCountA := new(big.Int).SetBytes(gethStorage)
|
||||||
|
Expect(gethCountA.String()).To(Equal(slvCountA.String()))
|
||||||
|
|
||||||
|
ipldStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(slvContract.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldCountA := new(big.Int).SetBytes(ipldStorage)
|
||||||
|
Expect(ipldCountA.String()).To(Equal(slvCountA.String()))
|
||||||
|
|
||||||
|
Expect(gethStorage).To(Equal(ipldStorage))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("eth call", func() {
|
Describe("eth call", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
contract, contractErr = integration.DeployContract()
|
contract, contractErr = integration.DeployContract()
|
||||||
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
erc20TotalSupply, bigIntResult = new(big.Int).SetString("1000000000000000000000", 10)
|
||||||
|
|
||||||
@ -505,9 +563,6 @@ var _ = Describe("Integration test", func() {
|
|||||||
|
|
||||||
Describe("Chain ID", func() {
|
Describe("Chain ID", func() {
|
||||||
It("Check chain id", func() {
|
It("Check chain id", func() {
|
||||||
if directProxyEthCalls {
|
|
||||||
Skip("skipping no-direct-proxy-forwarding integration tests")
|
|
||||||
}
|
|
||||||
gethChainId, err := gethClient.ChainID(ctx)
|
gethChainId, err := gethClient.ChainID(ctx)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
674
test/watch_address_integration_test.go
Normal file
674
test/watch_address_integration_test.go
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
gethMethod = "statediff_watchAddress"
|
||||||
|
ipldMethod = "vdb_watchAddress"
|
||||||
|
|
||||||
|
sleepInterval = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("WatchAddress integration test", func() {
|
||||||
|
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
|
gethRPCClient, err := rpc.Dial(gethHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldEthHttpPath := "http://127.0.0.1:8081"
|
||||||
|
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldRPCClient, err := rpc.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctx = context.Background()
|
||||||
|
|
||||||
|
txErr error
|
||||||
|
contractErr error
|
||||||
|
incErr error
|
||||||
|
|
||||||
|
contract1 *integration.ContractDeployed
|
||||||
|
contract2 *integration.ContractDeployed
|
||||||
|
contract3 *integration.ContractDeployed
|
||||||
|
|
||||||
|
countAIndex string
|
||||||
|
|
||||||
|
prevBalance1 *big.Int
|
||||||
|
prevBalance2 *big.Int
|
||||||
|
prevBalance3 *big.Int
|
||||||
|
|
||||||
|
actualBalance1 *big.Int
|
||||||
|
actualBalance2 *big.Int
|
||||||
|
actualBalance3 *big.Int
|
||||||
|
|
||||||
|
prevCountA1 *big.Int
|
||||||
|
prevCountA2 *big.Int
|
||||||
|
prevCountA3 *big.Int
|
||||||
|
|
||||||
|
actualCountA1 *big.Int
|
||||||
|
actualCountA2 *big.Int
|
||||||
|
actualCountA3 *big.Int
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
if !dbWrite || watchedAddressServiceEnabled {
|
||||||
|
Skip("skipping WatchAddress API integration tests")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("test init", func() {
|
||||||
|
// Deploy three contracts
|
||||||
|
contract1, contractErr = integration.DeploySLVContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
contract2, contractErr = integration.DeploySLVContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
contract3, contractErr = integration.DeploySLVContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Get the storage slot key
|
||||||
|
storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countAIndex = storageSlotAKey.Key
|
||||||
|
|
||||||
|
// Clear out watched addresses
|
||||||
|
err = integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Get initial balances for all the contracts
|
||||||
|
// Contract 1
|
||||||
|
actualBalance1 = big.NewInt(0)
|
||||||
|
initBalance1, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(initBalance1.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1 = big.NewInt(0)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
actualBalance2 = big.NewInt(0)
|
||||||
|
initBalance2, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(initBalance2.String()).To(Equal(actualBalance2.String()))
|
||||||
|
prevBalance2 = big.NewInt(0)
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
actualBalance3 = big.NewInt(0)
|
||||||
|
initBalance3, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(initBalance3.String()).To(Equal(actualBalance3.String()))
|
||||||
|
prevBalance3 = big.NewInt(0)
|
||||||
|
|
||||||
|
// Get initial storage values for the contracts
|
||||||
|
// Contract 1, countA
|
||||||
|
actualCountA1 = big.NewInt(0)
|
||||||
|
ipldCountA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldCountA1 := new(big.Int).SetBytes(ipldCountA1Storage)
|
||||||
|
Expect(ipldCountA1.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1 = big.NewInt(0)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
actualCountA2 = big.NewInt(0)
|
||||||
|
ipldCountA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldCountA2 := new(big.Int).SetBytes(ipldCountA2Storage)
|
||||||
|
Expect(ipldCountA2.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA2 = big.NewInt(0)
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
actualCountA3 = big.NewInt(0)
|
||||||
|
ipldCountA3Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldCountA3 := new(big.Int).SetBytes(ipldCountA3Storage)
|
||||||
|
Expect(ipldCountA3.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA3 = big.NewInt(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
defer It("test cleanup", func() {
|
||||||
|
// Clear out watched addresses
|
||||||
|
err := integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("no contracts being watched", func() {
|
||||||
|
It("indexes state for all the contracts", func() {
|
||||||
|
// WatchedAddresses = []
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1.Set(actualBalance1)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
|
||||||
|
prevBalance2.Set(actualBalance2)
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
|
||||||
|
prevBalance3.Set(actualBalance3)
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1.Set(actualCountA1)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA2.Set(actualCountA2)
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
|
||||||
|
prevCountA3.Set(actualCountA3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("one contract being watched", func() {
|
||||||
|
It("indexes state only for the watched contract", func() {
|
||||||
|
operation := statediff.Add
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1.Address,
|
||||||
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [Contract1]
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1.Set(actualBalance1)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1.Set(actualCountA1)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("contract added to a non-empty watch-list", func() {
|
||||||
|
It("indexes state only for the watched contracts", func() {
|
||||||
|
operation := statediff.Add
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract2.Address,
|
||||||
|
CreatedAt: uint64(contract2.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [Contract1, Contract2]
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1.Set(actualBalance1)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
|
||||||
|
prevBalance2.Set(actualBalance2)
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1.Set(actualCountA1)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA2.Set(actualCountA2)
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("contract removed from the watch-list", func() {
|
||||||
|
It("indexes state only for the watched contract", func() {
|
||||||
|
operation := statediff.Remove
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1.Address,
|
||||||
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [Contract2]
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(prevBalance1.String()))
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
|
||||||
|
prevBalance2.Set(actualBalance2)
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(prevBalance3.String()))
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(prevCountA1.String()))
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA2.Set(actualCountA2)
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(prevCountA3.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("list of watched addresses set", func() {
|
||||||
|
It("indexes state only for the watched contracts", func() {
|
||||||
|
operation := statediff.Set
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: contract1.Address,
|
||||||
|
CreatedAt: uint64(contract1.BlockNumber),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: contract3.Address,
|
||||||
|
CreatedAt: uint64(contract3.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [Contract1, Contract3]
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1.Set(actualBalance1)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(prevBalance2.String()))
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
|
||||||
|
prevBalance3.Set(actualBalance3)
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1.Set(actualCountA1)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(prevCountA2.String()))
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
|
||||||
|
prevCountA3.Set(actualCountA3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("list of watched addresses cleared", func() {
|
||||||
|
It("indexes state for all the contracts", func() {
|
||||||
|
operation := statediff.Clear
|
||||||
|
args := []sdtypes.WatchAddressArg{}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = []
|
||||||
|
// Send eth to all three contract accounts
|
||||||
|
// Contract 1
|
||||||
|
_, txErr = integration.SendEth(contract1.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance1.Add(actualBalance1, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance1AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract1.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance1AfterTransfer.String()).To(Equal(actualBalance1.String()))
|
||||||
|
prevBalance1.Set(actualBalance1)
|
||||||
|
|
||||||
|
// Contract 2
|
||||||
|
_, txErr = integration.SendEth(contract2.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance2.Add(actualBalance2, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance2AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract2.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance2AfterTransfer.String()).To(Equal(actualBalance2.String()))
|
||||||
|
prevBalance2.Set(actualBalance2)
|
||||||
|
|
||||||
|
// Contract 3
|
||||||
|
_, txErr = integration.SendEth(contract3.Address, "0.01")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
actualBalance3.Add(actualBalance3, big.NewInt(10000000000000000))
|
||||||
|
|
||||||
|
balance3AfterTransfer, err := ipldClient.BalanceAt(ctx, common.HexToAddress(contract3.Address), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(balance3AfterTransfer.String()).To(Equal(actualBalance3.String()))
|
||||||
|
prevBalance3.Set(actualBalance3)
|
||||||
|
|
||||||
|
// Increment counts
|
||||||
|
// Contract 1, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA1.Add(actualCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(actualCountA1.String()))
|
||||||
|
prevCountA1.Set(actualCountA1)
|
||||||
|
|
||||||
|
// Contract 2, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract2.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA2.Add(actualCountA2, big.NewInt(1))
|
||||||
|
|
||||||
|
countA2AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2AfterIncrement := new(big.Int).SetBytes(countA2AfterIncrementStorage)
|
||||||
|
Expect(countA2AfterIncrement.String()).To(Equal(actualCountA2.String()))
|
||||||
|
prevCountA2.Set(actualCountA2)
|
||||||
|
|
||||||
|
// Contract 3, countA
|
||||||
|
_, incErr = integration.IncrementCount(contract3.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(incErr).ToNot(HaveOccurred())
|
||||||
|
actualCountA3.Add(actualCountA3, big.NewInt(1))
|
||||||
|
|
||||||
|
countA3AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(contract3.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA3AfterIncrement := new(big.Int).SetBytes(countA3AfterIncrementStorage)
|
||||||
|
Expect(countA3AfterIncrement.String()).To(Equal(actualCountA3.String()))
|
||||||
|
prevCountA3.Set(actualCountA3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("with invalid args", func() {
|
||||||
|
It("returns an error on invalid operation arg", func() {
|
||||||
|
operation := "WrongOp"
|
||||||
|
args := []sdtypes.WatchAddressArg{}
|
||||||
|
|
||||||
|
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
|
||||||
|
Expect(gethErr).To(HaveOccurred())
|
||||||
|
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).To(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(ipldErr).To(Equal(gethErr))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("returns an error on args of invalid type", func() {
|
||||||
|
operation := statediff.Add
|
||||||
|
args := []string{"WrongArg"}
|
||||||
|
|
||||||
|
gethErr := gethRPCClient.Call(nil, gethMethod, operation, args)
|
||||||
|
Expect(gethErr).To(HaveOccurred())
|
||||||
|
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).To(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(ipldErr).To(Equal(gethErr))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
321
test/watched_address_gap_filling_service_integration_test.go
Normal file
321
test/watched_address_gap_filling_service_integration_test.go
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
package integration_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
sdtypes "github.com/ethereum/go-ethereum/statediff/types"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
integration "github.com/vulcanize/ipld-eth-server/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Watched address gap filling service integration test", func() {
|
||||||
|
dbWrite, err := strconv.ParseBool(os.Getenv("DB_WRITE"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
watchedAddressServiceEnabled, err := strconv.ParseBool(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_ENABLED"))
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
serviceInterval, err := strconv.ParseInt(os.Getenv("WATCHED_ADDRESS_GAP_FILLER_INTERVAL"), 10, 0)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
gethHttpPath := "http://127.0.0.1:8545"
|
||||||
|
gethRPCClient, err := rpc.Dial(gethHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
ipldEthHttpPath := "http://127.0.0.1:8081"
|
||||||
|
ipldClient, err := ethclient.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
ipldRPCClient, err := rpc.Dial(ipldEthHttpPath)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctx = context.Background()
|
||||||
|
|
||||||
|
contractErr error
|
||||||
|
txErr error
|
||||||
|
|
||||||
|
GLD1 *integration.ContractDeployed
|
||||||
|
SLV1 *integration.ContractDeployed
|
||||||
|
SLV2 *integration.ContractDeployed
|
||||||
|
|
||||||
|
countAIndex string
|
||||||
|
countBIndex string
|
||||||
|
|
||||||
|
oldCountA1 = big.NewInt(0)
|
||||||
|
oldCountA2 = big.NewInt(0)
|
||||||
|
oldCountB2 = big.NewInt(0)
|
||||||
|
|
||||||
|
updatedCountA1 = big.NewInt(1)
|
||||||
|
updatedCountA2 = big.NewInt(1)
|
||||||
|
updatedCountB2 = big.NewInt(1)
|
||||||
|
|
||||||
|
SLV2CountBIncrementedAt *integration.CountIncremented
|
||||||
|
|
||||||
|
contract1Salt = "contract1SLV"
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
if !dbWrite || !watchedAddressServiceEnabled {
|
||||||
|
Skip("skipping watched address gap filling service integration tests")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("test init", func() {
|
||||||
|
// Clear out watched addresses
|
||||||
|
err := integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Deploy a GLD contract
|
||||||
|
GLD1, contractErr = integration.DeployContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Watch GLD1 contract
|
||||||
|
operation := statediff.Add
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: GLD1.Address,
|
||||||
|
CreatedAt: uint64(GLD1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Deploy two SLV contracts and update storage slots
|
||||||
|
SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, txErr = integration.IncrementCount(SLV1.Address, "A")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
SLV2, contractErr = integration.DeploySLVContract()
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
_, txErr = integration.IncrementCount(SLV2.Address, "A")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
SLV2CountBIncrementedAt, txErr = integration.IncrementCount(SLV2.Address, "B")
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Get storage slot keys
|
||||||
|
storageSlotAKey, err := integration.GetStorageSlotKey("SLVToken", "countA")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countAIndex = storageSlotAKey.Key
|
||||||
|
|
||||||
|
storageSlotBKey, err := integration.GetStorageSlotKey("SLVToken", "countB")
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countBIndex = storageSlotBKey.Key
|
||||||
|
})
|
||||||
|
|
||||||
|
defer It("test cleanup", func() {
|
||||||
|
// Destroy create2 contract
|
||||||
|
_, err := integration.DestroySLVContract(SLV1.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Clear out watched addresses
|
||||||
|
err = integration.ClearWatchedAddresses(gethRPCClient)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("previously unwatched contract watched", func() {
|
||||||
|
It("indexes state only for watched contract", func() {
|
||||||
|
// WatchedAddresses = [GLD1]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(oldCountA1.String()))
|
||||||
|
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(oldCountB2.String()))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes past state on watching a contract", func() {
|
||||||
|
// Watch SLV1 contract
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, statediff.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(oldCountB2.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("previously unwatched contract watched (different 'created_at')", func() {
|
||||||
|
It("indexes past state from 'created_at' onwards on watching a contract", func() {
|
||||||
|
// Watch SLV2 (created_at -> countB incremented) contract
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, statediff.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1, SLV2]
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(oldCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(updatedCountB2.String()))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes missing past state on watching a contract from an earlier 'created_at'", func() {
|
||||||
|
// Remove SLV2 (created_at -> countB incremented) watched contract
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2CountBIncrementedAt.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, statediff.Remove, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Watch SLV2 (created_at -> deployment) contract
|
||||||
|
args = []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV2.Address,
|
||||||
|
CreatedAt: uint64(SLV2.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr = ipldRPCClient.Call(nil, ipldMethod, statediff.Add, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV1, SLV2]
|
||||||
|
// SLV2, countA
|
||||||
|
countA2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA2 := new(big.Int).SetBytes(countA2Storage)
|
||||||
|
Expect(countA2.String()).To(Equal(updatedCountA2.String()))
|
||||||
|
|
||||||
|
// SLV2, countB
|
||||||
|
countB2Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV2.Address), common.HexToHash(countBIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countB2 := new(big.Int).SetBytes(countB2Storage)
|
||||||
|
Expect(countB2.String()).To(Equal(updatedCountB2.String()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("destroyed contract redeployed and watched", func() {
|
||||||
|
It("returns zero value for destroyed contract", func() {
|
||||||
|
_, err := integration.DestroySLVContract(SLV1.Address)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
updatedCountA1 = big.NewInt(0)
|
||||||
|
|
||||||
|
operation := statediff.Remove
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV2]
|
||||||
|
// SLV1, countA
|
||||||
|
countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
oldCountA1.Set(updatedCountA1)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("indexes state for redeployed contract", func() {
|
||||||
|
// Redeploy contract
|
||||||
|
SLV1, contractErr = integration.Create2Contract("SLVToken", contract1Salt)
|
||||||
|
Expect(contractErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Add to watched address
|
||||||
|
operation := statediff.Add
|
||||||
|
args := []sdtypes.WatchAddressArg{
|
||||||
|
{
|
||||||
|
Address: SLV1.Address,
|
||||||
|
CreatedAt: uint64(SLV1.BlockNumber),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ipldErr := ipldRPCClient.Call(nil, ipldMethod, operation, args)
|
||||||
|
Expect(ipldErr).ToNot(HaveOccurred())
|
||||||
|
|
||||||
|
// Sleep for service interval + few extra seconds
|
||||||
|
time.Sleep(time.Duration(serviceInterval+2) * time.Second)
|
||||||
|
|
||||||
|
// WatchedAddresses = [GLD1, SLV2, SLV1]
|
||||||
|
// SLV1, countA
|
||||||
|
|
||||||
|
// TODO: Fix old storage value fetched after redeploying to same address.
|
||||||
|
// countA1Storage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
// Expect(err).ToNot(HaveOccurred())
|
||||||
|
// countA1 := new(big.Int).SetBytes(countA1Storage)
|
||||||
|
// Expect(countA1.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
// oldCountA1.Set(updatedCountA1)
|
||||||
|
|
||||||
|
// Update storage slots
|
||||||
|
_, txErr = integration.IncrementCount(SLV1.Address, "A")
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
Expect(txErr).ToNot(HaveOccurred())
|
||||||
|
updatedCountA1.Add(updatedCountA1, big.NewInt(1))
|
||||||
|
|
||||||
|
countA1AfterIncrementStorage, err := ipldClient.StorageAt(ctx, common.HexToAddress(SLV1.Address), common.HexToHash(countAIndex), nil)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
countA1AfterIncrement := new(big.Int).SetBytes(countA1AfterIncrementStorage)
|
||||||
|
Expect(countA1AfterIncrement.String()).To(Equal(updatedCountA1.String()))
|
||||||
|
oldCountA1.Set(updatedCountA1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user