diff --git a/.github/workflows/dependency-updates.yml b/.github/workflows/dependency-updates.yml index 52ac166c6..e7219013d 100644 --- a/.github/workflows/dependency-updates.yml +++ b/.github/workflows/dependency-updates.yml @@ -16,7 +16,7 @@ jobs: # outputs echo "name=bump/solana-$image" >> "$GITHUB_OUTPUT" echo "prTitle=[automated] bump solana image to $image" >> "$GITHUB_OUTPUT" - echo "prBody=(run CI by closing + reopening PR) Latest Solana mainnet release is [$image](https://github.com/solana-labs/solana/releases/latest)" >> "$GITHUB_OUTPUT" + echo "prBody=Latest Solana mainnet release is [$image](https://github.com/solana-labs/solana/releases/latest)" >> "$GITHUB_OUTPUT" echo "commitString=[automated] bump solana dependencies" >> "$GITHUB_OUTPUT" secrets: inherit E2E-Testing-Dependencies: @@ -48,6 +48,6 @@ jobs: # outputs echo "name=bump/e2e-deps-$coreVersion" >> "$GITHUB_OUTPUT" echo "prTitle=[automated] bump e2e test deps to match chainlink/integration-tests" >> "$GITHUB_OUTPUT" - echo "prBody=(run CI by closing + reopening PR) chainlink/integration-tests uses chainlink-testing-framework@$coreVersion" >> "$GITHUB_OUTPUT" + echo "prBody=chainlink/integration-tests uses chainlink-testing-framework@$coreVersion" >> "$GITHUB_OUTPUT" echo "commitString=[automated] bump e2e <> core/integration-tests dependencies" >> "$GITHUB_OUTPUT" secrets: inherit diff --git a/.github/workflows/open-pr.yml b/.github/workflows/open-pr.yml index f9f1fc20a..1da1285af 100644 --- a/.github/workflows/open-pr.yml +++ b/.github/workflows/open-pr.yml @@ -12,6 +12,9 @@ on: jobs: create-commits-and-pr: + permissions: + id-token: write + contents: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # checkout branch that it is called from @@ -63,6 +66,14 @@ jobs: git reset --hard git branch --set-upstream-to=origin/${{ steps.run.outputs.name }} git pull + - name: Setup GitHub Token + if: '!steps.check.outputs.skip' + id: token + uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_SOLANA_CICD_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_RELENG_TEAM_GATI_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} - name: Create pull request if: '!steps.check.outputs.skip' uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 # v6.0.0 @@ -72,3 +83,4 @@ jobs: branch: ${{ steps.run.outputs.name }} reviewers: ${{ inputs.reviewers }} body: ${{ steps.run.outputs.prBody }} + token: ${{ steps.token.outputs.access-token }} diff --git a/.github/workflows/upstream-tracker.yml b/.github/workflows/upstream-tracker.yml new file mode 100644 index 000000000..4c068f603 --- /dev/null +++ b/.github/workflows/upstream-tracker.yml @@ -0,0 +1,33 @@ +name: UpstreamTracker +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 1' # check monday at midnight UTC + +jobs: + SIMD-Update-Checker: + runs-on: ubuntu-latest + steps: + - name: Check For Updates In Past Week + id: updates + run: | + # new PRs + OPEN=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state=open\&per_page=100 | jq --arg t "$(date -d '7 days ago' +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + # macos + # OPEN=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state\=open\&per_page\=100 | jq --arg t "$(date -v-7d +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + + # closed PRs + CLOSED=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state=closed\&per_page=100 | jq --arg t "$(date -d '7 days ago' +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + # macos + # CLOSED=$(curl https://api.github.com/repos/solana-foundation/solana-improvement-documents/pulls\?state\=closed\&per_page\=100 | jq --arg t "$(date -v-7d +%s)" -r '.[] | select (.created_at | . == null or fromdateiso8601 > ($t|tonumber)) | "- \(.html_url)"') + + echo "open=$OPEN" >> "$GITHUB_OUTPUT" + echo "closed=$CLOSED" >> "$GITHUB_OUTPUT" + - uses: actions/checkout@v3 + if: steps.updates.outputs.open || steps.updates.outputs.closed + - name: Open Issue + if: steps.updates.outputs.open || steps.updates.outputs.closed + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # TODO: update tagged to team + run: gh issue create -a aalu1418 -t "SIMD Updates - $(date)" -l "[auto] SIMD Updates" -b $'## Opened\n${{ steps.updates.outputs.open}}\n\n## Closed\n${{ steps.updates.outputs.closed}}' diff --git a/go.mod b/go.mod index 92e546feb..0d485b698 100644 --- a/go.mod +++ b/go.mod @@ -8,19 +8,21 @@ require ( github.com/gagliardetto/gofuzz v1.2.2 github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 github.com/gagliardetto/treeout v0.1.4 + github.com/gagliardetto/utilz v0.1.1 github.com/google/uuid v1.3.1 - github.com/hashicorp/go-plugin v1.5.2 + github.com/hashicorp/go-plugin v1.6.0 + github.com/mitchellh/mapstructure v1.5.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 github.com/smartcontractkit/libocr v0.0.0-20240112202000-6359502d2ff1 - github.com/stretchr/testify v1.8.4 - github.com/test-go/testify v1.1.4 + github.com/stretchr/testify v1.9.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 + golang.org/x/text v0.14.0 gopkg.in/guregu/null.v4 v4.0.0 ) @@ -32,6 +34,7 @@ require ( github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blendle/zapdriver v1.3.1 // indirect + github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/confluentinc/confluent-kafka-go/v2 v2.3.0 // indirect @@ -47,16 +50,20 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect - github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.15 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/linkedin/goavro/v2 v2.12.0 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/miekg/dns v1.1.35 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -70,9 +77,11 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/riferrei/srclient v0.5.4 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -93,11 +102,11 @@ require ( golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ff155ba26..d3874d791 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,8 @@ github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHf github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4= +github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= @@ -105,6 +107,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -142,10 +145,13 @@ github.com/gagliardetto/binary v0.7.1 h1:6ggDQ26vR+4xEvl/S13NcdLK3MUCi4oSy73pS9a github.com/gagliardetto/binary v0.7.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= +github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27 h1:q2IztKyRQUxJ6abXRsawaBtvDFvM+szj4jDqV4od1gs= github.com/gagliardetto/solana-go v1.4.1-0.20220428092759-5250b4abbb27/go.mod h1:NFuoDwHPvw858ZMHUJr6bkhN8qHt4x6e+U3EYHxAwNY= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= +github.com/gagliardetto/utilz v0.1.1/go.mod h1:b+rGFkRHz3HWJD0RYMzat47JyvbTtpE0iEcYTRJTLLA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -244,6 +250,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= +github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -267,8 +275,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -328,6 +336,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -380,6 +390,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -410,10 +421,13 @@ github.com/riferrei/srclient v0.5.4 h1:dfwyR5u23QF7beuVl2WemUY2KXh5+Sc4DHKyPXBNY github.com/riferrei/srclient v0.5.4/go.mod h1:vbkLmWcgYa7JgfPvuy/+K8fTS0p1bApqadxrxi/S1MI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= @@ -424,8 +438,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4 h1:Yk0RK9WV59ISOZZMsdtxZBAKaBfdgb05oXyca/qSqcw= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240213113935-001c2f4befd4/go.mod h1:pRlQrvcizMmuHAUV4N96oO2e3XbA99JCQELLc6ES160= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498 h1:WeLb67RVd0lqdbm8qJ/LqrcfoLr7PoMjzi9wGy7ocqc= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240312172711-7ec0dab0a498/go.mod h1:8sn4HEfG8lR/D1Ov0yPHsY4kOleDKZKh2r8Op4oaAFE= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= @@ -447,8 +461,9 @@ github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -459,8 +474,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= @@ -540,6 +556,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= @@ -637,6 +654,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -658,6 +676,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -692,6 +711,7 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= @@ -879,6 +899,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/integration-tests/common/test_common.go b/integration-tests/common/test_common.go index 16c129345..59db94fc4 100644 --- a/integration-tests/common/test_common.go +++ b/integration-tests/common/test_common.go @@ -190,7 +190,7 @@ func (m *OCRv2TestState) DeployCluster(contractsDir string) { } else { env, err := test_env.NewTestEnv() require.NoError(m.T, err) - sol := test_env_sol.NewSolana([]string{env.Network.Name}) + sol := test_env_sol.NewSolana([]string{env.DockerNetwork.Name}) err = sol.StartContainer() require.NoError(m.T, err) m.Common.SolanaUrl = sol.InternalHttpUrl diff --git a/integration-tests/docker/test_env/sol.go b/integration-tests/docker/test_env/sol.go index d7edb2805..d2f83818b 100644 --- a/integration-tests/docker/test_env/sol.go +++ b/integration-tests/docker/test_env/sol.go @@ -157,7 +157,7 @@ func (ms *Solana) getContainerRequest(inactiveFeatures InactiveFeatures) (*tc.Co return &tc.ContainerRequest{ Name: ms.ContainerName, - Image: "solanalabs/solana:v1.17.25", + Image: "solanalabs/solana:v1.17.28", ExposedPorts: []string{test_env.NatPortFormat(SOL_HTTP_PORT), test_env.NatPortFormat(SOL_WS_PORT)}, Env: map[string]string{ "SERVER_PORT": "1080", diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b9cdee810..fec496004 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -8,20 +8,20 @@ require ( github.com/ethereum/go-ethereum v1.13.8 github.com/gagliardetto/binary v0.7.7 github.com/gagliardetto/solana-go v1.8.3 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.6.0 github.com/lib/pq v1.10.9 github.com/onsi/gomega v1.30.0 github.com/rs/zerolog v1.30.0 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e - github.com/smartcontractkit/chainlink-testing-framework v1.23.6 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2 - github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2 - github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a - github.com/stretchr/testify v1.8.4 - github.com/testcontainers/testcontainers-go v0.23.0 + github.com/smartcontractkit/chainlink-testing-framework v1.27.8 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216 + github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216 + github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.28.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.21.0 golang.org/x/exp v0.0.0-20240213143201-ec583247a57a golang.org/x/sync v0.6.0 gopkg.in/guregu/null.v4 v4.0.0 @@ -55,11 +55,12 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.1 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/NethermindEth/juno v0.3.1 // indirect + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect @@ -67,7 +68,9 @@ require ( github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect @@ -96,7 +99,7 @@ require ( github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/containerd v1.7.7 // indirect + github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/continuity v0.4.3 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -123,10 +126,12 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.7+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/docker v25.0.2+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dominikbraun/graph v0.23.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect @@ -158,7 +163,7 @@ require ( github.com/go-kit/log v0.2.1 // indirect github.com/go-ldap/ldap/v3 v3.4.6 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/analysis v0.21.4 // indirect @@ -187,7 +192,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic v0.6.9 // indirect @@ -210,8 +215,8 @@ require ( github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.0.4 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.4 // indirect + github.com/grafana/pyroscope-go v1.1.1 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -223,7 +228,7 @@ require ( github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/consul/api v1.25.1 // indirect - github.com/hashicorp/consul/sdk v0.14.1 // indirect + github.com/hashicorp/consul/sdk v0.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect @@ -232,6 +237,7 @@ require ( github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect @@ -247,14 +253,15 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.1 // indirect + github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackc/pgx/v4 v4.18.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect @@ -265,7 +272,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.3 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -295,10 +302,12 @@ require ( github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect @@ -306,6 +315,8 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/naoina/go-stringutil v0.1.0 // indirect + github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -345,19 +356,19 @@ require ( github.com/segmentio/ksuid v1.0.4 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v3 v3.23.11 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/slack-go/slack v0.12.2 // indirect - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 // indirect + github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect - github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect + github.com/smartcontractkit/seth v0.1.2 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wasp v0.4.5 // indirect @@ -372,12 +383,13 @@ require ( github.com/spf13/viper v1.16.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect + github.com/test-go/testify v1.1.4 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -393,6 +405,7 @@ require ( github.com/umbracle/ethgo v0.1.3 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.1.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -410,25 +423,25 @@ require ( go.opentelemetry.io/collector/semconv v0.87.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/ratelimit v0.2.0 // indirect + go.uber.org/ratelimit v0.3.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.18.0 // indirect @@ -439,8 +452,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect - gopkg.in/guregu/null.v2 v2.1.2 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect @@ -464,7 +476,7 @@ require ( sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( @@ -483,8 +495,6 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - github.com/testcontainers/testcontainers-go => github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 - // K8s imports are weird k8s.io/api => k8s.io/api v0.25.11 k8s.io/client-go => k8s.io/client-go v0.25.11 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e81748fbb..0fcb95925 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -130,8 +130,12 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= -github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -139,8 +143,6 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56 h1:HItfr1XKD/4xnsJE56m3uxnkMQ9lbg8xDnkf9qoZCH0= -github.com/Tofel/testcontainers-go v0.0.0-20231130110817-e6fbf9498b56/go.mod h1:ICriE9bLX5CLxL9OFQ2N+2N+f+803LNJ1utJb1+Inx0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= @@ -167,7 +169,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -195,9 +196,13 @@ github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3s github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -299,8 +304,8 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= -github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -392,17 +397,21 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/digitalocean/godo v1.104.1 h1:SZNxjAsskM/su0YW9P8Wx3gU0W1Z13b6tZlYNpl5BnA= github.com/digitalocean/godo v1.104.1/go.mod h1:VAI/L5YDzMuPRU01lEEUSQ/sp5Z//1HnnFv/RBTEdbg= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= +github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= +github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -522,8 +531,8 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= @@ -686,8 +695,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -755,8 +764,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -795,10 +804,10 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMHC7Bm0= -github.com/grafana/pyroscope-go v1.0.4/go.mod h1:0d7ftwSMBV/Awm7CCiYmHQEG8Y44Ma3YSjt+nWcWztY= -github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk= -github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko= +github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= +github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= +github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= +github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= @@ -832,8 +841,8 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= -github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= +github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= +github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -849,6 +858,7 @@ github.com/hashicorp/go-envparse v0.1.0 h1:bE++6bhIsNCPLvgDZkYqo3nA+/PFI51pkrHdm github.com/hashicorp/go-envparse v0.1.0/go.mod h1:OHheN1GoygLlAkTlXLXvAdnXdZxy8JUweQ1rAXx1xnc= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -862,8 +872,8 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -930,6 +940,8 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ionos-cloud/sdk-go/v6 v6.1.9 h1:Iq3VIXzeEbc8EbButuACgfLMiY5TPVWUPNrF+Vsddo4= github.com/ionos-cloud/sdk-go/v6 v6.1.9/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -942,9 +954,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= -github.com/jackc/pgconn v1.14.1 h1:smbxIaZA08n6YuxEX1sDyjV/qkbtUtkH20qLkR9MUR4= -github.com/jackc/pgconn v1.14.1/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -960,8 +971,8 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= -github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= +github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= @@ -975,12 +986,11 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= -github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= +github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -1027,8 +1037,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -1163,6 +1173,8 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1175,6 +1187,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= @@ -1188,6 +1202,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= @@ -1354,6 +1372,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1373,8 +1393,8 @@ github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08O github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ= -github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -1393,36 +1413,36 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429 h1:xkejUBZhcBpBrTSfxc91Iwzadrb6SXw8ks69bHIQ9Ww= -github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240118014648-1ab6a88c9429/go.mod h1:wJmVvDf4XSjsahWtfUq3wvIAYEAuhr7oxmxYnEL/LGQ= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1 h1:MNYkjakmoKxg7L1nmfAVeFOdONaLT7E62URBpmcTh84= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240219152510-85226a0fbdc1/go.mod h1:6aXWSEQawX2oZXcPPOdxnEGufAhj7PqPKolXf6ijRGA= +github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= +github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35/go.mod h1:2I0dWdYdK6jHPnSYYy7Y7Xp7L0YTnJ3KZtkhLQflsTU= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df h1:AKjckaIV8R53dLJwoQ3VlUI56L34Ca+nkkzjR1784zY= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240327133125-eed636b9a6df/go.mod h1:u2XnvJHl7sQ9HMlRnVLsOKgV9ihk0RGIYywB12p9gQQ= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336 h1:j00D0/EqE9HRu+63v7KwUOe4ZxLc4AN5SOJFiinkkH0= -github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240214203158-47dae5de1336/go.mod h1:umLyYLRGqyIuFfGpEREZP3So6+O8iL35cCCqW+OxX5w= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= +github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.23.6 h1:krjJswtgQ/J4kBgFpC7Tyh8wSFfWiGGUsADg6BG/EGw= -github.com/smartcontractkit/chainlink-testing-framework v1.23.6/go.mod h1:lGaqSnCB36n49fZNdTGXMrxhPu9w5+2n3c9V1Fqz1hM= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8 h1:V1G4hVjztvFuY6dPfBdv53OzQ99lwLUraXH0Wapyh3Q= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2 h1:5Snvs4I/TlfEku8cjv7FlaDQxOzgb/xhlScewi1ZyD0= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240221052856-2cd4bc5508e2/go.mod h1:A6vR7K9Ps9CAQlt+2J1tAoudv+0apEdCmXmM8l6tfKg= -github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2 h1:oRhIbbpv6lYVgaRNoLbYYPVvVG78OAdPal1FusyjGsU= -github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240221052856-2cd4bc5508e2/go.mod h1:gNYKSdUUe0b6EjrnMmomnrcwHcBmwUjjKIfz0TdUjQQ= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216 h1:tJLpFGp0LhlUN6G30FwbLDYjvJkQGPB2Ca5Ij5fpS9A= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240327222022-90568911d216/go.mod h1:cD8iUq244aN237wHe0KwJYOjsCJ6TUGUJ6ukpp1Fr/w= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216 h1:9698nTCBXxy/jPn4B10eXLRfrBveRnQFK6gv2AJcOwQ= +github.com/smartcontractkit/chainlink/v2 v2.10.0-beta0.0.20240327222022-90568911d216/go.mod h1:KagwtDKSGK5L45xmFKKxlYMMSlZJVOAfM+B2CJwIqLo= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a h1:nGkZ9uXS8lPIJOi68rdftEo2c9Q8qbRAi5+XMnKobVc= -github.com/smartcontractkit/libocr v0.0.0-20240215150045-fe2ba71b2f0a/go.mod h1:kC0qmVPUaVkFqGiZMNhmRmjdphuUmeyLEdlWFOQzFWI= +github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 h1:1WFjrrVrWoQ9UpVMh7Mx4jDpzhmo1h8hFUKd9awIhIU= +github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +github.com/smartcontractkit/seth v0.1.2 h1:ImXJmniuq6yWB6b3eezjV+lkYb1GfQuaJkwRvrCfTKQ= +github.com/smartcontractkit/seth v0.1.2/go.mod h1:aOaGwrIVFG/MYaLSj9UUMyE5QJnYQoAgnxm5cKfT9Ng= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= @@ -1473,8 +1493,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1486,8 +1507,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1502,6 +1524,8 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= +github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= @@ -1553,6 +1577,8 @@ github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7E github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -1626,26 +1652,29 @@ go.opentelemetry.io/collector/pdata v1.0.0-rcv0016/go.mod h1:OdN0alYOlYhHXu6BDlG go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXnizczQpEs/gg8= go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1 h1:mMv2jG58h6ZI5t5S9QCVGdzCmAsTakMa3oxVgpSD44g= -go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.46.1/go.mod h1:oqRuNKG0upTaDPbLVCG8AD0G2ETrfDtmh7jViy7ox6M= +go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= +go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= @@ -1667,8 +1696,9 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= +go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -1711,10 +1741,9 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1943,8 +1972,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1954,8 +1983,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2182,8 +2211,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2194,8 +2223,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/guregu/null.v2 v2.1.2 h1:YOuepWdYqGnrenzPyMi+ybCjeDzjdazynbwsXXOk4i8= -gopkg.in/guregu/null.v2 v2.1.2/go.mod h1:XORrx8tyS5ZDcyUboCIxQtta/Aujk/6pfWrn9Xe33mU= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= @@ -2277,5 +2304,5 @@ sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2 sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/solana/chain_reader.go b/pkg/solana/chain_reader.go deleted file mode 100644 index 6642cf62a..000000000 --- a/pkg/solana/chain_reader.go +++ /dev/null @@ -1,74 +0,0 @@ -package solana - -import ( - "context" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -const ServiceName = "SolanaChainReader" - -type SolanaChainReaderService struct { - lggr logger.Logger - services.StateMachine -} - -var ( - _ services.Service = &SolanaChainReaderService{} - _ types.ChainReader = &SolanaChainReaderService{} -) - -// NewChainReaderService is a constructor for a new ChainReaderService for Solana. Returns a nil service on error. -func NewChainReaderService(lggr logger.Logger) (*SolanaChainReaderService, error) { - return &SolanaChainReaderService{ - lggr: logger.Named(lggr, ServiceName), - }, nil -} - -// Name implements the services.ServiceCtx interface and returns the logger service name. -func (s *SolanaChainReaderService) Name() string { - return s.lggr.Name() -} - -// Start implements the services.ServiceCtx interface and starts necessary background services. -// An error is returned if starting any internal services fails. Subsequent calls to Start return -// and error. -func (s *SolanaChainReaderService) Start(_ context.Context) error { - return s.StartOnce(ServiceName, func() error { - return nil - }) -} - -// Close implements the services.ServiceCtx interface and stops all background services and cleans -// up used resources. Subsequent calls to Close return an error. -func (s *SolanaChainReaderService) Close() error { - return s.StopOnce(ServiceName, func() error { - return nil - }) -} - -// Ready implements the services.ServiceCtx interface and returns an error if starting the service -// encountered any errors or if the service is not ready to serve requests. -func (s *SolanaChainReaderService) Ready() error { - return s.StateMachine.Ready() -} - -// HealthReport implements the services.ServiceCtx interface and returns errors for any internal -// function or service that may have failed. -func (s *SolanaChainReaderService) HealthReport() map[string]error { - return map[string]error{s.Name(): s.Healthy()} -} - -// GetLatestValue implements the types.ChainReader interface and requests and parses on-chain -// data named by the provided contract, method, and params. -func (s *SolanaChainReaderService) GetLatestValue(_ context.Context, contractName, method string, params any, returnVal any) error { - return types.UnimplementedError("GetLatestValue not available") -} - -// Bind implements the types.ChainReader interface and allows new contract bindings to be added -// to the service. -func (s *SolanaChainReaderService) Bind(_ context.Context, bindings []types.BoundContract) error { - return types.UnimplementedError("Bind not available") -} diff --git a/pkg/solana/chain_reader_test.go b/pkg/solana/chain_reader_test.go deleted file mode 100644 index 9db536a6c..000000000 --- a/pkg/solana/chain_reader_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package solana_test - -import ( - "testing" - - "github.com/test-go/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink-solana/pkg/solana" -) - -func TestSolanaChainReaderService_ServiceCtx(t *testing.T) { - t.Parallel() - - ctx := tests.Context(t) - svc, err := solana.NewChainReaderService(logger.Test(t)) - - require.NoError(t, err) - require.NotNil(t, svc) - - require.Error(t, svc.Ready()) - require.Len(t, svc.HealthReport(), 1) - require.Contains(t, svc.HealthReport(), solana.ServiceName) - require.Error(t, svc.HealthReport()[solana.ServiceName]) - - require.NoError(t, svc.Start(ctx)) - require.NoError(t, svc.Ready()) - require.Equal(t, map[string]error{solana.ServiceName: nil}, svc.HealthReport()) - - require.Error(t, svc.Start(ctx)) - - require.NoError(t, svc.Close()) - require.Error(t, svc.Ready()) - require.Error(t, svc.Close()) -} diff --git a/pkg/solana/chainreader/account_read_binding.go b/pkg/solana/chainreader/account_read_binding.go new file mode 100644 index 000000000..c1635e3a9 --- /dev/null +++ b/pkg/solana/chainreader/account_read_binding.go @@ -0,0 +1,103 @@ +package chainreader + +import ( + "context" + "fmt" + + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// BinaryDataReader provides an interface for reading bytes from a source. This is likely a wrapper +// for a solana client. +type BinaryDataReader interface { + ReadAll(context.Context, solana.PublicKey, *rpc.GetAccountInfoOpts) ([]byte, error) +} + +// accountReadBinding provides decoding and reading Solana Account data using a defined codec. The +// `idlAccount` refers to the account name in the IDL for which the codec has a type mapping. +type accountReadBinding struct { + idlAccount string + account solana.PublicKey + codec types.RemoteCodec + reader BinaryDataReader + opts *rpc.GetAccountInfoOpts +} + +func newAccountReadBinding(acct string, codec types.RemoteCodec, reader BinaryDataReader, opts *rpc.GetAccountInfoOpts) *accountReadBinding { + return &accountReadBinding{ + idlAccount: acct, + codec: codec, + reader: reader, + opts: opts, + } +} + +var _ readBinding = &accountReadBinding{} + +func (b *accountReadBinding) PreLoad(ctx context.Context, result *loadedResult) { + if result == nil { + return + } + + bts, err := b.reader.ReadAll(ctx, b.account, b.opts) + if err != nil { + result.err <- fmt.Errorf("%w: failed to get binary data", err) + + return + } + + select { + case <-ctx.Done(): + result.err <- ctx.Err() + default: + result.value <- bts + } +} + +func (b *accountReadBinding) GetLatestValue(ctx context.Context, _ any, outVal any, result *loadedResult) error { + var ( + bts []byte + err error + ) + + if result != nil { + // when preloading, the process will wait for one of three conditions: + // 1. the context ends and returns an error + // 2. bytes were loaded in the bytes channel + // 3. an error was loaded in the err channel + select { + case <-ctx.Done(): + err = ctx.Err() + case bts = <-result.value: + case err = <-result.err: + } + + if err != nil { + return err + } + } else { + if bts, err = b.reader.ReadAll(ctx, b.account, b.opts); err != nil { + return fmt.Errorf("%w: failed to get binary data", err) + } + } + + return b.codec.Decode(ctx, bts, outVal, b.idlAccount) +} + +func (b *accountReadBinding) Bind(contract types.BoundContract) error { + account, err := solana.PublicKeyFromBase58(contract.Address) + if err != nil { + return err + } + + b.account = account + + return nil +} + +func (b *accountReadBinding) CreateType(_ bool) (any, error) { + return b.codec.CreateType(b.idlAccount, false) +} diff --git a/pkg/solana/chainreader/account_read_binding_test.go b/pkg/solana/chainreader/account_read_binding_test.go new file mode 100644 index 000000000..3b391e104 --- /dev/null +++ b/pkg/solana/chainreader/account_read_binding_test.go @@ -0,0 +1,160 @@ +package chainreader + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestPreload(t *testing.T) { + t.Parallel() + + testCodec := makeTestCodec(t) + + t.Run("get latest value waits for preload", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) + + expected := testStruct{A: true, B: 42} + bts, err := testCodec.Encode(context.Background(), expected, testCodecKey) + + require.NoError(t, err) + + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything).Return(bts, nil).After(time.Second) + + ctx := context.Background() + start := time.Now() + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + + binding.PreLoad(ctx, loaded) + + var result testStruct + + err = binding.GetLatestValue(ctx, nil, &result, loaded) + elapsed := time.Since(start) + + require.NoError(t, err) + assert.GreaterOrEqual(t, elapsed, time.Second) + assert.Less(t, elapsed, 1100*time.Millisecond) + assert.Equal(t, expected, result) + }) + + t.Run("cancelled context exits preload and returns error on get latest value", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) + + ctx, cancel := context.WithCancelCause(context.Background()) + + // make the readall pause until after the context is cancelled + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything). + Return([]byte{}, nil). + After(600 * time.Millisecond) + + expectedErr := errors.New("test error") + go func() { + time.Sleep(500 * time.Millisecond) + cancel(expectedErr) + }() + + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + start := time.Now() + binding.PreLoad(ctx, loaded) + + var result testStruct + err := binding.GetLatestValue(ctx, nil, &result, loaded) + elapsed := time.Since(start) + + assert.ErrorIs(t, err, ctx.Err()) + assert.ErrorIs(t, context.Cause(ctx), expectedErr) + assert.GreaterOrEqual(t, elapsed, 600*time.Millisecond) + assert.Less(t, elapsed, 700*time.Millisecond) + }) + + t.Run("error from preload is returned in get latest value", func(t *testing.T) { + t.Parallel() + + reader := new(mockReader) + binding := newAccountReadBinding(testCodecKey, testCodec, reader, nil) + ctx := context.Background() + expectedErr := errors.New("test error") + + reader.On("ReadAll", mock.Anything, mock.Anything, mock.Anything). + Return([]byte{}, expectedErr) + + loaded := &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + binding.PreLoad(ctx, loaded) + + var result testStruct + err := binding.GetLatestValue(ctx, nil, &result, loaded) + + assert.ErrorIs(t, err, expectedErr) + }) +} + +type mockReader struct { + mock.Mock +} + +func (_m *mockReader) ReadAll(ctx context.Context, pk solana.PublicKey, opts *rpc.GetAccountInfoOpts) ([]byte, error) { + ret := _m.Called(ctx, pk) + + var r0 []byte + if val, ok := ret.Get(0).([]byte); ok { + r0 = val + } + + var r1 error + if fn, ok := ret.Get(1).(func() error); ok { + r1 = fn() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type testStruct struct { + A bool + B int64 +} + +const testCodecKey = "TEST" + +func makeTestCodec(t *testing.T) types.RemoteCodec { + t.Helper() + + builder := binary.LittleEndian() + + structCodec, err := encodings.NewStructCodec([]encodings.NamedTypeCodec{ + {Name: "A", Codec: builder.Bool()}, + {Name: "B", Codec: builder.Int64()}, + }) + + require.NoError(t, err) + + return encodings.CodecFromTypeCodec(map[string]encodings.TypeCodec{testCodecKey: structCodec}) +} diff --git a/pkg/solana/chainreader/bindings.go b/pkg/solana/chainreader/bindings.go new file mode 100644 index 000000000..3e96f3be9 --- /dev/null +++ b/pkg/solana/chainreader/bindings.go @@ -0,0 +1,151 @@ +package chainreader + +import ( + "context" + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +type readBinding interface { + PreLoad(context.Context, *loadedResult) + GetLatestValue(ctx context.Context, params, returnVal any, preload *loadedResult) error + Bind(types.BoundContract) error + CreateType(bool) (any, error) +} + +// key is namespace +type namespaceBindings map[string]methodBindings + +// key is method name +type methodBindings map[string]readBindings + +// read bindings is a list of bindings by index +type readBindings []readBinding + +func (b namespaceBindings) AddReadBinding(namespace, methodName string, reader readBinding) { + nbs, nbsExists := b[namespace] + if !nbsExists { + nbs = methodBindings{} + b[namespace] = nbs + } + + rbs, rbsExists := nbs[methodName] + if !rbsExists { + rbs = []readBinding{} + } + + b[namespace][methodName] = append(rbs, reader) +} + +func (b namespaceBindings) GetReadBindings(namespace, methodName string) ([]readBinding, error) { + nbs, nbsExists := b[namespace] + if !nbsExists { + return nil, fmt.Errorf("%w: no read binding exists for %s", types.ErrInvalidConfig, namespace) + } + + rbs, rbsExists := nbs[methodName] + if !rbsExists { + return nil, fmt.Errorf("%w: no read binding exists for %s and %s", types.ErrInvalidConfig, namespace, methodName) + } + + return rbs, nil +} + +func (b namespaceBindings) CreateType(namespace, methodName string, forEncoding bool) (any, error) { + bindings, err := b.GetReadBindings(namespace, methodName) + if err != nil { + return nil, err + } + + if len(bindings) == 1 { + // get the item type from the binding codec + return bindings[0].CreateType(forEncoding) + } + + // build a merged struct from all bindings + fields := make([]reflect.StructField, 0) + var fieldIdx int + fieldNames := make(map[string]struct{}) + + for _, binding := range bindings { + bindingType, err := binding.CreateType(forEncoding) + if err != nil { + return nil, err + } + + tBinding := reflect.TypeOf(bindingType) + if tBinding.Kind() == reflect.Pointer { + tBinding = tBinding.Elem() + } + + // all bindings must be structs to allow multiple bindings + if tBinding.Kind() != reflect.Struct { + return nil, fmt.Errorf("%w: support for multiple bindings only applies to all bindings having the type struct", types.ErrInvalidType) + } + + for idx := 0; idx < tBinding.NumField(); idx++ { + value := tBinding.FieldByIndex([]int{idx}) + + _, exists := fieldNames[value.Name] + if exists { + return nil, fmt.Errorf("%w: field name overlap on %s", types.ErrInvalidConfig, value.Name) + } + + field := reflect.StructField{ + Name: value.Name, + Type: value.Type, + Index: []int{fieldIdx}, + } + + fields = append(fields, field) + + fieldIdx++ + fieldNames[value.Name] = struct{}{} + } + } + + return reflect.New(reflect.StructOf(fields)).Interface(), nil +} + +func (b namespaceBindings) Bind(boundContracts []types.BoundContract) error { + for _, bc := range boundContracts { + parts := strings.Split(bc.Name, ".") + if len(parts) != 3 { + return fmt.Errorf("%w: BoundContract.Name must follow pattern of [namespace.method.procedure_idx]", types.ErrInvalidConfig) + } + + nbs, nbsExist := b[parts[0]] + if !nbsExist { + return fmt.Errorf("%w: no namespace named %s for %s", types.ErrInvalidConfig, parts[0], bc.Name) + } + + mbs, mbsExists := nbs[parts[1]] + if !mbsExists { + return fmt.Errorf("%w: no method named %s for %s", types.ErrInvalidConfig, parts[1], bc.Name) + } + + val, err := strconv.Atoi(parts[2]) + if err != nil { + return fmt.Errorf("%w: procedure index not parsable for %s", types.ErrInvalidConfig, bc.Name) + } + + if len(mbs) <= val { + return fmt.Errorf("%w: no procedure for index %d for %s", types.ErrInvalidConfig, val, bc.Name) + } + + if err := mbs[val].Bind(bc); err != nil { + return err + } + } + + return nil +} + +type loadedResult struct { + value chan []byte + err chan error +} diff --git a/pkg/solana/chainreader/bindings_test.go b/pkg/solana/chainreader/bindings_test.go new file mode 100644 index 000000000..94b3632a5 --- /dev/null +++ b/pkg/solana/chainreader/bindings_test.go @@ -0,0 +1,122 @@ +package chainreader + +import ( + "context" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func TestBindings_CreateType(t *testing.T) { + t.Parallel() + + t.Run("single binding returns type", func(t *testing.T) { + t.Parallel() + + expected := 8 + binding := new(mockBinding) + bindings := namespaceBindings{} + bindings.AddReadBinding("A", "B", binding) + + binding.On("CreateType", mock.Anything).Return(expected, nil) + + returned, err := bindings.CreateType("A", "B", true) + + require.NoError(t, err) + assert.Equal(t, expected, returned) + }) + + t.Run("multiple bindings return merged struct", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + bindingA.On("CreateType", mock.Anything).Return(struct{ A string }{A: "test"}, nil) + bindingB.On("CreateType", mock.Anything).Return(struct{ B int }{B: 8}, nil) + + result, err := bindings.CreateType("A", "B", true) + + expected := reflect.New(reflect.StructOf([]reflect.StructField{ + {Name: "A", Type: reflect.TypeOf("")}, + {Name: "B", Type: reflect.TypeOf(0)}, + })) + + require.NoError(t, err) + assert.Equal(t, expected.Type(), reflect.TypeOf(result)) + }) + + t.Run("multiple bindings fails when not a struct", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + bindingA.On("CreateType", mock.Anything).Return(8, nil) + bindingB.On("CreateType", mock.Anything).Return(struct{ A string }{A: "test"}, nil) + + _, err := bindings.CreateType("A", "B", true) + + require.ErrorIs(t, err, types.ErrInvalidType) + }) + + t.Run("multiple bindings errors when fields overlap", func(t *testing.T) { + t.Parallel() + + bindingA := new(mockBinding) + bindingB := new(mockBinding) + bindings := namespaceBindings{} + + bindings.AddReadBinding("A", "B", bindingA) + bindings.AddReadBinding("A", "B", bindingB) + + type A struct { + A string + B int + } + + type B struct { + A int + } + + bindingA.On("CreateType", mock.Anything).Return(A{A: ""}, nil) + bindingB.On("CreateType", mock.Anything).Return(B{A: 8}, nil) + + _, err := bindings.CreateType("A", "B", true) + + require.ErrorIs(t, err, types.ErrInvalidConfig) + }) +} + +type mockBinding struct { + mock.Mock +} + +func (_m *mockBinding) PreLoad(context.Context, *loadedResult) {} + +func (_m *mockBinding) GetLatestValue(ctx context.Context, params, returnVal any, _ *loadedResult) error { + return nil +} + +func (_m *mockBinding) Bind(types.BoundContract) error { + return nil +} + +func (_m *mockBinding) CreateType(b bool) (any, error) { + ret := _m.Called(b) + + return ret.Get(0), ret.Error(1) +} diff --git a/pkg/solana/chainreader/chain_reader.go b/pkg/solana/chainreader/chain_reader.go new file mode 100644 index 000000000..b52c72bb5 --- /dev/null +++ b/pkg/solana/chainreader/chain_reader.go @@ -0,0 +1,256 @@ +package chainreader + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "sync" + + ag_solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +const ServiceName = "SolanaChainReader" + +type SolanaChainReaderService struct { + // provided values + lggr logger.Logger + client BinaryDataReader + + // internal values + bindings namespaceBindings + + // service state management + wg sync.WaitGroup + services.StateMachine +} + +var ( + _ services.Service = &SolanaChainReaderService{} + _ types.ChainReader = &SolanaChainReaderService{} +) + +// NewChainReaderService is a constructor for a new ChainReaderService for Solana. Returns a nil service on error. +func NewChainReaderService(lggr logger.Logger, dataReader BinaryDataReader, cfg config.ChainReader) (*SolanaChainReaderService, error) { + svc := &SolanaChainReaderService{ + lggr: logger.Named(lggr, ServiceName), + client: dataReader, + bindings: namespaceBindings{}, + } + + if err := svc.init(cfg.Namespaces); err != nil { + return nil, err + } + + return svc, nil +} + +// Name implements the services.ServiceCtx interface and returns the logger service name. +func (s *SolanaChainReaderService) Name() string { + return s.lggr.Name() +} + +// Start implements the services.ServiceCtx interface and starts necessary background services. +// An error is returned if starting any internal services fails. Subsequent calls to Start return +// and error. +func (s *SolanaChainReaderService) Start(_ context.Context) error { + return s.StartOnce(ServiceName, func() error { + return nil + }) +} + +// Close implements the services.ServiceCtx interface and stops all background services and cleans +// up used resources. Subsequent calls to Close return an error. +func (s *SolanaChainReaderService) Close() error { + return s.StopOnce(ServiceName, func() error { + s.wg.Wait() + + return nil + }) +} + +// Ready implements the services.ServiceCtx interface and returns an error if starting the service +// encountered any errors or if the service is not ready to serve requests. +func (s *SolanaChainReaderService) Ready() error { + return s.StateMachine.Ready() +} + +// HealthReport implements the services.ServiceCtx interface and returns errors for any internal +// function or service that may have failed. +func (s *SolanaChainReaderService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +// GetLatestValue implements the types.ChainReader interface and requests and parses on-chain +// data named by the provided contract, method, and params. +func (s *SolanaChainReaderService) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { + if err := s.Ready(); err != nil { + return err + } + + s.wg.Add(1) + defer s.wg.Done() + + bindings, err := s.bindings.GetReadBindings(contractName, method) + if err != nil { + return err + } + + localCtx, localCancel := context.WithCancel(ctx) + + // the wait group ensures GetLatestValue returns only after all go-routines have completed + var wg sync.WaitGroup + + results := make(map[int]*loadedResult) + + if len(bindings) > 1 { + // might go for some guardrails when dealing with multiple bindings + // the returnVal should be compatible with multiple passes by the codec decoder + // this should only apply to types struct{} and map[any]any + tReturnVal := reflect.TypeOf(returnVal) + if tReturnVal.Kind() == reflect.Pointer { + tReturnVal = reflect.Indirect(reflect.ValueOf(returnVal)).Type() + } + + switch tReturnVal.Kind() { + case reflect.Struct, reflect.Map: + default: + localCancel() + + wg.Wait() + + return fmt.Errorf("%w: multiple bindings is only supported for struct and map", types.ErrInvalidType) + } + + // for multiple bindings, preload the remote data in parallel + for idx, binding := range bindings { + results[idx] = &loadedResult{ + value: make(chan []byte, 1), + err: make(chan error, 1), + } + + wg.Add(1) + go func(ctx context.Context, rb readBinding, res *loadedResult) { + defer wg.Done() + + rb.PreLoad(ctx, res) + }(localCtx, binding, results[idx]) + } + } + + // in the case of parallel preloading, GetLatestValue will still run in + // sequence because the function will block until the data is loaded. + // in the case of no preloading, GetLatestValue will load and decode in + // sequence. + for idx, binding := range bindings { + if err := binding.GetLatestValue(ctx, params, returnVal, results[idx]); err != nil { + localCancel() + + wg.Wait() + + return err + } + } + + localCancel() + + wg.Wait() + + return nil +} + +// Bind implements the types.ChainReader interface and allows new contract bindings to be added +// to the service. +func (s *SolanaChainReaderService) Bind(_ context.Context, bindings []types.BoundContract) error { + return s.bindings.Bind(bindings) +} + +// CreateContractType implements the ContractTypeProvider interface and allows the chain reader +// service to explicitly define the expected type for a grpc server to provide. +func (s *SolanaChainReaderService) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { + return s.bindings.CreateType(contractName, itemType, forEncoding) +} + +func (s *SolanaChainReaderService) init(namespaces map[string]config.ChainReaderMethods) error { + for namespace, methods := range namespaces { + for methodName, method := range methods.Methods { + var idl codec.IDL + if err := json.Unmarshal([]byte(method.AnchorIDL), &idl); err != nil { + return err + } + + idlCodec, err := codec.NewIDLCodec(idl, config.BuilderForEncoding(method.Encoding)) + if err != nil { + return err + } + + for _, procedure := range method.Procedures { + mod, err := procedure.OutputModifications.ToModifier(codec.DecoderHooks...) + if err != nil { + return err + } + + codecWithModifiers, err := codec.NewNamedModifierCodec(idlCodec, procedure.IDLAccount, mod) + if err != nil { + return err + } + + s.bindings.AddReadBinding(namespace, methodName, newAccountReadBinding( + procedure.IDLAccount, + codecWithModifiers, + s.client, + createRPCOpts(procedure.RPCOpts), + )) + } + } + } + + return nil +} + +func createRPCOpts(opts *config.RPCOpts) *rpc.GetAccountInfoOpts { + if opts == nil { + return nil + } + + result := &rpc.GetAccountInfoOpts{ + DataSlice: opts.DataSlice, + } + + if opts.Encoding != nil { + result.Encoding = *opts.Encoding + } + + if opts.Commitment != nil { + result.Commitment = *opts.Commitment + } + + return result +} + +type accountDataReader struct { + client *rpc.Client +} + +func NewAccountDataReader(client *rpc.Client) *accountDataReader { + return &accountDataReader{client: client} +} + +func (r *accountDataReader) ReadAll(ctx context.Context, pk ag_solana.PublicKey, opts *rpc.GetAccountInfoOpts) ([]byte, error) { + result, err := r.client.GetAccountInfoWithOpts(ctx, pk, opts) + if err != nil { + return nil, err + } + + bts := result.Value.Data.GetBinary() + + return bts, nil +} diff --git a/pkg/solana/chainreader/chain_reader_test.go b/pkg/solana/chainreader/chain_reader_test.go new file mode 100644 index 000000000..dd4b4ebc7 --- /dev/null +++ b/pkg/solana/chainreader/chain_reader_test.go @@ -0,0 +1,820 @@ +package chainreader_test + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/gagliardetto/solana-go" + ag_solana "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" + "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/chainreader" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +const ( + Namespace = "NameSpace" + NamedMethod = "NamedMethod1" +) + +func TestSolanaChainReaderService_ReaderInterface(t *testing.T) { + t.Parallel() + + it := &chainReaderInterfaceTester{} + RunChainReaderInterfaceTests(t, it) + RunChainReaderInterfaceTests(t, commontestutils.WrapChainReaderTesterForLoop(it)) +} + +func TestSolanaChainReaderService_ServiceCtx(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + svc, err := chainreader.NewChainReaderService(logger.Test(t), new(mockedRPCClient), config.ChainReader{}) + + require.NoError(t, err) + require.NotNil(t, svc) + + require.Error(t, svc.Ready()) + require.Len(t, svc.HealthReport(), 1) + require.Contains(t, svc.HealthReport(), chainreader.ServiceName) + require.Error(t, svc.HealthReport()[chainreader.ServiceName]) + + require.NoError(t, svc.Start(ctx)) + require.NoError(t, svc.Ready()) + require.Equal(t, map[string]error{chainreader.ServiceName: nil}, svc.HealthReport()) + + require.Error(t, svc.Start(ctx)) + + require.NoError(t, svc.Close()) + require.Error(t, svc.Ready()) + require.Error(t, svc.Close()) +} + +func TestSolanaChainReaderService_GetLatestValue(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + + // encode values from unmodified test struct to be read and decoded + expected := testutils.DefaultTestStruct + + t.Run("Success", func(t *testing.T) { + t.Parallel() + + testCodec, conf := newTestConfAndCodec(t) + encoded, err := testCodec.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + + require.NoError(t, err) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + client.SetNext(encoded, nil, 0) + + var result modifiedStructWithNestedStruct + + require.NoError(t, svc.GetLatestValue(ctx, Namespace, NamedMethod, nil, &result)) + assert.Equal(t, expected.InnerStruct, result.InnerStruct) + assert.Equal(t, expected.Value, result.V) + assert.Equal(t, expected.TimeVal, result.TimeVal) + assert.Equal(t, expected.DurationVal, result.DurationVal) + }) + + t.Run("Error Returned From Account Reader", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + expectedErr := fmt.Errorf("expected error") + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + client.SetNext(nil, expectedErr, 0) + + var result modifiedStructWithNestedStruct + + assert.ErrorIs(t, svc.GetLatestValue(ctx, Namespace, NamedMethod, nil, &result), expectedErr) + }) + + t.Run("Method Not Found", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + var result modifiedStructWithNestedStruct + + assert.NotNil(t, svc.GetLatestValue(ctx, Namespace, "Unknown", nil, &result)) + }) + + t.Run("Namespace Not Found", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + var result modifiedStructWithNestedStruct + + assert.NotNil(t, svc.GetLatestValue(ctx, "Unknown", "Unknown", nil, &result)) + }) + + t.Run("Bind Success", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + pk := ag_solana.NewWallet().PublicKey() + err = svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 0), + }, + }) + + assert.NoError(t, err) + }) + + t.Run("Bind Errors", func(t *testing.T) { + t.Parallel() + + _, conf := newTestConfAndCodec(t) + + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, conf) + + require.NoError(t, err) + require.NotNil(t, svc) + require.NoError(t, svc.Start(ctx)) + + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + pk := ag_solana.NewWallet().PublicKey() + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: "incorrect format", + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", "Unknown", "Unknown", 0), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, "Unknown", 0), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 1), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: pk.String(), + Name: fmt.Sprintf("%s.%s.o", Namespace, NamedMethod), + }, + })) + + require.NotNil(t, svc.Bind(ctx, []types.BoundContract{ + { + Address: "invalid", + Name: fmt.Sprintf("%s.%s.%d", Namespace, NamedMethod, 0), + }, + })) + }) +} + +func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTypeCodec) { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.JSONIDLWithAllTypes), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + entry, err := codec.NewIDLCodec(idl, binary.LittleEndian()) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + require.NotNil(t, entry) + + return testutils.JSONIDLWithAllTypes, idl, entry +} + +func newTestConfAndCodec(t *testing.T) (encodings.CodecFromTypeCodec, config.ChainReader) { + t.Helper() + + rawIDL, _, testCodec := newTestIDLAndCodec(t) + conf := config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + Namespace: { + Methods: map[string]config.ChainDataReader{ + NamedMethod: { + AnchorIDL: rawIDL, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.RenameModifierConfig{Fields: map[string]string{"Value": "V"}}, + }, + }, + }, + }, + }, + }, + }, + } + + return testCodec, conf +} + +type modifiedStructWithNestedStruct struct { + V uint8 + InnerStruct testutils.ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []testutils.ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 +} + +type mockedRPCCall struct { + bts []byte + err error + delay time.Duration +} + +type mockedRPCClient struct { + mu sync.Mutex + responseByAddress map[string]mockedRPCCall + sequence []mockedRPCCall +} + +func (_m *mockedRPCClient) ReadAll(_ context.Context, pk ag_solana.PublicKey, _ *rpc.GetAccountInfoOpts) ([]byte, error) { + _m.mu.Lock() + defer _m.mu.Unlock() + + if _m.responseByAddress == nil { + _m.responseByAddress = make(map[string]mockedRPCCall) + } + + if resp, ok := _m.responseByAddress[pk.String()]; ok { + if resp.delay > 0 { + time.Sleep(resp.delay) + } + + delete(_m.responseByAddress, pk.String()) + + return resp.bts, resp.err + } + + if len(_m.sequence) == 0 { + panic("no values to return") + } + + next := _m.sequence[0] + _m.sequence = _m.sequence[1:len(_m.sequence)] + + if next.delay > 0 { + time.Sleep(next.delay) + } + + return next.bts, next.err +} + +func (_m *mockedRPCClient) SetNext(bts []byte, err error, delay time.Duration) { + _m.mu.Lock() + defer _m.mu.Unlock() + + _m.sequence = append(_m.sequence, mockedRPCCall{ + bts: bts, + err: err, + delay: delay, + }) +} + +func (_m *mockedRPCClient) SetForAddress(pk ag_solana.PublicKey, bts []byte, err error, delay time.Duration) { + _m.mu.Lock() + defer _m.mu.Unlock() + + if _m.responseByAddress == nil { + _m.responseByAddress = make(map[string]mockedRPCCall) + } + + _m.responseByAddress[pk.String()] = mockedRPCCall{ + bts: bts, + err: err, + delay: delay, + } +} + +type chainReaderInterfaceTester struct { + conf config.ChainReader + address []string + reader *wrappedTestChainReader +} + +func (r *chainReaderInterfaceTester) GetAccountBytes(i int) []byte { + account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + account[i%20] += byte(i) + account[(i+3)%20] += byte(i + 3) + return account[:] +} + +func (r *chainReaderInterfaceTester) Name() string { + return "Solana" +} + +func (r *chainReaderInterfaceTester) Setup(t *testing.T) { + r.address = make([]string, 8) + for idx := range r.address { + r.address[idx] = ag_solana.NewWallet().PublicKey().String() + } + + encodingBase64 := solana.EncodingBase64 + commitment := rpc.CommitmentConfirmed + offset := uint64(1) + length := uint64(1) + + r.conf = config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + AnyContractName: { + Methods: map[string]config.ChainDataReader{ + MethodTakingLatestParamsReturningTestStruct: { + AnchorIDL: fullStructIDL(t), + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "TestStructB", + RPCOpts: &config.RPCOpts{ + Encoding: &encodingBase64, + Commitment: &commitment, + DataSlice: &rpc.DataSlice{ + Offset: &offset, + Length: &length, + }, + }, + }, + { + IDLAccount: "TestStructA", + }, + }, + }, + MethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + DifferentMethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + MethodReturningUint64Slice: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), + Encoding: config.EncodingTypeBincode, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "Uint64Slice", + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "Vals"}, + }, + }, + }, + }, + MethodReturningSeenStruct: { + AnchorIDL: fullStructIDL(t), + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "TestStructB", + }, + { + IDLAccount: "TestStructA", + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, + }, + }, + }, + }, + }, + }, + AnySecondContractName: { + Methods: map[string]config.ChainDataReader{ + MethodReturningUint64: { + AnchorIDL: fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: "SimpleUint64Value", + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "I"}, + }, + }, + }, + }, + }, + }, + }, + } +} + +func (r *chainReaderInterfaceTester) GetChainReader(t *testing.T) types.ChainReader { + client := new(mockedRPCClient) + svc, err := chainreader.NewChainReaderService(logger.Test(t), client, r.conf) + if err != nil { + t.Logf("chain reader service was not able to start: %s", err.Error()) + t.FailNow() + } + + require.NoError(t, svc.Start(context.Background())) + t.Cleanup(func() { + require.NoError(t, svc.Close()) + }) + + if r.reader == nil { + r.reader = &wrappedTestChainReader{ + test: t, + tester: r, + } + } + + r.reader.service = svc + r.reader.client = client + + return r.reader +} + +type wrappedTestChainReader struct { + test *testing.T + service *chainreader.SolanaChainReaderService + client *mockedRPCClient + tester ChainReaderInterfaceTester + testStructQueue []*TestStruct +} + +func (r *wrappedTestChainReader) GetLatestValue(ctx context.Context, contractName string, method string, params, returnVal any) error { + var ( + a ag_solana.PublicKey + b ag_solana.PublicKey + ) + switch contractName + method { + case AnyContractName + EventName: + // t.Skip won't skip the test here + // returning the expected error to satisfy the test + return types.ErrNotFound + case AnyContractName + MethodReturningUint64: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), config.EncodingTypeBorsh) + onChainStruct := struct { + I uint64 + }{ + I: AnyValueToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "SimpleUint64Value") + if err != nil { + r.test.Log(err.Error()) + r.test.FailNow() + } + + r.client.SetNext(bts, nil, 0) + case AnyContractName + MethodReturningUint64Slice: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64SliceBaseTypeIDL, ""), config.EncodingTypeBincode) + onChainStruct := struct { + Vals []uint64 + }{ + Vals: AnySliceToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "Uint64Slice") + if err != nil { + r.test.FailNow() + } + + r.client.SetNext(bts, nil, 0) + case AnySecondContractName + MethodReturningUint64, AnyContractName + DifferentMethodReturningUint64: + cdc := makeTestCodec(r.test, fmt.Sprintf(baseIDL, uint64BaseTypeIDL, ""), config.EncodingTypeBorsh) + onChainStruct := struct { + I uint64 + }{ + I: AnyDifferentValueToReadWithoutAnArgument, + } + + bts, err := cdc.Encode(ctx, onChainStruct, "SimpleUint64Value") + if err != nil { + r.test.FailNow() + } + + r.client.SetNext(bts, nil, 0) + case AnyContractName + MethodReturningSeenStruct: + nextStruct := CreateTestStruct(0, r.tester) + r.testStructQueue = append(r.testStructQueue, &nextStruct) + + a, b = getAddresses(r.test, r.tester, 5, 6) + + fallthrough + default: + if r.testStructQueue == nil || len(r.testStructQueue) == 0 { + r.test.FailNow() + } + + if contractName+method != AnyContractName+MethodReturningSeenStruct { + a, b = getAddresses(r.test, r.tester, 0, 1) + } + + nextTestStruct := r.testStructQueue[0] + r.testStructQueue = r.testStructQueue[1:len(r.testStructQueue)] + + // split into two encoded parts to test the preloading function + cdc := makeTestCodec(r.test, fullStructIDL(r.test), config.EncodingTypeBorsh) + + bts, err := cdc.Encode(ctx, nextTestStruct, "TestStructB") + if err != nil { + r.test.FailNow() + } + + // make part A return slower than part B + r.client.SetForAddress(a, bts, nil, 300*time.Millisecond) + + bts, err = cdc.Encode(ctx, nextTestStruct, "TestStructA") + if err != nil { + r.test.FailNow() + } + + r.client.SetForAddress(b, bts, nil, 50*time.Millisecond) + } + + return r.service.GetLatestValue(ctx, contractName, method, params, returnVal) +} + +func getAddresses(t *testing.T, tester ChainReaderInterfaceTester, a, b int) (ag_solana.PublicKey, ag_solana.PublicKey) { + t.Helper() + + bindings := tester.GetBindings(t) + fn := ag_solana.MustPublicKeyFromBase58 + + return fn(bindings[a].Address), fn(bindings[b].Address) +} + +func (r *wrappedTestChainReader) Bind(ctx context.Context, bindings []types.BoundContract) error { + return r.service.Bind(ctx, bindings) +} + +func (r *wrappedTestChainReader) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { + if AnyContractName+EventName == contractName+itemType { + // events are not supported, so just make the tests pass + return nil, types.ErrNotFound + } + + return r.service.CreateContractType(contractName, itemType, forEncoding) +} + +// SetLatestValue is expected to return the same bound contract and method in the same test +// Any setup required for this should be done in Setup. +// The contract should take a LatestParams as the params and return the nth TestStruct set +func (r *chainReaderInterfaceTester) SetLatestValue(t *testing.T, testStruct *TestStruct) { + if r.reader == nil { + r.reader = &wrappedTestChainReader{ + test: t, + tester: r, + } + } + + r.reader.testStructQueue = append(r.reader.testStructQueue, testStruct) +} + +func (r *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *TestStruct) { + t.Skip("Events are not yet supported in Solana") +} + +func (r *chainReaderInterfaceTester) GetBindings(t *testing.T) []types.BoundContract { + return []types.BoundContract{ + {Name: strings.Join([]string{AnyContractName, MethodTakingLatestParamsReturningTestStruct, "0"}, "."), Address: r.address[0], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodTakingLatestParamsReturningTestStruct, "1"}, "."), Address: r.address[1], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64, "0"}, "."), Address: r.address[2], Pending: true}, + {Name: strings.Join([]string{AnyContractName, DifferentMethodReturningUint64, "0"}, "."), Address: r.address[3], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningUint64Slice, "0"}, "."), Address: r.address[4], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "0"}, "."), Address: r.address[5], Pending: true}, + {Name: strings.Join([]string{AnyContractName, MethodReturningSeenStruct, "1"}, "."), Address: r.address[6], Pending: true}, + {Name: strings.Join([]string{AnySecondContractName, MethodReturningUint64, "0"}, "."), Address: r.address[7], Pending: true}, + } +} + +func (r *chainReaderInterfaceTester) MaxWaitTimeForEvents() time.Duration { + // From trial and error, when running on CI, sometimes the boxes get slow + maxWaitTime := time.Second + maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") + if ok { + wiatS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) + if err != nil { + fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) + } + maxWaitTime = time.Second * time.Duration(wiatS) + } + + return maxWaitTime +} + +func makeTestCodec(t *testing.T, rawIDL string, encoding config.EncodingType) encodings.CodecFromTypeCodec { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(rawIDL), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + testCodec, err := codec.NewIDLCodec(idl, config.BuilderForEncoding(encoding)) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + return testCodec +} + +func fullStructIDL(t *testing.T) string { + t.Helper() + + return fmt.Sprintf( + baseIDL, + strings.Join([]string{testStructAIDL, testStructBIDL}, ","), + strings.Join([]string{midLevelStructIDL, innerStructIDL}, ","), + ) +} + +const ( + baseIDL = `{ + "version": "0.1.0", + "name": "some_test_idl", + "accounts": [%s], + "types": [%s] + }` + + testStructAIDL = `{ + "name": "TestStructA", + "type": { + "kind": "struct", + "fields": [ + {"name": "field","type": {"option": "i32"}}, + {"name": "differentField","type": "string"}, + {"name": "bigField","type": "i128"}, + {"name": "nestedStruct","type": {"defined": "MidLevelStruct"}} + ] + } + }` + + testStructBIDL = `{ + "name": "TestStructB", + "type": { + "kind": "struct", + "fields": [ + {"name": "oracleID","type": "u8"}, + {"name": "oracleIDs","type": {"array": ["u8",32]}}, + {"name": "account","type": "bytes"}, + {"name": "accounts","type": {"vec": "bytes"}} + ] + } + }` + + midLevelStructIDL = `{ + "name": "MidLevelStruct", + "type": { + "kind": "struct", + "fields": [ + {"name": "fixedBytes", "type": {"array": ["u8",2]}}, + {"name": "inner", "type": {"defined": "InnerTestStruct"}} + ] + } + }` + + innerStructIDL = `{ + "name": "InnerTestStruct", + "type": { + "kind": "struct", + "fields": [ + {"name": "i", "type": "i32"}, + {"name": "s", "type": "string"} + ] + } + }` + + uint64BaseTypeIDL = `{ + "name": "SimpleUint64Value", + "type": { + "kind": "struct", + "fields": [ + {"name": "i", "type": "u64"} + ] + } + }` + + uint64SliceBaseTypeIDL = `{ + "name": "Uint64Slice", + "type": { + "kind": "struct", + "fields": [ + {"name": "vals", "type": {"vec": "u64"}} + ] + } + }` +) diff --git a/pkg/solana/codec/anchoridl.go b/pkg/solana/codec/anchoridl.go new file mode 100644 index 000000000..359409d5c --- /dev/null +++ b/pkg/solana/codec/anchoridl.go @@ -0,0 +1,403 @@ +package codec + +/* +copied from https://github.com/gagliardetto/anchor-go where the IDL definition is not importable due to being defined +in the `main` package. +*/ + +import ( + "encoding/json" + "fmt" + + "github.com/davecgh/go-spew/spew" + "github.com/gagliardetto/utilz" +) + +// https://github.com/project-serum/anchor/blob/97e9e03fb041b8b888a9876a7c0676d9bb4736f3/ts/src/idl.ts +type IDL struct { + Version string `json:"version"` + Name string `json:"name"` + Instructions []IdlInstruction `json:"instructions"` + Accounts IdlTypeDefSlice `json:"accounts,omitempty"` + Types IdlTypeDefSlice `json:"types,omitempty"` + Events []IdlEvent `json:"events,omitempty"` + Errors []IdlErrorCode `json:"errors,omitempty"` + Constants []IdlConstant `json:"constants,omitempty"` +} + +type IdlConstant struct { + Name string + Type IdlType + Value string +} + +type IdlTypeDefSlice []IdlTypeDef + +func (named IdlTypeDefSlice) GetByName(name string) *IdlTypeDef { + for i := range named { + v := named[i] + if v.Name == name { + return &v + } + } + return nil +} + +type IdlEvent struct { + Name string `json:"name"` + Fields []IdlEventField `json:"fields"` +} + +type IdlEventField struct { + Name string `json:"name"` + Type IdlType `json:"type"` + Index bool `json:"index"` +} + +type IdlInstruction struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Accounts IdlAccountItemSlice `json:"accounts"` + Args []IdlField `json:"args"` +} + +type IdlAccountItemSlice []IdlAccountItem + +func (slice IdlAccountItemSlice) NumAccounts() (count int) { + + for _, item := range slice { + if item.IdlAccount != nil { + count++ + } + + if item.IdlAccounts != nil { + count += item.IdlAccounts.Accounts.NumAccounts() + } + } + + return count +} + +// type IdlAccountItem = IdlAccount | IdlAccounts; +type IdlAccountItem struct { + IdlAccount *IdlAccount + IdlAccounts *IdlAccounts +} + +func (env *IdlAccountItem) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case map[string]interface{}: + if len(v) == 0 { + return nil + } + + // Multiple accounts: + if _, ok := v["accounts"]; ok { + if err := utilz.TranscodeJSON(temp, &env.IdlAccounts); err != nil { + return err + } + } + // Single account: + // TODO: check both isMut and isSigner + if _, ok := v["isMut"]; ok { + if err := utilz.TranscodeJSON(temp, &env.IdlAccount); err != nil { + return err + } + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +type IdlAccount struct { + Docs []string `json:"docs"` // @custom + Name string `json:"name"` + IsMut bool `json:"isMut"` + IsSigner bool `json:"isSigner"` + Optional bool `json:"optional"` // @custom +} + +// A nested/recursive version of IdlAccount. +type IdlAccounts struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Accounts IdlAccountItemSlice `json:"accounts"` +} + +type IdlField struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Type IdlType `json:"type"` +} + +type IdlTypeAsString string + +const ( + IdlTypeBool IdlTypeAsString = "bool" + IdlTypeU8 IdlTypeAsString = "u8" + IdlTypeI8 IdlTypeAsString = "i8" + IdlTypeU16 IdlTypeAsString = "u16" + IdlTypeI16 IdlTypeAsString = "i16" + IdlTypeU32 IdlTypeAsString = "u32" + IdlTypeI32 IdlTypeAsString = "i32" + IdlTypeU64 IdlTypeAsString = "u64" + IdlTypeI64 IdlTypeAsString = "i64" + IdlTypeU128 IdlTypeAsString = "u128" + IdlTypeI128 IdlTypeAsString = "i128" + IdlTypeBytes IdlTypeAsString = "bytes" + IdlTypeString IdlTypeAsString = "string" + IdlTypePublicKey IdlTypeAsString = "publicKey" + + // Custom additions: + IdlTypeUnixTimestamp IdlTypeAsString = "unixTimestamp" + IdlTypeHash IdlTypeAsString = "hash" + IdlTypeDuration IdlTypeAsString = "duration" +) + +type IdlTypeVec struct { + Vec IdlType `json:"vec"` +} + +type IdlTypeOption struct { + Option IdlType `json:"option"` +} + +// User defined type. +type IdlTypeDefined struct { + Defined string `json:"defined"` +} + +// Wrapper type: +type IdlTypeArray struct { + Thing IdlType + Num int +} + +func (env *IdlType) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case string: + env.asString = IdlTypeAsString(v) + case map[string]interface{}: + if len(v) == 0 { + return nil + } + + if _, ok := v["vec"]; ok { + var target IdlTypeVec + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeVec = &target + } + if _, ok := v["option"]; ok { + var target IdlTypeOption + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeOption = &target + } + if _, ok := v["defined"]; ok { + var target IdlTypeDefined + if err := utilz.TranscodeJSON(temp, &target); err != nil { + return err + } + env.asIdlTypeDefined = &target + } + if got, ok := v["array"]; ok { + + if _, ok := got.([]interface{}); !ok { + panic(utilz.Sf("array is not in expected format:\n%s", spew.Sdump(got))) + } + arrVal := got.([]interface{}) + if len(arrVal) != 2 { + panic(utilz.Sf("array is not of expected length:\n%s", spew.Sdump(got))) + } + var target IdlTypeArray + if err := utilz.TranscodeJSON(arrVal[0], &target.Thing); err != nil { + return err + } + + target.Num = int(arrVal[1].(float64)) + + env.asIdlTypeArray = &target + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +// Wrapper type: +type IdlType struct { + asString IdlTypeAsString + asIdlTypeVec *IdlTypeVec + asIdlTypeOption *IdlTypeOption + asIdlTypeDefined *IdlTypeDefined + asIdlTypeArray *IdlTypeArray +} + +func (env *IdlType) IsString() bool { + return env.asString != "" +} +func (env *IdlType) IsIdlTypeVec() bool { + return env.asIdlTypeVec != nil +} +func (env *IdlType) IsIdlTypeOption() bool { + return env.asIdlTypeOption != nil +} +func (env *IdlType) IsIdlTypeDefined() bool { + return env.asIdlTypeDefined != nil +} +func (env *IdlType) IsArray() bool { + return env.asIdlTypeArray != nil +} + +// Getters: +func (env *IdlType) GetString() IdlTypeAsString { + return env.asString +} +func (env *IdlType) GetIdlTypeVec() *IdlTypeVec { + return env.asIdlTypeVec +} +func (env *IdlType) GetIdlTypeOption() *IdlTypeOption { + return env.asIdlTypeOption +} +func (env *IdlType) GetIdlTypeDefined() *IdlTypeDefined { + return env.asIdlTypeDefined +} +func (env *IdlType) GetArray() *IdlTypeArray { + return env.asIdlTypeArray +} + +type IdlTypeDef struct { + Name string `json:"name"` + Type IdlTypeDefTy `json:"type"` +} + +type IdlTypeDefTyKind string + +const ( + IdlTypeDefTyKindStruct IdlTypeDefTyKind = "struct" + IdlTypeDefTyKindEnum IdlTypeDefTyKind = "enum" +) + +type IdlTypeDefTyStruct struct { + Kind IdlTypeDefTyKind `json:"kind"` // == "struct" + + Fields *IdlTypeDefStruct `json:"fields,omitempty"` +} + +type IdlTypeDefTyEnum struct { + Kind IdlTypeDefTyKind `json:"kind"` // == "enum" + + Variants IdlEnumVariantSlice `json:"variants,omitempty"` +} + +type IdlTypeDefTy struct { + Kind IdlTypeDefTyKind `json:"kind"` + + Fields *IdlTypeDefStruct `json:"fields,omitempty"` + Variants IdlEnumVariantSlice `json:"variants,omitempty"` +} + +type IdlEnumVariantSlice []IdlEnumVariant + +func (slice IdlEnumVariantSlice) IsAllUint8() bool { + for _, elem := range slice { + if !elem.IsUint8() { + return false + } + } + return true +} + +func (slice IdlEnumVariantSlice) IsSimpleEnum() bool { + return slice.IsAllUint8() +} + +type IdlTypeDefStruct = []IdlField + +type IdlEnumVariant struct { + Name string `json:"name"` + Docs []string `json:"docs"` // @custom + Fields *IdlEnumFields `json:"fields,omitempty"` +} + +func (variant *IdlEnumVariant) IsUint8() bool { + // it's a simple uint8 if there is no fields data + return variant.Fields == nil +} + +// type IdlEnumFields = IdlEnumFieldsNamed | IdlEnumFieldsTuple; +type IdlEnumFields struct { + IdlEnumFieldsNamed *IdlEnumFieldsNamed + IdlEnumFieldsTuple *IdlEnumFieldsTuple +} + +type IdlEnumFieldsNamed []IdlField + +type IdlEnumFieldsTuple []IdlType + +// TODO: verify with examples +func (env *IdlEnumFields) UnmarshalJSON(data []byte) error { + var temp interface{} + if err := json.Unmarshal(data, &temp); err != nil { + return err + } + + if temp == nil { + return fmt.Errorf("envelope is nil: %v", env) + } + + switch v := temp.(type) { + case []interface{}: + if len(v) == 0 { + return nil + } + + firstItem := v[0] + + if _, ok := firstItem.(map[string]interface{})["name"]; ok { + // TODO: + // If has `name` field, then it's most likely a IdlEnumFieldsNamed. + if err := utilz.TranscodeJSON(temp, &env.IdlEnumFieldsNamed); err != nil { + return err + } + } else { + if err := utilz.TranscodeJSON(temp, &env.IdlEnumFieldsTuple); err != nil { + return err + } + } + default: + return fmt.Errorf("Unknown kind: %s", spew.Sdump(temp)) + } + + return nil +} + +type IdlErrorCode struct { + Code int `json:"code"` + Name string `json:"name"` + Msg string `json:"msg,omitempty"` +} diff --git a/pkg/solana/codec/duration.go b/pkg/solana/codec/duration.go new file mode 100644 index 000000000..e6e540778 --- /dev/null +++ b/pkg/solana/codec/duration.go @@ -0,0 +1,54 @@ +package codec + +import ( + "fmt" + "reflect" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +func NewDuration(builder encodings.Builder) encodings.TypeCodec { + return &duration{ + intEncoder: builder.Int64(), + } +} + +type duration struct { + intEncoder encodings.TypeCodec +} + +var _ encodings.TypeCodec = &duration{} + +func (d *duration) Encode(value any, into []byte) ([]byte, error) { + bi, ok := value.(time.Duration) + if !ok { + return nil, fmt.Errorf("%w: expected time.Duration, got %T", types.ErrInvalidType, value) + } + + return d.intEncoder.Encode(int64(bi), into) +} + +func (d *duration) Decode(encoded []byte) (any, []byte, error) { + value, bytes, err := d.intEncoder.Decode(encoded) + + bi, ok := value.(int64) + if !ok { + return value, bytes, err + } + + return time.Duration(bi), bytes, nil +} + +func (d *duration) GetType() reflect.Type { + return reflect.TypeOf(time.Duration(0)) +} + +func (d *duration) Size(val int) (int, error) { + return d.intEncoder.Size(val) +} + +func (d *duration) FixedSize() (int, error) { + return d.intEncoder.FixedSize() +} diff --git a/pkg/solana/codec/solana.go b/pkg/solana/codec/solana.go new file mode 100644 index 000000000..aecdbf612 --- /dev/null +++ b/pkg/solana/codec/solana.go @@ -0,0 +1,325 @@ +/* +Package codec provides functions to create a codec from an Anchor IDL. All Anchor primitives map to the following native +Go values: + +bool -> bool +string -> string +bytes -> []byte +[u|i][8-64] -> [u]int[8-64] +[u|i]128 -> *big.Int +duration -> time.Duration +unixTimestamp -> int64 +publicKey -> [32]byte +hash -> [32]byte + +Enums as an Anchor data structure are only supported in their basic form of uint8 values. Enums with variants are not +supported at this time. + +Modifiers can be provided to assist in modifying property names, adding properties, etc. +*/ +package codec + +import ( + "fmt" + "math" + + "github.com/mitchellh/mapstructure" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +const ( + DefaultHashBitLength = 32 + unknownIDLFormat = "%w: unknown IDL type def %s" +) + +// BigIntHook allows *big.Int to be represented as any integer type or a string and to go back to them. +// Useful for config, or if when a model may use a go type that isn't a *big.Int when Pack expects one. +// Eg: int32 in a go struct from a plugin could require a *big.Int in Pack for int24, if it fits, we shouldn't care. +// SliceToArrayVerifySizeHook verifies that slices have the correct size when converting to an array +// EpochToTimeHook allows multiple conversions: time.Time -> int64; int64 -> time.Time; *big.Int -> time.Time; and more +var DecoderHooks = []mapstructure.DecodeHookFunc{codec.EpochToTimeHook, codec.BigIntHook, codec.SliceToArrayVerifySizeHook} + +func NewNamedModifierCodec(original types.RemoteCodec, itemType string, modifier codec.Modifier) (types.RemoteCodec, error) { + mod, err := codec.NewByItemTypeModifier(map[string]codec.Modifier{itemType: modifier}) + if err != nil { + return nil, err + } + + modCodec, err := codec.NewModifierCodec(original, mod, DecoderHooks...) + if err != nil { + return nil, err + } + + _, err = modCodec.CreateType(itemType, true) + + return modCodec, err +} + +// NewIDLCodec is for Anchor custom types +func NewIDLCodec(idl IDL, builder encodings.Builder) (encodings.CodecFromTypeCodec, error) { + accounts := make(map[string]encodings.TypeCodec) + + refs := &codecRefs{ + builder: builder, + codecs: make(map[string]encodings.TypeCodec), + typeDefs: idl.Types, + dependencies: make(map[string][]string), + } + + for _, account := range idl.Accounts { + var ( + name string + accCodec encodings.TypeCodec + err error + ) + + name, accCodec, err = createNamedCodec(account, refs) + if err != nil { + return nil, err + } + + accounts[name] = accCodec + } + + return encodings.CodecFromTypeCodec(accounts), nil +} + +type codecRefs struct { + builder encodings.Builder + codecs map[string]encodings.TypeCodec + typeDefs IdlTypeDefSlice + dependencies map[string][]string +} + +func createNamedCodec( + def IdlTypeDef, + refs *codecRefs, +) (string, encodings.TypeCodec, error) { + caser := cases.Title(language.English) + name := def.Name + + switch def.Type.Kind { + case IdlTypeDefTyKindStruct: + return asStruct(def, refs, name, caser) + case IdlTypeDefTyKindEnum: + variants := def.Type.Variants + if !variants.IsAllUint8() { + return name, nil, fmt.Errorf("%w: variants are not supported", types.ErrInvalidConfig) + } + + return name, refs.builder.Uint8(), nil + default: + return name, nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, def.Type.Kind) + } +} + +func asStruct( + def IdlTypeDef, + refs *codecRefs, + name string, // name is the struct name and can be used in dependency checks + caser cases.Caser, +) (string, encodings.TypeCodec, error) { + named := make([]encodings.NamedTypeCodec, len(*def.Type.Fields)) + + for idx, field := range *def.Type.Fields { + fieldName := field.Name + + typedCodec, err := processFieldType(name, field.Type, refs) + if err != nil { + return name, nil, err + } + + named[idx] = encodings.NamedTypeCodec{Name: caser.String(fieldName), Codec: typedCodec} + } + + structCodec, err := encodings.NewStructCodec(named) + if err != nil { + return name, nil, err + } + + return name, structCodec, nil +} + +func processFieldType(parentTypeName string, idlType IdlType, refs *codecRefs) (encodings.TypeCodec, error) { + switch true { + case idlType.IsString(): + return getCodecByStringType(idlType.GetString(), refs.builder) + case idlType.IsIdlTypeOption(): + // Go doesn't have an `Option` type; use pointer to type instead + // this should be automatic in the codec + return processFieldType(parentTypeName, idlType.GetIdlTypeOption().Option, refs) + case idlType.IsIdlTypeDefined(): + return asDefined(parentTypeName, idlType.GetIdlTypeDefined(), refs) + case idlType.IsArray(): + return asArray(parentTypeName, idlType.GetArray(), refs) + case idlType.IsIdlTypeVec(): + return asVec(parentTypeName, idlType.GetIdlTypeVec(), refs) + default: + return nil, fmt.Errorf("%w: unknown IDL type def", types.ErrInvalidConfig) + } +} + +func asDefined(parentTypeName string, definedName *IdlTypeDefined, refs *codecRefs) (encodings.TypeCodec, error) { + if definedName == nil { + return nil, fmt.Errorf("%w: defined type name should not be nil", types.ErrInvalidConfig) + } + + // already exists as a type in the typed codecs + if savedCodec, ok := refs.codecs[definedName.Defined]; ok { + return savedCodec, nil + } + + // nextDef should not have a dependency on definedName + if !validDependency(refs, parentTypeName, definedName.Defined) { + return nil, fmt.Errorf("%w: circular dependency detected on %s -> %s relation", types.ErrInvalidConfig, parentTypeName, definedName.Defined) + } + + // codec by defined type doesn't exist + // process it using the provided typeDefs + nextDef := refs.typeDefs.GetByName(definedName.Defined) + if nextDef == nil { + return nil, fmt.Errorf("%w: IDL type does not exist for name %s", types.ErrInvalidConfig, definedName.Defined) + } + + saveDependency(refs, parentTypeName, definedName.Defined) + + newTypeName, newTypeCodec, err := createNamedCodec(*nextDef, refs) + if err != nil { + return nil, err + } + + // we know that recursive found codecs are types so add them to the type lookup + refs.codecs[newTypeName] = newTypeCodec + + return newTypeCodec, nil +} + +func asArray(parentTypeName string, idlArray *IdlTypeArray, refs *codecRefs) (encodings.TypeCodec, error) { + codec, err := processFieldType(parentTypeName, idlArray.Thing, refs) + if err != nil { + return nil, err + } + + return encodings.NewArray(idlArray.Num, codec) +} + +func asVec(parentTypeName string, idlVec *IdlTypeVec, refs *codecRefs) (encodings.TypeCodec, error) { + codec, err := processFieldType(parentTypeName, idlVec.Vec, refs) + if err != nil { + return nil, err + } + + b, err := refs.builder.Int(4) + if err != nil { + return nil, err + } + + return encodings.NewSlice(codec, b) +} + +func getCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeBool: + return builder.Bool(), nil + case IdlTypeString: + return builder.String(math.MaxUint32) + case IdlTypeI8, IdlTypeI16, IdlTypeI32, IdlTypeI64, IdlTypeI128: + return getIntCodecByStringType(curType, builder) + case IdlTypeU8, IdlTypeU16, IdlTypeU32, IdlTypeU64, IdlTypeU128: + return getUIntCodecByStringType(curType, builder) + case IdlTypeUnixTimestamp, IdlTypeDuration: + return getTimeCodecByStringType(curType, builder) + case IdlTypeBytes, IdlTypePublicKey, IdlTypeHash: + return getByteCodecByStringType(curType, builder) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getIntCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeI8: + return builder.Int8(), nil + case IdlTypeI16: + return builder.Int16(), nil + case IdlTypeI32: + return builder.Int32(), nil + case IdlTypeI64: + return builder.Int64(), nil + case IdlTypeI128: + return builder.BigInt(16, true) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getUIntCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeU8: + return builder.Uint8(), nil + case IdlTypeU16: + return builder.Uint16(), nil + case IdlTypeU32: + return builder.Uint32(), nil + case IdlTypeU64: + return builder.Uint64(), nil + case IdlTypeU128: + return builder.BigInt(16, true) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getTimeCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeUnixTimestamp: + return builder.Int64(), nil + case IdlTypeDuration: + return NewDuration(builder), nil + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func getByteCodecByStringType(curType IdlTypeAsString, builder encodings.Builder) (encodings.TypeCodec, error) { + switch curType { + case IdlTypeBytes: + b, err := builder.Int(4) + if err != nil { + return nil, err + } + + return encodings.NewSlice(builder.Uint8(), b) + case IdlTypePublicKey, IdlTypeHash: + return encodings.NewArray(DefaultHashBitLength, builder.Uint8()) + default: + return nil, fmt.Errorf(unknownIDLFormat, types.ErrInvalidConfig, curType) + } +} + +func validDependency(refs *codecRefs, parent, child string) bool { + deps, ok := refs.dependencies[child] + if ok { + for _, dep := range deps { + if dep == parent { + return false + } + } + } + + return true +} + +func saveDependency(refs *codecRefs, parent, child string) { + deps, ok := refs.dependencies[parent] + if !ok { + deps = make([]string, 0) + } + + refs.dependencies[parent] = append(deps, child) +} diff --git a/pkg/solana/codec/solana_test.go b/pkg/solana/codec/solana_test.go new file mode 100644 index 000000000..73bcf28d8 --- /dev/null +++ b/pkg/solana/codec/solana_test.go @@ -0,0 +1,140 @@ +package codec_test + +import ( + "encoding/json" + "testing" + "time" + + ag_solana "github.com/gagliardetto/solana-go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" +) + +func TestNewIDLCodec(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + _, _, entry := newTestIDLAndCodec(t) + + expected := testutils.DefaultTestStruct + bts, err := entry.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + + require.NoError(t, err) + + var decoded testutils.StructWithNestedStruct + + require.NoError(t, entry.Decode(ctx, bts, &decoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected, decoded) +} + +func TestNewIDLCodec_WithModifiers(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + _, _, idlCodec := newTestIDLAndCodec(t) + modConfig := codeccommon.ModifiersConfig{ + &codeccommon.RenameModifierConfig{Fields: map[string]string{"Value": "V"}}, + } + + renameMod, err := modConfig.ToModifier(codec.DecoderHooks...) + require.NoError(t, err) + + idlCodecWithMods, err := codec.NewNamedModifierCodec(idlCodec, testutils.TestStructWithNestedStruct, renameMod) + require.NoError(t, err) + + type modifiedTestStruct struct { + V uint8 + InnerStruct testutils.ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []testutils.ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 + } + + expected := modifiedTestStruct{ + V: testutils.DefaultTestStruct.Value, + InnerStruct: testutils.DefaultTestStruct.InnerStruct, + BasicNestedArray: testutils.DefaultTestStruct.BasicNestedArray, + Option: testutils.DefaultTestStruct.Option, + DefinedArray: testutils.DefaultTestStruct.DefinedArray, + BasicVector: testutils.DefaultTestStruct.BasicVector, + TimeVal: testutils.DefaultTestStruct.TimeVal, + DurationVal: testutils.DefaultTestStruct.DurationVal, + PublicKey: testutils.DefaultTestStruct.PublicKey, + EnumVal: testutils.DefaultTestStruct.EnumVal, + } + + withModsBts, err := idlCodecWithMods.Encode(ctx, expected, testutils.TestStructWithNestedStruct) + require.NoError(t, err) + + noModsBts, err := idlCodec.Encode(ctx, testutils.DefaultTestStruct, testutils.TestStructWithNestedStruct) + + // the codec without modifiers should encode an unmodified struct to the same bytes + // as the codec with modifiers encodes a modified struct + require.NoError(t, err) + require.Equal(t, withModsBts, noModsBts) + + var decoded modifiedTestStruct + + // the codec with modifiers should decode from unmodified bytes into a modified struct + require.NoError(t, idlCodecWithMods.Decode(ctx, noModsBts, &decoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected, decoded) + + var unmodifiedDecoded testutils.StructWithNestedStruct + + // the codec without modifiers should decode from unmodified bytes to the same values as + // modified struct + require.NoError(t, idlCodec.Decode(ctx, noModsBts, &unmodifiedDecoded, testutils.TestStructWithNestedStruct)) + require.Equal(t, expected.V, unmodifiedDecoded.Value) + require.Equal(t, expected.TimeVal, unmodifiedDecoded.TimeVal) + require.Equal(t, expected.DurationVal, unmodifiedDecoded.DurationVal) + require.Equal(t, expected.PublicKey, unmodifiedDecoded.PublicKey) + require.Equal(t, expected.EnumVal, unmodifiedDecoded.EnumVal) +} + +func TestNewIDLCodec_CircularDependency(t *testing.T) { + t.Parallel() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.CircularDepIDL), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + _, err := codec.NewIDLCodec(idl, binary.LittleEndian()) + + assert.ErrorIs(t, err, types.ErrInvalidConfig) +} + +func newTestIDLAndCodec(t *testing.T) (string, codec.IDL, encodings.CodecFromTypeCodec) { + t.Helper() + + var idl codec.IDL + if err := json.Unmarshal([]byte(testutils.JSONIDLWithAllTypes), &idl); err != nil { + t.Logf("failed to unmarshal test IDL: %s", err.Error()) + t.FailNow() + } + + entry, err := codec.NewIDLCodec(idl, binary.LittleEndian()) + if err != nil { + t.Logf("failed to create new codec from test IDL: %s", err.Error()) + t.FailNow() + } + + require.NotNil(t, entry) + + return testutils.JSONIDLWithAllTypes, idl, entry +} diff --git a/pkg/solana/codec/testutils/circularDepIDL.json b/pkg/solana/codec/testutils/circularDepIDL.json new file mode 100644 index 000000000..fb896f088 --- /dev/null +++ b/pkg/solana/codec/testutils/circularDepIDL.json @@ -0,0 +1,42 @@ +{ + "accounts": [{ + "name": "TopLevelStruct", + "type": { + "kind": "struct", + "fields": [{ + "name": "circularOne", + "type": { + "defined": "TypeOne" + } + }, { + "name": "circularTwo", + "type": { + "defined": "TypeTwo" + } + }] + } + }], + "types": [{ + "name": "TypeOne", + "type": { + "kind": "struct", + "fields": [{ + "name": "circular", + "type": { + "defined": "TypeTwo" + } + }] + } + }, { + "name": "TypeTwo", + "type": { + "kind": "struct", + "fields": [{ + "name": "circular", + "type": { + "defined": "TypeOne" + } + }] + } + }] +} \ No newline at end of file diff --git a/pkg/solana/codec/testutils/testIDL.json b/pkg/solana/codec/testutils/testIDL.json new file mode 100644 index 000000000..d05496ee5 --- /dev/null +++ b/pkg/solana/codec/testutils/testIDL.json @@ -0,0 +1,159 @@ +{ + "version": "0.1.0", + "name": "some_test_idl", + "accounts": [ + { + "name": "StructWithNestedStruct", + "type": { + "kind": "struct", + "fields": [ + { + "name": "value", + "type": "u8" + }, + { + "name": "innerStruct", + "type": { + "defined": "ObjectRef1" + } + }, + { + "name": "basicNestedArray", + "type": { + "array": [ + { + "array": [ + "u32", + 3 + ] + }, + 3 + ] + } + }, + { + "name": "option", + "type": { + "option": "string" + } + }, + { + "name": "definedArray", + "type": { + "array": [ + { + "defined": "ObjectRef2" + }, + 2 + ] + } + }, + { + "name": "basicVector", + "type": { + "vec": "string" + } + }, + { + "name": "timeVal", + "type": "unixTimestamp" + }, + { + "name": "durationVal", + "type": "duration" + }, + { + "name": "publicKey", + "type": "publicKey" + }, + { + "name": "enumVal", + "type": { + "defined": "SimpleEnum" + } + } + ] + } + } + ], + "types": [ + { + "name": "ObjectRef1", + "type": { + "kind": "struct", + "fields": [ + { + "name": "prop1", + "type": "i8" + }, + { + "name": "prop2", + "type": "string" + }, + { + "name": "prop3", + "type": "u128" + }, + { + "name": "prop4", + "type": "u16" + }, + { + "name": "prop5", + "type": "u64" + }, + { + "name": "prop6", + "type": "bool" + } + ] + } + }, + { + "name": "ObjectRef2", + "type": { + "kind": "struct", + "fields": [ + { + "name": "prop1", + "type": "u32" + }, + { + "name": "prop2", + "type": "i128" + }, + { + "name": "prop3", + "type": "i16" + }, + { + "name": "prop4", + "type": "i32" + }, + { + "name": "prop5", + "type": "i64" + }, + { + "name": "prop6", + "type": "bytes" + } + ] + } + }, + { + "name": "SimpleEnum", + "type": { + "kind": "enum", + "variants": [ + { + "name": "A" + }, + { + "name": "B" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/solana/codec/testutils/types.go b/pkg/solana/codec/testutils/types.go new file mode 100644 index 000000000..7c20762f7 --- /dev/null +++ b/pkg/solana/codec/testutils/types.go @@ -0,0 +1,87 @@ +package testutils + +import ( + _ "embed" + "math/big" + "time" + + ag_solana "github.com/gagliardetto/solana-go" +) + +var ( + TestStructWithNestedStruct = "StructWithNestedStruct" + DefaultStringRef = "test string" + DefaultTestStruct = StructWithNestedStruct{ + Value: 80, + InnerStruct: ObjectRef1{ + Prop1: 10, + Prop2: "some_val", + Prop3: new(big.Int).SetUint64(42), + Prop4: 42, + Prop5: 42, + Prop6: true, + }, + BasicNestedArray: [][]uint32{{5, 6, 7}, {0, 0, 0}, {0, 0, 0}}, + Option: &DefaultStringRef, + DefinedArray: []ObjectRef2{ + { + Prop1: 42, + Prop2: new(big.Int).SetInt64(42), + Prop3: 43, + Prop4: 44, + Prop5: 45, + Prop6: []byte{}, + }, + { + Prop1: 46, + Prop2: new(big.Int).SetInt64(46), + Prop3: 47, + Prop4: 48, + Prop5: 49, + Prop6: []byte{}, + }, + }, + BasicVector: []string{"some string", "another string"}, + TimeVal: 683_100_000, + DurationVal: 42 * time.Second, + PublicKey: ag_solana.NewWallet().PublicKey(), + EnumVal: 0, + } +) + +type StructWithNestedStruct struct { + Value uint8 + InnerStruct ObjectRef1 + BasicNestedArray [][]uint32 + Option *string + DefinedArray []ObjectRef2 + BasicVector []string + TimeVal int64 + DurationVal time.Duration + PublicKey ag_solana.PublicKey + EnumVal uint8 +} + +type ObjectRef1 struct { + Prop1 int8 + Prop2 string + Prop3 *big.Int + Prop4 uint16 + Prop5 uint64 + Prop6 bool +} + +type ObjectRef2 struct { + Prop1 uint32 + Prop2 *big.Int + Prop3 int16 + Prop4 int32 + Prop5 int64 + Prop6 []byte +} + +//go:embed testIDL.json +var JSONIDLWithAllTypes string + +//go:embed circularDepIDL.json +var CircularDepIDL string diff --git a/pkg/solana/config/chain_reader.go b/pkg/solana/config/chain_reader.go new file mode 100644 index 000000000..a1fed147d --- /dev/null +++ b/pkg/solana/config/chain_reader.go @@ -0,0 +1,101 @@ +package config + +import ( + "encoding/json" + "fmt" + + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + + "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +type ChainReader struct { + Namespaces map[string]ChainReaderMethods `json:"namespaces" toml:"namespaces"` +} + +type ChainReaderMethods struct { + Methods map[string]ChainDataReader `json:"methods" toml:"methods"` +} + +type ChainDataReader struct { + AnchorIDL string `json:"anchorIDL" toml:"anchorIDL"` + // Encoding defines the type of encoding used for on-chain data. Currently supported + // are 'borsh' and 'bincode'. + Encoding EncodingType `json:"encoding" toml:"encoding"` + Procedures []ChainReaderProcedure `json:"procedures" toml:"procedures"` +} + +type EncodingType int + +const ( + EncodingTypeBorsh EncodingType = iota + EncodingTypeBincode + + encodingTypeBorshStr = "borsh" + encodingTypeBincodeStr = "bincode" +) + +func (t EncodingType) MarshalJSON() ([]byte, error) { + switch t { + case EncodingTypeBorsh: + return json.Marshal(encodingTypeBorshStr) + case EncodingTypeBincode: + return json.Marshal(encodingTypeBincodeStr) + default: + return nil, fmt.Errorf("%w: unrecognized encoding type: %d", types.ErrInvalidConfig, t) + } +} + +func (t *EncodingType) UnmarshalJSON(data []byte) error { + var str string + + if err := json.Unmarshal(data, &str); err != nil { + return fmt.Errorf("%w: %s", types.ErrInvalidConfig, err.Error()) + } + + switch str { + case encodingTypeBorshStr: + *t = EncodingTypeBorsh + case encodingTypeBincodeStr: + *t = EncodingTypeBincode + default: + return fmt.Errorf("%w: unrecognized encoding type: %s", types.ErrInvalidConfig, str) + } + + return nil +} + +type RPCOpts struct { + Encoding *solana.EncodingType `json:"encoding,omitempty"` + Commitment *rpc.CommitmentType `json:"commitment,omitempty"` + DataSlice *rpc.DataSlice `json:"dataSlice,omitempty"` +} + +type ChainReaderProcedure chainDataProcedureFields + +type chainDataProcedureFields struct { + // IDLAccount refers to the account defined in the IDL. + IDLAccount string `json:"idlAccount,omitempty"` + // OutputModifications provides modifiers to convert chain data format to custom + // output formats. + OutputModifications codec.ModifiersConfig `json:"outputModifications,omitempty"` + // RPCOpts provides optional configurations for commitment, encoding, and data + // slice offsets. + RPCOpts *RPCOpts `json:"rpcOpts,omitempty"` +} + +// BuilderForEncoding returns a builder for the encoding configuration. Defaults to little endian. +func BuilderForEncoding(eType EncodingType) encodings.Builder { + switch eType { + case EncodingTypeBorsh: + return binary.LittleEndian() + case EncodingTypeBincode: + return binary.BigEndian() + default: + return binary.LittleEndian() + } +} diff --git a/pkg/solana/config/chain_reader_test.go b/pkg/solana/config/chain_reader_test.go new file mode 100644 index 000000000..b0ad49181 --- /dev/null +++ b/pkg/solana/config/chain_reader_test.go @@ -0,0 +1,135 @@ +package config_test + +import ( + _ "embed" + "encoding/json" + "testing" + + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + codeccommon "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/codec/encodings/binary" + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink-solana/pkg/solana/codec/testutils" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +//go:embed testChainReader_valid.json +var validJSON string + +//go:embed testChainReader_invalid.json +var invalidJSON string + +func TestChainReaderConfig(t *testing.T) { + t.Parallel() + + t.Run("valid unmarshal", func(t *testing.T) { + t.Parallel() + + var result config.ChainReader + require.NoError(t, json.Unmarshal([]byte(validJSON), &result)) + assert.Equal(t, validChainReaderConfig, result) + }) + + t.Run("invalid unmarshal", func(t *testing.T) { + t.Parallel() + + var result config.ChainReader + require.ErrorIs(t, json.Unmarshal([]byte(invalidJSON), &result), types.ErrInvalidConfig) + }) + + t.Run("marshal", func(t *testing.T) { + t.Parallel() + + result, err := json.Marshal(validChainReaderConfig) + + require.NoError(t, err) + + var conf config.ChainReader + + require.NoError(t, json.Unmarshal(result, &conf)) + assert.Equal(t, validChainReaderConfig, conf) + }) +} + +func TestEncodingType_Fail(t *testing.T) { + t.Parallel() + + _, err := json.Marshal(config.EncodingType(100)) + + require.NotNil(t, err) + + var tp config.EncodingType + + require.ErrorIs(t, json.Unmarshal([]byte(`42`), &tp), types.ErrInvalidConfig) + require.ErrorIs(t, json.Unmarshal([]byte(`"invalid"`), &tp), types.ErrInvalidConfig) +} + +func TestBuilderForEncoding_Default(t *testing.T) { + t.Parallel() + + builder := config.BuilderForEncoding(config.EncodingType(100)) + require.Equal(t, binary.LittleEndian(), builder) +} + +var ( + encodingBase64 = solana.EncodingBase64 + commitment = rpc.CommitmentFinalized + offset = uint64(10) + length = uint64(10) +) + +var validChainReaderConfig = config.ChainReader{ + Namespaces: map[string]config.ChainReaderMethods{ + "Contract": { + Methods: map[string]config.ChainDataReader{ + "Method": { + AnchorIDL: "test idl 1", + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + }, + }, + }, + "MethodWithOpts": { + AnchorIDL: "test idl 2", + Encoding: config.EncodingTypeBorsh, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + OutputModifications: codeccommon.ModifiersConfig{ + &codeccommon.PropertyExtractorConfig{FieldName: "DurationVal"}, + }, + RPCOpts: &config.RPCOpts{ + Encoding: &encodingBase64, + Commitment: &commitment, + DataSlice: &rpc.DataSlice{ + Offset: &offset, + Length: &length, + }, + }, + }, + }, + }, + }, + }, + "OtherContract": { + Methods: map[string]config.ChainDataReader{ + "Method": { + AnchorIDL: "test idl 3", + Encoding: config.EncodingTypeBincode, + Procedures: []config.ChainReaderProcedure{ + { + IDLAccount: testutils.TestStructWithNestedStruct, + }, + }, + }, + }, + }, + }, +} diff --git a/pkg/solana/config/testChainReader_invalid.json b/pkg/solana/config/testChainReader_invalid.json new file mode 100644 index 000000000..b428b6115 --- /dev/null +++ b/pkg/solana/config/testChainReader_invalid.json @@ -0,0 +1,15 @@ +{ + "namespaces": { + "Contract": { + "methods": { + "Method": { + "anchorIDL": "test idl 1", + "encoding": "invalid", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + } + } + } + } +} \ No newline at end of file diff --git a/pkg/solana/config/testChainReader_valid.json b/pkg/solana/config/testChainReader_valid.json new file mode 100644 index 000000000..6dfbe0626 --- /dev/null +++ b/pkg/solana/config/testChainReader_valid.json @@ -0,0 +1,45 @@ +{ + "namespaces": { + "Contract": { + "methods": { + "Method": { + "anchorIDL": "test idl 1", + "encoding": "borsh", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + }, + "MethodWithOpts": { + "anchorIDL": "test idl 2", + "encoding": "borsh", + "procedures": [{ + "idlAccount": "StructWithNestedStruct", + "outputModifications": [{ + "Type": "extract property", + "FieldName": "DurationVal" + }], + "rpcOpts": { + "encoding": "base64", + "commitment": "finalized", + "dataSlice": { + "offset": 10, + "length": 10 + } + } + }] + } + } + }, + "OtherContract": { + "methods": { + "Method": { + "anchorIDL": "test idl 3", + "encoding": "bincode", + "procedures": [{ + "idlAccount": "StructWithNestedStruct" + }] + } + } + } + } +} \ No newline at end of file diff --git a/scripts/install-solana-ci.sh b/scripts/install-solana-ci.sh index 117639c3a..633287384 100755 --- a/scripts/install-solana-ci.sh +++ b/scripts/install-solana-ci.sh @@ -2,5 +2,5 @@ set -euxo pipefail -sh -c "$(curl -sSfL https://release.solana.com/v1.17.25/install)" +sh -c "$(curl -sSfL https://release.solana.com/v1.17.28/install)" echo "PATH=$HOME/.local/share/solana/install/active_release/bin:$PATH" >> $GITHUB_ENV diff --git a/scripts/update-e2e.sh b/scripts/update-e2e.sh index 35c28d0af..33198d5df 100755 --- a/scripts/update-e2e.sh +++ b/scripts/update-e2e.sh @@ -7,6 +7,6 @@ echo "Chainlink Develop Commit: $SHA" # update dependencies go get github.com/smartcontractkit/chainlink/integration-tests@$SHA -go mod tidy +go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink dep and try tidy again\n------" go get github.com/smartcontractkit/chainlink/v2@$SHA go mod tidy diff --git a/sonar-project.properties b/sonar-project.properties index 7f64da7db..0434465b5 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.projectKey=smartcontractkit_chainlink-solana sonar.sources=. # Full exclusions from the static analysis -sonar.exclusions=**/node_modules/**/*, **/contracts/artifacts/**/*, **/generated/**/*, **/docs/**/*, **/*.config.ts, **/*.config.js, **/*.txt +sonar.exclusions=**/node_modules/**/*, **/contracts/artifacts/**/*, **/generated/**/*, **/docs/**/*, **/*.config.ts, **/*.config.js, **/*.txt, pkg/solana/codec/anchoridl.go # Coverage exclusions sonar.coverage.exclusions=**/*.test.ts, **/*_test.go, **/contracts/tests/**/*, **/integration-tests/**/*