From 3c4e74f9cdf14bc202865f8ff4ba680fbdf6d640 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 3 Oct 2025 16:11:13 -0300 Subject: [PATCH 01/45] squash: ton explorer --- cmd/chainlink-ton/lock.nix | 2 +- cmd/explorer/main.go | 58 +++ deployment/go.mod | 37 +- deployment/go.sum | 78 ++-- go.mod | 63 ++- go.sum | 381 +++++++++++++++++- integration-tests/go.mod | 27 +- integration-tests/go.sum | 69 ++-- integration-tests/jetton/jetton_test.go | 321 ++++++++------- pkg/bindings/jetton/common.go | 46 +++ pkg/bindings/jetton/minter.go | 106 ----- pkg/bindings/jetton/minter/codec.go | 88 ++++ pkg/bindings/jetton/minter/minter.go | 32 ++ pkg/bindings/jetton/wallet/codec.go | 84 ++++ pkg/bindings/jetton/{ => wallet}/wallet.go | 29 +- .../ccipsendexecutor/ccipsendexecutor.go | 82 ++++ pkg/ccip/bindings/ccipsendexecutor/codec.go | 37 ++ pkg/ccip/bindings/feequoter/codec.go | 41 ++ pkg/ccip/bindings/feequoter/fee_quoter.go | 38 ++ pkg/ccip/bindings/onramp/codec.go | 35 ++ pkg/ccip/bindings/onramp/onramp.go | 51 +++ pkg/ccip/bindings/router/codec.go | 40 ++ pkg/ccip/bindings/router/router.go | 8 - pkg/ton/codec/builder.go | 28 ++ .../ccip/ccipsendexecutor/ccipsendexecutor.go | 70 ++++ pkg/ton/debug/decoders/ccip/common/common.go | 66 +++ .../decoders/ccip/feequoter/feequoter.go | 111 +++++ pkg/ton/debug/decoders/ccip/onramp/onramp.go | 92 +++++ pkg/ton/debug/decoders/ccip/router/router.go | 74 ++++ pkg/ton/debug/decoders/jetton/common.go | 54 +++ .../decoders/jetton/minter/jetton_minter.go | 112 +++++ .../decoders/jetton/wallet/jetton_wallet.go | 145 +++++++ pkg/ton/debug/explorer/explorer.go | 134 ++++++ pkg/ton/debug/lib/lib.go | 101 +++++ pkg/ton/debug/pretty_print.go | 345 ++++++++++++++++ pkg/ton/debug/pretty_print_test.go | 41 ++ pkg/ton/debug/sequencediagram.go | 5 + pkg/ton/debug/tree_diagram.go | 163 ++++++++ pkg/ton/tracetracking/message.go | 4 +- pkg/ton/tracetracking/pretty_print.go | 124 ------ pkg/ton/tvm/exit_codes.go | 10 - 41 files changed, 2884 insertions(+), 548 deletions(-) create mode 100644 cmd/explorer/main.go create mode 100644 pkg/bindings/jetton/common.go delete mode 100644 pkg/bindings/jetton/minter.go create mode 100644 pkg/bindings/jetton/minter/codec.go create mode 100644 pkg/bindings/jetton/minter/minter.go create mode 100644 pkg/bindings/jetton/wallet/codec.go rename pkg/bindings/jetton/{ => wallet}/wallet.go (56%) create mode 100644 pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go create mode 100644 pkg/ccip/bindings/ccipsendexecutor/codec.go create mode 100644 pkg/ccip/bindings/feequoter/codec.go create mode 100644 pkg/ccip/bindings/onramp/codec.go create mode 100644 pkg/ccip/bindings/router/codec.go create mode 100644 pkg/ton/codec/builder.go create mode 100644 pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go create mode 100644 pkg/ton/debug/decoders/ccip/common/common.go create mode 100644 pkg/ton/debug/decoders/ccip/feequoter/feequoter.go create mode 100644 pkg/ton/debug/decoders/ccip/onramp/onramp.go create mode 100644 pkg/ton/debug/decoders/ccip/router/router.go create mode 100644 pkg/ton/debug/decoders/jetton/common.go create mode 100644 pkg/ton/debug/decoders/jetton/minter/jetton_minter.go create mode 100644 pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go create mode 100644 pkg/ton/debug/explorer/explorer.go create mode 100644 pkg/ton/debug/lib/lib.go create mode 100644 pkg/ton/debug/pretty_print.go create mode 100644 pkg/ton/debug/pretty_print_test.go create mode 100644 pkg/ton/debug/sequencediagram.go create mode 100644 pkg/ton/debug/tree_diagram.go delete mode 100644 pkg/ton/tracetracking/pretty_print.go diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index decc27485..fa60d1d74 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `nix-lock-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-ab9I2x47vAI0eReG+dKLMhrezubMQ0ric3tI5iMKOFA="; + chainlink-ton = "sha256-6a0atpcomw37rgr09whm3AsBp7GUZf6JORM7MQnnnPg="; } diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go new file mode 100644 index 000000000..29c120b99 --- /dev/null +++ b/cmd/explorer/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" +) + +var ( + destAddressStr string + txHashStr string + net string + verbose bool +) + +var rootCmd = &cobra.Command{ + Use: "explorer", + Short: "TON blockchain explorer and trace analyzer", + Long: `A command-line tool for exploring TON blockchain transactions and analyzing traces. +This tool helps debug and understand transaction flows on the TON network.`, + RunE: func(cmd *cobra.Command, args []string) error { + if destAddressStr == "" || txHashStr == "" { + return fmt.Errorf("both --address and --tx flags are required") + } + + ctx := context.Background() + err := explorer.PrintTrace(ctx, net, destAddressStr, txHashStr, verbose) + if err != nil { + return fmt.Errorf("failed to execute trace: %w", err) + } + return nil + }, +} + +func init() { + rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (required)") + rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (required)") + rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") + rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") + + if err := rootCmd.MarkFlagRequired("address"); err != nil { + panic(err) + } + if err := rootCmd.MarkFlagRequired("tx"); err != nil { + panic(err) + } +} + +func main() { + if err := rootCmd.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} diff --git a/deployment/go.mod b/deployment/go.mod index a01dae7a5..389e97b59 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -12,14 +12,14 @@ require ( github.com/Masterminds/semver/v3 v3.4.0 github.com/hashicorp/consul/sdk v0.16.2 github.com/rs/zerolog v1.33.0 - github.com/smartcontractkit/chain-selectors v1.0.67 + github.com/smartcontractkit/chain-selectors v1.0.72 github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 - github.com/smartcontractkit/chainlink-deployments-framework v0.42.0 - github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23 + github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 + github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 github.com/smartcontractkit/chainlink-ton v0.0.0-20250904183752-4ea5c19ee886 - github.com/smartcontractkit/mcms v0.21.1 - github.com/stretchr/testify v1.10.0 + github.com/smartcontractkit/mcms v0.25.0 + github.com/stretchr/testify v1.11.1 github.com/xssnick/tonutils-go v1.14.1 golang.org/x/sync v0.16.0 ) @@ -33,26 +33,12 @@ require ( github.com/XSAM/otelsql v0.37.0 // indirect github.com/aptos-labs/aptos-go-sdk v1.9.1-0.20250613185448-581cb03acb8f // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect - github.com/aws/aws-sdk-go-v2 v1.38.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect - github.com/aws/smithy-go v1.22.5 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.20.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect - github.com/block-vision/sui-go-sdk v1.0.6 // indirect + github.com/block-vision/sui-go-sdk v1.0.9 // indirect github.com/btcsuite/btcd v0.24.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/btcutil v1.1.6 // indirect @@ -77,7 +63,7 @@ require ( github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.3.2+incompatible // indirect + github.com/docker/docker v28.3.3+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.8.4 // indirect @@ -124,6 +110,7 @@ require ( github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect github.com/jackc/pgx/v4 v4.18.3 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -164,6 +151,7 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect + github.com/samber/lo v1.49.1 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect @@ -171,17 +159,18 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chainlink-aptos v0.0.0-20250818164129-fa2e60d95157 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 // indirect github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 // indirect github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1 // indirect + github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335 // indirect github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d // indirect - github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/supranational/blst v0.3.14 // indirect @@ -228,7 +217,7 @@ require ( golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.34.0 // indirect golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.35.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect diff --git a/deployment/go.sum b/deployment/go.sum index e916d0311..f13facf1f 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -30,34 +30,6 @@ github.com/aptos-labs/aptos-go-sdk v1.9.1-0.20250613185448-581cb03acb8f h1:O1DCx github.com/aptos-labs/aptos-go-sdk v1.9.1-0.20250613185448-581cb03acb8f/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk= github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA= -github.com/aws/aws-sdk-go-v2 v1.38.1 h1:j7sc33amE74Rz0M/PoCpsZQ6OunLqys/m5antM0J+Z8= -github.com/aws/aws-sdk-go-v2 v1.38.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= -github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= -github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 h1:IdCLsiiIj5YJ3AFevsewURCPV+YWUlOW8JiPhoAy8vg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4/go.mod h1:l4bdfCD7XyyZA9BolKBo1eLqgaJxl0/x91PL4Yqe0ao= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 h1:j7vjtr1YIssWQOMeOWRbh3z8g2oY/xPjnZH2gLY4sGw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4/go.mod h1:yDmJgqOiH4EA8Hndnv4KwAo8jCGTSnM5ASG1nBI+toA= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= -github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= -github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= 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/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -69,8 +41,8 @@ github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3M github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= -github.com/block-vision/sui-go-sdk v1.0.6 h1:FysCc4TJC8v4BEBbCjJPDR4iR5eKqJT1dxGwsT67etg= -github.com/block-vision/sui-go-sdk v1.0.6/go.mod h1:FyK1vGE8lWm9QA1fdQpf1agfXQSMbPT8AV1BICgx6d8= +github.com/block-vision/sui-go-sdk v1.0.9 h1:vp8y+nSshTdTyhiDYy6Z/4aEsyTbveJ6n8ALg53GHWg= +github.com/block-vision/sui-go-sdk v1.0.9/go.mod h1:V9vmxB2pyYdy8eXV+x5lb/PcSVt3ytvF43m3NUlybx0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -183,8 +155,8 @@ github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbz github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= -github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+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= @@ -412,6 +384,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= @@ -589,6 +563,8 @@ github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWR github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= 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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -609,10 +585,10 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.67 h1:gxTqP/JC40KDe3DE1SIsIKSTKTZEPyEU1YufO1admnw= -github.com/smartcontractkit/chain-selectors v1.0.67/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250818164129-fa2e60d95157 h1:jcDGTwLBDGwgBOYFf3FerTh8k2JPHApIg2UDiIKwZRE= -github.com/smartcontractkit/chainlink-aptos v0.0.0-20250818164129-fa2e60d95157/go.mod h1:zNZ5rtLkbqsGCjDWb1y8n7BRk2zgflkzmj2GjnLnj08= +github.com/smartcontractkit/chain-selectors v1.0.72 h1:AExF2H3mABdLCN0QZd+IjU8CkblTZLKJqvp4vcwew+g= +github.com/smartcontractkit/chain-selectors v1.0.72/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b h1:scWqERf9tWr5ocX/nENI1Kc9FqSl2y87bglwjXbe3XA= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b/go.mod h1:zNZ5rtLkbqsGCjDWb1y8n7BRk2zgflkzmj2GjnLnj08= github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 h1:Lz2/FNeODZr7YGY6uOPf2n87o0rrKfsNxr5Bx6VcQ7I= github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960/go.mod h1:W3d6TbZ4PNLGb8QOK8URc/tVWBhnAOwtAYsQ2iPgwtw= github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a h1:kQ8Zs6OzXizScIK8PEb8THxDUziGttGT9D6tTTAwmZk= @@ -623,14 +599,16 @@ github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b14 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142/go.mod h1:1r3aM96KHAESfnayJ3BTHCkP1qJS1BEG1r4czeoaXlA= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 h1:hvqATtrZ0iMRTI80cpBot/3JFbjz2j+2tvpfooVhRHw= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4/go.mod h1:eKGyfTKzr0/PeR7qKN4l2FcW9p+HzyKUwAfGhm/5YZc= -github.com/smartcontractkit/chainlink-deployments-framework v0.42.0 h1:48m4KU+gj9BzehxqKw+GOAwNDh0JxdOx9x3Zmummppo= -github.com/smartcontractkit/chainlink-deployments-framework v0.42.0/go.mod h1:pbj+mMphYAKdgQ+oSy0FZN3236wxJnAxCnbgUXJZR8s= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 h1:0BMVTqGYmYV2xf7s+OI9HzbYkNpBj+TgiqCHB4zJAcA= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0/go.mod h1:71uC1ddxWsxq7uf5rCAjlSo/8mmIdvNwahqgoNrrx90= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 h1:1/KdO5AbUr3CmpLjMPuJXPo2wHMbfB8mldKLsg7D4M8= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q= github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1 h1:PWwLGimBt37eDzpbfZ9V/ZkW4oCjcwKjKiAwKlSfPc0= github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23 h1:+L8R3Nn4ZadjGUDUr7HKVMt9I1vv5IS/IzUfQzyNvDw= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23/go.mod h1:gdW2dlrvHcTawMCtAIXQYZcZ9Ggx16L55kA7wONvzJ4= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f h1:7saUNbu+edzDgRPedNFfTsx5+5RL40r1r0pgISoh8Hs= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f/go.mod h1:CTR5agBB07sCpRltBkHmnkCZ+g8sXRafCJge/Hqr7aM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 h1:mDxJnEl5jKs3FLHKIjwtCFEP4ihKhFS6yuPDNcC0EDM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30/go.mod h1:SoCjdzeZHP500QtKAjJ9I6rHD03SkQmRL4dNkOoe6yk= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335 h1:7bxYNrPpygn8PUSBiEKn8riMd7CXMi/4bjTy0fHhcrY= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335/go.mod h1:ccjEgNeqOO+bjPddnL4lUrNLzyCvGCxgBjJdhFX3wa8= github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d h1:qLmSOOtB/Ogn79eIDkuujOu8M5Jd747V1H7Brk/nTvo= @@ -641,12 +619,12 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12i github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= -github.com/smartcontractkit/mcms v0.21.1 h1:vbM1c45Hd526XTKdXy2G1YKlMyzyc+ybdPTK79UlkKg= -github.com/smartcontractkit/mcms v0.21.1/go.mod h1:7bg4JECK7UHvXAJ7/kzvCNLzUu8JxKvvti3ko9y3FpI= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/smartcontractkit/mcms v0.25.0 h1:GTkG6jQ2CYoVQFKkRQnA42IvUrR4gObeHqwrQNRhmGM= +github.com/smartcontractkit/mcms v0.25.0/go.mod h1:7v5DNfWqIS81nISbuFBrlV1QHZfD+pFQzjsxqqhcK9o= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 h1:ba4VRWSkRzgdP5hB5OxexIzBXZbSwgcw8bEu06ivGQI= github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863/go.mod h1:oPTjPNrRucLv9mU27iNPj6n0CWWcNFhoXFOLVGJwHCA= github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= @@ -669,8 +647,8 @@ 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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= @@ -922,8 +900,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/go.mod b/go.mod index 457c42e70..bc65eb08a 100644 --- a/go.mod +++ b/go.mod @@ -10,11 +10,13 @@ require ( github.com/ethereum/go-ethereum v1.16.2 github.com/gagliardetto/solana-go v1.13.0 github.com/pelletier/go-toml/v2 v2.2.4 - github.com/smartcontractkit/chain-selectors v1.0.67 + github.com/smartcontractkit/chain-selectors v1.0.72 github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 - github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d - github.com/stretchr/testify v1.10.0 + github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 + github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358 + github.com/spf13/cobra v1.10.1 + github.com/stretchr/testify v1.11.1 github.com/xssnick/tonutils-go v1.14.1 golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc golang.org/x/sync v0.16.0 @@ -22,18 +24,40 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/XSAM/otelsql v0.37.0 // indirect + github.com/aptos-labs/aptos-go-sdk v1.7.1-0.20250602153733-bb1facae1d43 // indirect + github.com/avast/retry-go/v4 v4.6.1 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect + github.com/block-vision/sui-go-sdk v1.0.9 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 // indirect github.com/cloudevents/sdk-go/v2 v2.16.1 // indirect + github.com/coder/websocket v1.8.13 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect github.com/fatih/color v1.18.0 // indirect + github.com/fbsobreira/gotron-sdk v0.0.0-20250403083053-2943ce8c759b // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gagliardetto/binary v0.8.0 // indirect @@ -41,6 +65,7 @@ require ( github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.26.0 // indirect @@ -48,12 +73,16 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/yamux v0.1.2 // indirect + github.com/hasura/go-graphql-client v0.13.1 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/holiman/uint256 v1.3.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.13.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect @@ -63,11 +92,13 @@ require ( github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect github.com/jackc/pgx/v4 v4.18.3 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/jmank88/gomods v0.1.6 // indirect github.com/jmank88/modgraph v0.1.1 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect @@ -89,18 +120,40 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect + github.com/samber/lo v1.49.1 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect + github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a // indirect + github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 // indirect github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 // indirect + github.com/smartcontractkit/chainlink-protos/job-distributor v0.12.0 // indirect + github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f // indirect + github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335 // indirect github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect + github.com/smartcontractkit/mcms v0.25.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect + github.com/supranational/blst v0.3.14 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/valyala/fastjson v1.6.4 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect @@ -123,14 +176,16 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 // indirect go.opentelemetry.io/proto/otlp v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.uber.org/ratelimit v0.3.1 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.40.0 // indirect golang.org/x/mod v0.26.0 // indirect golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.34.0 // indirect golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.35.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/grpc v1.74.2 // indirect diff --git a/go.sum b/go.sum index f170eed0a..39eea0ba2 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,84 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= +github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/XSAM/otelsql v0.37.0 h1:ya5RNw028JW0eJW8Ma4AmoKxAYsJSGuNVbC7F1J457A= github.com/XSAM/otelsql v0.37.0/go.mod h1:LHbCu49iU8p255nCn1oi04oX2UjSoRcUMiKEHo2a5qM= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/apache/arrow-go/v18 v18.3.1 h1:oYZT8FqONiK74JhlH3WKVv+2NKYoyZ7C2ioD4Dj3ixk= github.com/apache/arrow-go/v18 v18.3.1/go.mod h1:12QBya5JZT6PnBihi5NJTzbACrDGXYkrgjujz3MRQXU= +github.com/aptos-labs/aptos-go-sdk v1.7.1-0.20250602153733-bb1facae1d43 h1:Mn2LI+fa8QzVmXQ/30MT76GYTQIxpSB3lzos0hat4qc= +github.com/aptos-labs/aptos-go-sdk v1.7.1-0.20250602153733-bb1facae1d43/go.mod h1:vYm/yHr6cQpoUBMw/Q93SRR1IhP0mPTBrEGjShwUvXc= +github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk= +github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA= 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/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 v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= +github.com/block-vision/sui-go-sdk v1.0.9 h1:vp8y+nSshTdTyhiDYy6Z/4aEsyTbveJ6n8ALg53GHWg= +github.com/block-vision/sui-go-sdk v1.0.9/go.mod h1:V9vmxB2pyYdy8eXV+x5lb/PcSVt3ytvF43m3NUlybx0= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -33,34 +89,116 @@ github.com/cloudevents/sdk-go/v2 v2.16.1/go.mod h1:v/kVOaWjNfbvc6tkhhlkhvLapj8Aa github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE= +github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= +github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= +github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= +github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= +github.com/cucumber/godog v0.15.0/go.mod h1:FX3rzIDybWABU4kuIXLZ/qtqEe1Ac5RdXmqvACJOces= +github.com/cucumber/messages/go/v21 v21.0.1 h1:wzA0LxwjlWQYZd32VTlAVDTkW6inOFmSM+RuOwHZiMI= +github.com/cucumber/messages/go/v21 v21.0.1/go.mod h1:zheH/2HS9JLVFukdrsPWoPdmUtmYQAQPLk7w5vWsk5s= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= +github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+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/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= +github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= +github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= github.com/ethereum/go-ethereum v1.16.2 h1:VDHqj86DaQiMpnMgc7l0rwZTg0FRmlz74yupSG5SnzI= github.com/ethereum/go-ethereum v1.16.2/go.mod h1:X5CIOyo8SuK1Q5GnaEizQVLHT/DfsiGWuNeVdQcEMNA= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= +github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +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/solana-go v1.13.0 h1:uNzhjwdAdbq9xMaX2DF0MwXNMw6f8zdZ7JPBtkJG7Ig= github.com/gagliardetto/solana-go v1.13.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY= github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -70,6 +208,9 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/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-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -78,6 +219,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= +github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -85,9 +228,15 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -104,6 +253,9 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/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.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -115,24 +267,58 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/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/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg= github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/hasura/go-graphql-client v0.13.1 h1:kKbjhxhpwz58usVl+Xvgah/TDha5K2akNTRQdsEHN6U= +github.com/hasura/go-graphql-client v0.13.1/go.mod h1:k7FF7h53C+hSNFRG3++DdVZWIuHdCaTbI7siTJ//zGQ= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -186,8 +372,14 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f 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 v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmank88/gomods v0.1.6 h1:HNHM9x2QPdF7R72pm83MZpori5AlPiXiukTdLqrUJYE= github.com/jmank88/gomods v0.1.6/go.mod h1:mFFORqytinYpCj2zbyAqAka1R8LZOG9N34uvMzKVSyA= github.com/jmank88/modgraph v0.1.1 h1:Lz9XlGbsb//zsHRDPq+fbU28NaSgUwUY/1PjbOMLnew= @@ -196,9 +388,13 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I= +github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= @@ -217,6 +413,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -227,6 +425,10 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/marcboeker/go-duckdb v1.8.5 h1:tkYp+TANippy0DaIOP5OEfBEwbUINqiFqgwMQ44jME0= @@ -243,36 +445,91 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= +github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= +github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +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= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -282,17 +539,31 @@ github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2 github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= 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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= +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/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= +github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -302,22 +573,53 @@ github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97M github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/smartcontractkit/chain-selectors v1.0.67 h1:gxTqP/JC40KDe3DE1SIsIKSTKTZEPyEU1YufO1admnw= -github.com/smartcontractkit/chain-selectors v1.0.67/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartcontractkit/chain-selectors v1.0.72 h1:AExF2H3mABdLCN0QZd+IjU8CkblTZLKJqvp4vcwew+g= +github.com/smartcontractkit/chain-selectors v1.0.72/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b h1:scWqERf9tWr5ocX/nENI1Kc9FqSl2y87bglwjXbe3XA= +github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b/go.mod h1:zNZ5rtLkbqsGCjDWb1y8n7BRk2zgflkzmj2GjnLnj08= github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 h1:Lz2/FNeODZr7YGY6uOPf2n87o0rrKfsNxr5Bx6VcQ7I= github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960/go.mod h1:W3d6TbZ4PNLGb8QOK8URc/tVWBhnAOwtAYsQ2iPgwtw= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a h1:kQ8Zs6OzXizScIK8PEb8THxDUziGttGT9D6tTTAwmZk= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:Ve1xD71bl193YIZQEoJMmBqLGQJdNs29bwbuObwvbhQ= +github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a h1:38dAlTPRUQHZus5dCnBnQyf/V4oYn0p2svWlbPgHDQ4= +github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:xtZNi6pOKdC3sLvokDvXOhgHzT+cyBqH/gWwvxTxqrg= github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 h1:xyGWWEwIwZv4wflEA12TDBGKEa86tDEECzl3n1Az2m0= github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142/go.mod h1:1r3aM96KHAESfnayJ3BTHCkP1qJS1BEG1r4czeoaXlA= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4 h1:hvqATtrZ0iMRTI80cpBot/3JFbjz2j+2tvpfooVhRHw= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.4/go.mod h1:eKGyfTKzr0/PeR7qKN4l2FcW9p+HzyKUwAfGhm/5YZc= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 h1:0BMVTqGYmYV2xf7s+OI9HzbYkNpBj+TgiqCHB4zJAcA= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0/go.mod h1:71uC1ddxWsxq7uf5rCAjlSo/8mmIdvNwahqgoNrrx90= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2 h1:1/KdO5AbUr3CmpLjMPuJXPo2wHMbfB8mldKLsg7D4M8= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250911124514-5874cc6d62b2/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.12.0 h1:/bhoALRzNXZkdzxBkNM505pMofNy0K0eW1nCzXw+AUI= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.12.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f h1:7saUNbu+edzDgRPedNFfTsx5+5RL40r1r0pgISoh8Hs= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f/go.mod h1:CTR5agBB07sCpRltBkHmnkCZ+g8sXRafCJge/Hqr7aM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 h1:mDxJnEl5jKs3FLHKIjwtCFEP4ihKhFS6yuPDNcC0EDM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30/go.mod h1:SoCjdzeZHP500QtKAjJ9I6rHD03SkQmRL4dNkOoe6yk= +github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335 h1:7bxYNrPpygn8PUSBiEKn8riMd7CXMi/4bjTy0fHhcrY= +github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20250815105909-75499abc4335/go.mod h1:ccjEgNeqOO+bjPddnL4lUrNLzyCvGCxgBjJdhFX3wa8= +github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d h1:qLmSOOtB/Ogn79eIDkuujOu8M5Jd747V1H7Brk/nTvo= +github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d/go.mod h1:4WhGgCA0smBbBud5mK+jnDb2wwndMvoqaWBJ3OV/7Bw= github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY= github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= -github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= +github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358 h1:+NVzR5LZVazRUunzVn34u+lwnpmn6NTVPCeZOVyQHLo= +github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= +github.com/smartcontractkit/mcms v0.25.0 h1:GTkG6jQ2CYoVQFKkRQnA42IvUrR4gObeHqwrQNRhmGM= +github.com/smartcontractkit/mcms v0.25.0/go.mod h1:7v5DNfWqIS81nISbuFBrlV1QHZfD+pFQzjsxqqhcK9o= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 h1:ba4VRWSkRzgdP5hB5OxexIzBXZbSwgcw8bEu06ivGQI= +github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863/go.mod h1:oPTjPNrRucLv9mU27iNPj6n0CWWcNFhoXFOLVGJwHCA= github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -331,35 +633,69 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= 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.38.0 h1:d7uEapLcv2P8AvH8ahLqDMMxda2W9gQN1nRbHS28HBw= +github.com/testcontainers/testcontainers-go v0.38.0/go.mod h1:C52c9MoHpWO+C4aqmgSU+hxlR5jlEayWtgYrb8Pzz1w= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= 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/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xssnick/tonutils-go v1.14.1 h1:zV/iVYl/h3hArS+tPsd9XrSFfGert3r21caMltPSeHg= github.com/xssnick/tonutils-go v1.14.1/go.mod h1:68xwWjpoGGqiTbLJ0gT63sKu1Z1moCnDLLzA+DKanIg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6 h1:VRdX3Gn/I7ITbzUY4ZNfgn65tdQM9Zhf2b7KP0HZllk= +github.com/zksync-sdk/zksync2-go v1.1.1-0.20250620124214-2c742ee399c6/go.mod h1:NWNlQS21isOsSsn+hLRAPpiuv+3P+LcdaZNuRt2T5Yo= go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM= go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 h1:06ZeJRe5BnYXceSM9Vya83XXVaNGe3H1QqsvqRANQq8= @@ -403,6 +739,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -412,6 +750,8 @@ 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.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= +go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= 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= @@ -419,12 +759,14 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/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-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -450,13 +792,17 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -481,15 +827,23 @@ golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/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= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -505,6 +859,7 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -529,8 +884,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -595,14 +950,24 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 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/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 27e50ce5d..03ae377b5 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -5,14 +5,15 @@ go 1.24.5 toolchain go1.24.6 require ( - github.com/smartcontractkit/chain-selectors v1.0.67 + github.com/Masterminds/semver/v3 v3.4.0 + github.com/smartcontractkit/chain-selectors v1.0.72 github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 - github.com/smartcontractkit/chainlink-deployments-framework v0.44.0 + github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 github.com/smartcontractkit/chainlink-ton v0.0.0-20250904183752-4ea5c19ee886 github.com/smartcontractkit/chainlink-ton/deployment v0.0.0-20250904183752-4ea5c19ee886 github.com/smartcontractkit/chainlink/deployment v0.0.0-20250910142604-9ad532208b79 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 github.com/xssnick/tonutils-go v1.14.1 go.uber.org/zap v1.27.0 ) @@ -47,7 +48,6 @@ require ( github.com/DataDog/zstd v1.5.6 // indirect github.com/Khan/genqlient v0.7.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect - github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.12.5 // indirect github.com/NethermindEth/starknet.go v0.8.0 // indirect @@ -87,7 +87,7 @@ require ( github.com/bits-and-blooms/bitset v1.20.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect - github.com/block-vision/sui-go-sdk v1.0.6 // indirect + github.com/block-vision/sui-go-sdk v1.0.9 // indirect github.com/btcsuite/btcd v0.24.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/btcutil v1.1.6 // indirect @@ -142,7 +142,7 @@ require ( github.com/dgraph-io/badger/v4 v4.7.0 // indirect github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.3.2+incompatible // indirect + github.com/docker/docker v28.3.3+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 @@ -260,6 +260,7 @@ require ( github.com/jackc/pgtype v1.14.4 // indirect github.com/jackc/pgx/v4 v4.18.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect @@ -348,6 +349,7 @@ require ( github.com/rs/zerolog v1.33.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/samber/lo v1.49.1 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect @@ -382,7 +384,8 @@ require ( github.com/smartcontractkit/chainlink-protos/svr v1.1.0 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250908151016-bf310cf85379 // indirect github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250905170534-87e867e6cf31 // indirect - github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23 // indirect + github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f // indirect + github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.4 // indirect github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.2 // indirect @@ -391,14 +394,14 @@ require ( github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d // indirect - github.com/smartcontractkit/mcms v0.21.1 // indirect + github.com/smartcontractkit/mcms v0.25.0 // indirect github.com/smartcontractkit/smdkg v0.0.0-20250905122113-4057e4fe4b25 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20250624150019-e49f7e125e6b // indirect github.com/smartcontractkit/wsrpc v0.8.5-0.20250502134807-c57d3d995945 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/cobra v1.10.1 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 // indirect github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -465,7 +468,7 @@ require ( golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.34.0 // indirect golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect golang.org/x/tools v0.35.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 203ee8a5a..0e15cb179 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -201,8 +201,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= -github.com/block-vision/sui-go-sdk v1.0.6 h1:FysCc4TJC8v4BEBbCjJPDR4iR5eKqJT1dxGwsT67etg= -github.com/block-vision/sui-go-sdk v1.0.6/go.mod h1:FyK1vGE8lWm9QA1fdQpf1agfXQSMbPT8AV1BICgx6d8= +github.com/block-vision/sui-go-sdk v1.0.9 h1:vp8y+nSshTdTyhiDYy6Z/4aEsyTbveJ6n8ALg53GHWg= +github.com/block-vision/sui-go-sdk v1.0.9/go.mod h1:V9vmxB2pyYdy8eXV+x5lb/PcSVt3ytvF43m3NUlybx0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -393,8 +393,8 @@ github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa5 github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= -github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= +github.com/docker/docker v28.3.3+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= @@ -857,6 +857,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1202,8 +1204,10 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD 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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= -github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= @@ -1248,8 +1252,8 @@ github.com/smartcontractkit/ccip-contract-examples/chains/evm v0.0.0-20250826190 github.com/smartcontractkit/ccip-contract-examples/chains/evm v0.0.0-20250826190403-aed7f5f33cde/go.mod h1:SYc+BvAALmwsx2zMJIAczIyVNwsiXRIBXmejcTORxGE= github.com/smartcontractkit/ccip-owner-contracts v0.1.0 h1:GiBDtlx7539o7AKlDV+9LsA7vTMPv+0n7ClhSFnZFAk= github.com/smartcontractkit/ccip-owner-contracts v0.1.0/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.67 h1:gxTqP/JC40KDe3DE1SIsIKSTKTZEPyEU1YufO1admnw= -github.com/smartcontractkit/chain-selectors v1.0.67/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.72 h1:AExF2H3mABdLCN0QZd+IjU8CkblTZLKJqvp4vcwew+g= +github.com/smartcontractkit/chain-selectors v1.0.72/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b h1:scWqERf9tWr5ocX/nENI1Kc9FqSl2y87bglwjXbe3XA= github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b/go.mod h1:zNZ5rtLkbqsGCjDWb1y8n7BRk2zgflkzmj2GjnLnj08= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= @@ -1268,8 +1272,8 @@ github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-2025041523564 github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7/go.mod h1:yaDOAZF6MNB+NGYpxGCUc+owIdKrjvFW0JODdTcQ3V0= github.com/smartcontractkit/chainlink-data-streams v0.1.2 h1:g/UmFJa/E1Zmc7NO20ob5SijxQen51DhnqTLr2f7BEc= github.com/smartcontractkit/chainlink-data-streams v0.1.2/go.mod h1:lxY97sDlDorQAmLGFo6x1tl8SQ2E7adsS0/wU8+mmTc= -github.com/smartcontractkit/chainlink-deployments-framework v0.44.0 h1:v3YxZ+kPm35Ea7J3tFJRhelZchBWo7PkuA+prwlRtSo= -github.com/smartcontractkit/chainlink-deployments-framework v0.44.0/go.mod h1:SpkLAp0QnfKPF2BNQfmwUz8goF8XbF2wGGqyjDAfJGA= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 h1:0BMVTqGYmYV2xf7s+OI9HzbYkNpBj+TgiqCHB4zJAcA= +github.com/smartcontractkit/chainlink-deployments-framework v0.52.0/go.mod h1:71uC1ddxWsxq7uf5rCAjlSo/8mmIdvNwahqgoNrrx90= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20250909183314-c46f62fb74f6 h1:5BMWJBiVxafrXQ+cMj3GOnNQ6MTgsIC9T3q/04LZ3f0= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20250909183314-c46f62fb74f6/go.mod h1:FvtivQibe2N7XYsZ/EqGcSLFy40yVMa/7zaHUA60VKk= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20250827130336-5922343458be h1:NRldnH+Q6v8TjO3sBGo1mL/VRGeaPVneY2L13tCx114= @@ -1302,8 +1306,10 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250908151016- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20250908151016-bf310cf85379/go.mod h1:HIpGvF6nKCdtZ30xhdkKWGM9+4Z4CVqJH8ZBL1FTEiY= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250905170534-87e867e6cf31 h1:NzyJvTqIJXJA3jXDkDnoEIbHoWtcEOeqTm5F+I+llUw= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20250905170534-87e867e6cf31/go.mod h1:6vmFNkzEDz7YTVBa+I2bmTf6a9ecAJyoDfey7BSfbak= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23 h1:+L8R3Nn4ZadjGUDUr7HKVMt9I1vv5IS/IzUfQzyNvDw= -github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.23/go.mod h1:gdW2dlrvHcTawMCtAIXQYZcZ9Ggx16L55kA7wONvzJ4= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f h1:7saUNbu+edzDgRPedNFfTsx5+5RL40r1r0pgISoh8Hs= +github.com/smartcontractkit/chainlink-sui v0.0.0-20250916193659-4becc28a467f/go.mod h1:CTR5agBB07sCpRltBkHmnkCZ+g8sXRafCJge/Hqr7aM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 h1:mDxJnEl5jKs3FLHKIjwtCFEP4ihKhFS6yuPDNcC0EDM= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30/go.mod h1:SoCjdzeZHP500QtKAjJ9I6rHD03SkQmRL4dNkOoe6yk= github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.4 h1:gbQqdsF8mVRgh4h4KRi+8b00OT3Wp/6zrN0uXr0i/J0= github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.4/go.mod h1:dgwtcefGr+0i+C2S6V/Xgntzm7E5CPxXMyi2OnQvnHI= github.com/smartcontractkit/chainlink-testing-framework/parrot v0.6.2 h1:cWUHB6QETyKbmh0B988f5AKIKb3aBDWugfrZ04jAUUY= @@ -1326,8 +1332,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12i github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= -github.com/smartcontractkit/mcms v0.21.1 h1:vbM1c45Hd526XTKdXy2G1YKlMyzyc+ybdPTK79UlkKg= -github.com/smartcontractkit/mcms v0.21.1/go.mod h1:7bg4JECK7UHvXAJ7/kzvCNLzUu8JxKvvti3ko9y3FpI= +github.com/smartcontractkit/mcms v0.25.0 h1:GTkG6jQ2CYoVQFKkRQnA42IvUrR4gObeHqwrQNRhmGM= +github.com/smartcontractkit/mcms v0.25.0/go.mod h1:7v5DNfWqIS81nISbuFBrlV1QHZfD+pFQzjsxqqhcK9o= github.com/smartcontractkit/smdkg v0.0.0-20250905122113-4057e4fe4b25 h1:zxZHMnCEjSfQYq9vzWUZncikyAy971yU7GsviXVGmLM= github.com/smartcontractkit/smdkg v0.0.0-20250905122113-4057e4fe4b25/go.mod h1:Cxtf6GUlIhyQRT6BSl39VhPOySGgsB85nmYGiICDnAs= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= @@ -1340,24 +1346,25 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863 h1:ba4VRWSkRzgdP5hB5OxexIzBXZbSwgcw8bEu06ivGQI= github.com/stephenlacy/go-ethereum-hdwallet v0.0.0-20230913225845-a4fa94429863/go.mod h1:oPTjPNrRucLv9mU27iNPj6n0CWWcNFhoXFOLVGJwHCA= github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= @@ -1383,8 +1390,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1570,6 +1577,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1847,8 +1856,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/integration-tests/jetton/jetton_test.go b/integration-tests/jetton/jetton_test.go index 5b284ac92..adce2d017 100644 --- a/integration-tests/jetton/jetton_test.go +++ b/integration-tests/jetton/jetton_test.go @@ -6,10 +6,11 @@ import ( "math/rand/v2" "path" "slices" - "strings" "sync" "testing" + "github.com/Masterminds/semver/v3" + "github.com/smartcontractkit/chainlink-ton/integration-tests/tracetracking/testutils" chainsel "github.com/smartcontractkit/chain-selectors" @@ -21,15 +22,20 @@ import ( "github.com/xssnick/tonutils-go/ton/nft" "github.com/xssnick/tonutils-go/tvm/cell" - jetton_wrappers "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + jetton_common "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/minter" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" jetton_testing_wrappers "github.com/smartcontractkit/chainlink-ton/pkg/bindings/test/examples/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) // Helper function to load the actual JettonWallet code func loadJettonWalletCode() (*cell.Cell, error) { - jettonWalletPath := path.Join(jetton_wrappers.PathToContracts, "JettonWallet.compiled.json") + jettonWalletPath := path.Join(jetton_common.PathToContracts, "JettonWallet.compiled.json") compiledContract, err := wrappers.ParseCompiledContract(jettonWalletPath) if err != nil { return nil, fmt.Errorf("failed to parse JettonWallet contract: %w", err) @@ -80,7 +86,7 @@ func TestJettonAll(t *testing.T) { require.NoError(t, err, "failed to load JettonWallet code") t.Logf("Deploying JettonMinter contract\n") - setup.jettonMinter = DeployMinter(t, &setup.deployer, jetton_wrappers.MinterInitData{ + setup.jettonMinter = DeployMinter(t, &setup.deployer, minter.InitData{ TotalSupply: tlb.ZeroCoins, Admin: setup.deployer.Wallet.WalletAddress(), TransferAdmin: nil, @@ -112,11 +118,11 @@ func TestJettonAll(t *testing.T) { t.Logf("Minting jettons to sender contract\n") queryID := rand.Uint64() - sendMintMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + sendMintMsg, err := setup.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: Sender.Contract.Address, TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: jettonMintingAmount, From: setup.deployer.Wallet.WalletAddress(), @@ -126,13 +132,13 @@ func TestJettonAll(t *testing.T) { }, }, tlb.MustFromTON("0.05")) require.NoError(t, err, "failed to mint jettons") - t.Logf("Msg trace:\n%s\n", replaceAddresses( - map[string]string{ - setup.deployer.Wallet.Address().String(): "Deployer", - Sender.Contract.Address.String(): "Sender", - setup.jettonMinter.Address.String(): "JettonMinter", - }, - sendMintMsg.Dump())) + + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + Sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Msg trace:\n%s\n", debugger.DumpReceived(sendMintMsg)) require.Zero(t, sendMintMsg.ExitCode, "Msg to wallet should have exit code 0") require.Len(t, sendMintMsg.OutgoingInternalReceivedMessages, 1, "Msg to wallet should have 1 outgoing message") @@ -180,11 +186,11 @@ func TestJettonAll(t *testing.T) { t.Logf("OnrampMock contract deployed at %s\n", onrampMock.Contract.Address.String()) queryID := rand.Uint64() - _, err = setup.common.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + _, err = setup.common.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: setup.sender.Contract.Address, TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: tlb.MustFromTON("1"), From: setup.common.deployer.Wallet.WalletAddress(), @@ -213,7 +219,7 @@ func TestJettonAll(t *testing.T) { t.Logf("Deploying SimpleJettonReceiver contract\n") simpleJettonReceiver, err := jetton_testing_wrappers.NewSimpleJettonReceiverProvider(setup.common.deployer).Deploy(jetton_testing_wrappers.SimpleJettonReceiverInitData{ - JettonClient: jetton_wrappers.Client{ + JettonClient: jetton_common.Client{ MasterAddress: setup.common.jettonMinter.Address, WalletCode: setup.common.jettonWalletCode, }, @@ -224,11 +230,11 @@ func TestJettonAll(t *testing.T) { t.Logf("SimpleJettonReceiver contract deployed at %s\n", simpleJettonReceiver.Contract.Address.String()) queryID := rand.Uint64() - _, err = setup.common.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + _, err = setup.common.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: setup.sender.Contract.Address, TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: tlb.MustFromTON("1"), From: setup.common.deployer.Wallet.WalletAddress(), @@ -256,11 +262,11 @@ func TestJettonAll(t *testing.T) { t.Logf("Minting jettons to sender contract\n") queryID := rand.Uint64() - sendMintMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + sendMintMsg, err := setup.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: setup.deployer.Wallet.WalletAddress(), TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: jettonMintingAmount, From: setup.deployer.Wallet.WalletAddress(), @@ -335,16 +341,17 @@ func TestJettonAll(t *testing.T) { t.Logf("Testing change content\n") const newContentURI = "new_content_uri" newContent := createStringCell(t, newContentURI) - changeContentMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.ChangeContentMessage{ + changeContentMsg, err := setup.jettonMinter.CallWaitRecursively(minter.ChangeContentMessage{ QueryID: rand.Uint64(), Content: newContent, }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to change content") - t.Logf("Change content message received: \n%s\n", replaceAddresses(map[string]string{ - setup.deployer.Wallet.Address().String(): "Deployer", - setup.jettonMinter.Address.String(): "JettonMinter", - newContent.String(): "NewContent", - }, changeContentMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + newContent.String(): {Type: "NewContent", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Change content message received: \n%s\n", debugger.DumpReceived(changeContentMsg)) jettonData, err := setup.jettonClient.GetJettonData(t.Context()) require.NoError(t, err, "failed to get jetton data after content change") @@ -373,11 +380,12 @@ func TestJettonAll(t *testing.T) { recipient := address.MustParseAddr("UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ") jettonAmount := tlb.MustFromTON("0.5") queryID := rand.Uint64() - mintMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + + mintMsg, err := setup.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: recipient, TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: jettonAmount, From: setup.deployer.Wallet.WalletAddress(), @@ -387,11 +395,13 @@ func TestJettonAll(t *testing.T) { }, }, tlb.MustFromTON("0.5")) require.NoError(t, err, "failed to mint jettons") - t.Logf("Jetton minting message received: \n%s\n", replaceAddresses(map[string]string{ - setup.deployer.Wallet.Address().String(): "Deployer", - setup.jettonMinter.Address.String(): "JettonMinter", - recipient.String(): "Recipient", - }, mintMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + recipient.String(): {Type: "Recipient", Version: *semver.MustParse("0.0.1")}, + }) + + t.Logf("Jetton minting message received: \n%s\n", debugger.DumpReceived(mintMsg)) receiverWallet, err := setup.jettonClient.GetJettonWallet(t.Context(), recipient) require.NoError(t, err, "failed to get receiver wallet") @@ -404,28 +414,30 @@ func TestJettonAll(t *testing.T) { t.Parallel() setup := setUpCommon(t) t.Logf("Testing change admin\n") - changeAdminMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.ChangeAdminMessage{ + changeAdminMsg, err := setup.jettonMinter.CallWaitRecursively(minter.ChangeAdminMessage{ QueryID: rand.Uint64(), NewAdmin: setup.receiver.Wallet.Address(), }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to change admin") - t.Logf("Change admin message received: \n%s\n", replaceAddresses(map[string]string{ - setup.deployer.Wallet.Address().String(): "Deployer", - setup.jettonMinter.Address.String(): "JettonMinter", - setup.receiver.Wallet.Address().String(): "NewAdmin", - }, changeAdminMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + setup.receiver.Wallet.Address().String(): {Type: "NewAdmin", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Change admin message received: \n%s\n", debugger.DumpReceived(changeAdminMsg)) jettonMinterAsReceiver := wrappers.Contract{ Address: setup.jettonMinter.Address, Client: &setup.receiver, } require.NoError(t, err, "failed to open jetton minter as new admin") - claimAdminMsg, err := jettonMinterAsReceiver.CallWaitRecursively(jetton_wrappers.ClaimAdminMessage{QueryID: rand.Uint64()}, tlb.MustFromTON("0.1")) + claimAdminMsg, err := jettonMinterAsReceiver.CallWaitRecursively(minter.ClaimAdminMessage{QueryID: rand.Uint64()}, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to claim admin") - t.Logf("Claim admin message received: \n%s\n", replaceAddresses(map[string]string{ - setup.receiver.Wallet.Address().String(): "NewAdmin", - setup.jettonMinter.Address.String(): "JettonMinter", - }, claimAdminMsg.Dump())) + debugger2 := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.receiver.Wallet.Address().String(): {Type: "NewAdmin", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Claim admin message received: \n%s\n", debugger2.DumpReceived(claimAdminMsg)) require.Zero(t, claimAdminMsg.ExitCode, "Claim admin message should have exit code 0") jettonData, err := setup.jettonClient.GetJettonData(t.Context()) @@ -437,15 +449,16 @@ func TestJettonAll(t *testing.T) { t.Parallel() setup := setUpCommon(t) t.Logf("Testing drop admin\n") - dropAdminMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.DropAdminMessage{ + dropAdminMsg, err := setup.jettonMinter.CallWaitRecursively(minter.DropAdminMessage{ QueryID: rand.Uint64(), }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to drop admin") - t.Logf("Drop admin message received: \n%s\n", replaceAddresses(map[string]string{ - setup.deployer.Wallet.Address().String(): "Deployer", - setup.jettonMinter.Address.String(): "JettonMinter", - setup.receiver.Wallet.Address().String(): "NewAdmin", - }, dropAdminMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + setup.receiver.Wallet.Address().String(): {Type: "NewAdmin", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Drop admin message received: \n%s\n", debugger.DumpReceived(dropAdminMsg)) require.Zero(t, dropAdminMsg.ExitCode, "Drop admin message should have exit code 0") require.Len(t, dropAdminMsg.OutgoingInternalReceivedMessages, 1, "Drop admin message should have 1 outgoing message") msgToMinter := dropAdminMsg.OutgoingInternalReceivedMessages[0] @@ -453,11 +466,11 @@ func TestJettonAll(t *testing.T) { require.Empty(t, msgToMinter.OutgoingInternalReceivedMessages, "Msg to minter should have no outgoing messages") queryID := rand.Uint64() - mintMsg, err := setup.jettonMinter.CallWaitRecursively(jetton_wrappers.MintMessage{ + mintMsg, err := setup.jettonMinter.CallWaitRecursively(minter.MintMessage{ QueryID: queryID, Destination: setup.receiver.Wallet.Address(), TonAmount: tlb.MustFromTON("0.05"), - MasterMsg: jetton_wrappers.InternalTransferMessage{ + MasterMsg: wallet.InternalTransferMessage{ QueryID: queryID, Amount: jettonMintingAmount, From: setup.deployer.Wallet.WalletAddress(), @@ -470,7 +483,7 @@ func TestJettonAll(t *testing.T) { require.Zero(t, mintMsg.ExitCode, "Mint message should have exit code 0") require.Len(t, mintMsg.OutgoingInternalReceivedMessages, 1, "Mint message should have 1 outgoing message") msgToMinter = mintMsg.OutgoingInternalReceivedMessages[0] - require.Equal(t, jetton_wrappers.ErrorNotOwner, msgToMinter.ExitCode, "Msg to minter should have") + require.Equal(t, jetton_common.ErrorNotOwner, msgToMinter.ExitCode, "Msg to minter should have") jettonData, err := setup.jettonClient.GetJettonData(t.Context()) require.NoError(t, err, "failed to get jetton data after admin change") @@ -493,12 +506,13 @@ func TestJettonAll(t *testing.T) { }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to send jettons in basic mode") t.Log("Jettons sent successfully") - t.Logf("Sender message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.sender.Contract.Address.String(): "Sender", - setup.common.jettonMinter.Address.String(): "JettonMinter", - receiver.String(): "Receiver", - }, msgReceived.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + receiver.String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Sender message received: \n%s\n", debugger.DumpReceived(msgReceived)) receiverWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), receiver) require.NoError(t, err, "failed to get receiver wallet") @@ -511,19 +525,20 @@ func TestJettonAll(t *testing.T) { t.Parallel() setup := setupSender(t) t.Logf("Deploying JettonMinter contract\n") - jettonWalletCode, err := jetton_wrappers.WalletCode() + jettonWalletCode, err := wallet.Code() require.NoError(t, err, "failed to deploy JettonWallet contract") - jettonWalletInitCell, err := jetton_wrappers.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.receiver.Wallet.Address()) + jettonWalletInitCell, err := wallet.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.receiver.Wallet.Address()) require.NoError(t, err, "failed to get JettonWallet init cell") - msg, err := tlb.ToCell(jetton_wrappers.TopUpMessage{QueryID: rand.Uint64()}) + msg, err := tlb.ToCell(jetton_common.TopUpMessage{QueryID: rand.Uint64()}) require.NoError(t, err, "failed to create top-up message") receiverJettonWallet, deployMsg, err := wrappers.Deploy(&setup.common.receiver, jettonWalletCode, jettonWalletInitCell, tlb.MustFromTON("0.1"), msg) require.NoError(t, err, "failed to deploy JettonWallet contract") - t.Logf("JettonWallet contract deploy message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.common.receiver.Wallet.Address().String(): "Receiver", - receiverJettonWallet.Address.String(): "ReceiverJettonWallet", - }, deployMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.common.receiver.Wallet.Address().String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + receiverJettonWallet.Address.String(): {Type: "ReceiverJettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("JettonWallet contract deploy message received: \n%s\n", debugger.DumpReceived(deployMsg)) t.Logf("JettonWallet contract deployed at %s\n", receiverJettonWallet.Address.String()) jettonAmount := tlb.MustFromTON("12") @@ -535,12 +550,13 @@ func TestJettonAll(t *testing.T) { }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to send jettons in basic mode") t.Log("Jettons sent successfully") - t.Logf("Sender message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.sender.Contract.Address.String(): "Sender", - setup.common.jettonMinter.Address.String(): "JettonMinter", - setup.common.receiver.Wallet.Address().String(): "Receiver", - }, msgReceived.Dump())) + debugger2 := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + setup.common.receiver.Wallet.Address().String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Sender message received: \n%s\n", debugger2.DumpReceived(msgReceived)) receiverWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), setup.common.receiver.Wallet.Address()) require.NoError(t, err, "failed to get receiver wallet") @@ -570,12 +586,13 @@ func TestJettonAll(t *testing.T) { ForwardPayload: forwardPayload, }, tonAmount) require.NoError(t, err, "failed to send jettons in basic mode") - t.Logf("Sent jettons extended:\n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.sender.Contract.Address.String(): "Sender", - setup.common.jettonMinter.Address.String(): "JettonMinter", - receiver.String(): "Receiver", - }, msgJettonsExtended.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + receiver.String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Sent jettons extended:\n%s\n", debugger.DumpReceived(msgJettonsExtended)) receiverWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), receiver) require.NoError(t, err, "failed to get receiver wallet") @@ -619,14 +636,15 @@ func TestJettonAll(t *testing.T) { ForwardPayload: jettonTransferPayload, }, tlb.MustFromTON("2")) require.NoError(t, err2, "failed to send jettons with custom payload") - t.Logf("Sender message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.Sender.Contract.Address.String(): "Sender", - SenderWallet.Address().String(): "SenderWallet", - setup.common.jettonMinter.Address.String(): "JettonMinter", - setup.onrampMock.Contract.Address.String(): "OnrampMock", - onrampMockJettonWallet.Address().String(): "OnrampMockJettonWallet", - }, msgReceived.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.Sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + SenderWallet.Address().String(): {Type: "SenderWallet", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + setup.onrampMock.Contract.Address.String(): {Type: "OnrampMock", Version: *semver.MustParse("0.0.1")}, + onrampMockJettonWallet.Address().String(): {Type: "OnrampMockJettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Sender message received: \n%s\n", debugger.DumpReceived(msgReceived)) require.NotEmpty(t, msgReceived.OutgoingInternalReceivedMessages, "Outgoing internal messages should not be empty") msgToSender := msgReceived.OutgoingInternalReceivedMessages[0] require.NotEmpty(t, msgToSender.OutgoingInternalReceivedMessages, "Outgoing internal messages should not be empty") @@ -724,14 +742,15 @@ func TestJettonAll(t *testing.T) { require.NoError(t, err, "failed to get jetton sender wallet") SimpleJettonReceiverWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), setup.simpleReceiver.Contract.Address) require.NoError(t, err, "failed to get simple jetton receiver wallet") - t.Logf("Jettons sent: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.Sender.Contract.Address.String(): "Sender", - SenderWallet.Address().String(): "SenderWallet", - setup.common.jettonMinter.Address.String(): "JettonMinter", - setup.simpleReceiver.Contract.Address.String(): "SimpleJettonReceiver", - SimpleJettonReceiverWallet.Address().String(): "SimpleJettonReceiverWallet", - }, receivedMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.Sender.Contract.Address.String(): {Type: "Sender", Version: *semver.MustParse("0.0.1")}, + SenderWallet.Address().String(): {Type: "SenderWallet", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + setup.simpleReceiver.Contract.Address.String(): {Type: "SimpleJettonReceiver", Version: *semver.MustParse("0.0.1")}, + SimpleJettonReceiverWallet.Address().String(): {Type: "SimpleJettonReceiverWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Jettons sent: \n%s\n", debugger.DumpReceived(receivedMsg)) t.Logf("Testing receiver checkers\n") amountChecker, err = setup.simpleReceiver.GetAmountChecker() @@ -753,19 +772,20 @@ func TestJettonAll(t *testing.T) { setup := setupJettonWallet(t) t.Logf("Deploying JettonWallet contract\n") - msg, err := tlb.ToCell(jetton_wrappers.TopUpMessage{QueryID: rand.Uint64()}) + msg, err := tlb.ToCell(jetton_common.TopUpMessage{QueryID: rand.Uint64()}) require.NoError(t, err, "failed to create top-up message") - jettonWalletCode, err := jetton_wrappers.WalletCode() + jettonWalletCode, err := wallet.Code() require.NoError(t, err, "failed to deploy JettonWallet contract") - jettonWalletInitCell, err := jetton_wrappers.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) + jettonWalletInitCell, err := wallet.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) require.NoError(t, err, "failed to get JettonWallet init cell") deployerJettonWallet, deployMsg, err := wrappers.Deploy(&setup.common.deployer, jettonWalletCode, jettonWalletInitCell, tlb.MustFromTON("0.1"), msg) require.NoError(t, err, "failed to deploy JettonWallet contract") - t.Logf("Deploy message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.common.jettonMinter.Address.String(): "JettonMinter", - deployerJettonWallet.Address.String(): "JettonWallet", - }, deployMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + deployerJettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Deploy message received: \n%s\n", debugger.DumpReceived(deployMsg)) t.Logf("JettonWallet contract opened at %s\n", deployerJettonWallet.Address.String()) @@ -794,13 +814,14 @@ func TestJettonAll(t *testing.T) { require.NoError(t, err, "failed to transfer jettons") receiverJettonWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), recipient) require.NoError(t, err, "failed to get receiver wallet") - t.Logf("Jetton transfer message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - deployerJettonWallet.Address.String(): "JettonWallet", - setup.common.jettonMinter.Address.String(): "JettonMinter", - recipient.String(): "Receiver", - receiverJettonWallet.Address().String(): "ReceiverJettonWallet", - }, transferMsg.Dump())) + debugger = debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + deployerJettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + recipient.String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + receiverJettonWallet.Address().String(): {Type: "ReceiverJettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Transfer message received: \n%s\n", debugger.DumpReceived(transferMsg)) jettonBalance, err := receiverJettonWallet.GetBalance(t.Context()) require.NoError(t, err, "failed to get receiver wallet balance") @@ -812,19 +833,20 @@ func TestJettonAll(t *testing.T) { setup := setupJettonWallet(t) t.Logf("Deploying JettonWallet contract\n") - jettonWalletCode, err := jetton_wrappers.WalletCode() + jettonWalletCode, err := wallet.Code() require.NoError(t, err, "failed to deploy JettonWallet contract") - jettonWalletInitCell, err := jetton_wrappers.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) + jettonWalletInitCell, err := wallet.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) require.NoError(t, err, "failed to get JettonWallet init cell") - msg, err := tlb.ToCell(jetton_wrappers.TopUpMessage{QueryID: rand.Uint64()}) + msg, err := tlb.ToCell(jetton_common.TopUpMessage{QueryID: rand.Uint64()}) require.NoError(t, err, "failed to create top-up message") deployerJettonWallet, deployMsg, err := wrappers.Deploy(&setup.common.deployer, jettonWalletCode, jettonWalletInitCell, tlb.MustFromTON("0.1"), msg) require.NoError(t, err, "failed to deploy JettonWallet contract") - t.Logf("Deploy message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.common.jettonMinter.Address.String(): "JettonMinter", - deployerJettonWallet.Address.String(): "JettonWallet", - }, deployMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + deployerJettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Deploy message received: \n%s\n", debugger.DumpReceived(deployMsg)) t.Logf("JettonWallet contract opened at %s\n", deployerJettonWallet.Address.String()) @@ -853,13 +875,14 @@ func TestJettonAll(t *testing.T) { require.NoError(t, err, "failed to transfer jettons") receiverJettonWallet, err := setup.common.jettonClient.GetJettonWallet(t.Context(), recipient) require.NoError(t, err, "failed to get receiver wallet") - t.Logf("Jetton transfer message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - deployerJettonWallet.Address.String(): "JettonWallet", - setup.common.jettonMinter.Address.String(): "JettonMinter", - recipient.String(): "Receiver", - receiverJettonWallet.Address().String(): "ReceiverJettonWallet", - }, transferMsg.Dump())) + debugger = debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + deployerJettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + recipient.String(): {Type: "Receiver", Version: *semver.MustParse("0.0.1")}, + receiverJettonWallet.Address().String(): {Type: "ReceiverJettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Transfer message received: \n%s\n", debugger.DumpReceived(transferMsg)) jettonBalance, err := receiverJettonWallet.GetBalance(t.Context()) require.NoError(t, err, "failed to get receiver wallet balance") @@ -870,19 +893,20 @@ func TestJettonAll(t *testing.T) { t.Parallel() setup := setupJettonWallet(t) t.Logf("Deploying JettonWallet contract\n") - jettonWalletCode, err := jetton_wrappers.WalletCode() + jettonWalletCode, err := wallet.Code() require.NoError(t, err, "failed to deploy JettonWallet contract") - jettonWalletInitCell, err := jetton_wrappers.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) + jettonWalletInitCell, err := wallet.NewWalletProvider(setup.common.jettonMinter.Address).GetWalletInitCell(setup.common.deployer.Wallet.Address()) require.NoError(t, err, "failed to get JettonWallet init cell") - msg, err := tlb.ToCell(jetton_wrappers.TopUpMessage{QueryID: rand.Uint64()}) + msg, err := tlb.ToCell(jetton_common.TopUpMessage{QueryID: rand.Uint64()}) require.NoError(t, err, "failed to create top-up message") jettonWallet, deployMsg, err := wrappers.Deploy(&setup.common.deployer, jettonWalletCode, jettonWalletInitCell, tlb.MustFromTON("0.1"), msg) require.NoError(t, err, "failed to deploy JettonWallet contract") - t.Logf("Deploy message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - setup.common.jettonMinter.Address.String(): "JettonMinter", - jettonWallet.Address.String(): "JettonWallet", - }, deployMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + jettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Deploy message received: \n%s\n", debugger.DumpReceived(deployMsg)) t.Logf("JettonWallet contract deployed at %s\n", jettonWallet.Address.String()) @@ -903,11 +927,12 @@ func TestJettonAll(t *testing.T) { }, tlb.MustFromTON("0.1")) require.NoError(t, err, "failed to burn jettons") - t.Logf("Jetton transfer message received: \n%s\n", replaceAddresses(map[string]string{ - setup.common.deployer.Wallet.Address().String(): "Deployer", - jettonWallet.Address.String(): "JettonWallet", - setup.common.jettonMinter.Address.String(): "JettonMinter", - }, burnMsg.Dump())) + debugger2 := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + setup.common.deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + jettonWallet.Address.String(): {Type: "JettonWallet", Version: *semver.MustParse("0.0.1")}, + setup.common.jettonMinter.Address.String(): {Type: "JettonMinter", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Jetton transfer message received: \n%s\n", debugger2.DumpReceived(burnMsg)) balanceAfterBurn, err := jettonWalletClient.GetBalance(t.Context()) require.NoError(t, err, "failed to get jetton balance after burn") @@ -918,30 +943,24 @@ func TestJettonAll(t *testing.T) { }) } -func DeployMinter(t *testing.T, deployer *tracetracking.SignedAPIClient, initData jetton_wrappers.MinterInitData) *wrappers.Contract { - minterCode, err := jetton_wrappers.MinterCode() +func DeployMinter(t *testing.T, deployer *tracetracking.SignedAPIClient, initData minter.InitData) *wrappers.Contract { + minterCode, err := minter.Code() require.NoError(t, err, "failed to load JettonMinter code") - topUpMsg, err := tlb.ToCell(jetton_wrappers.TopUpMessage{ + topUpMsg, err := tlb.ToCell(jetton_common.TopUpMessage{ QueryID: rand.Uint64(), }) require.NoError(t, err, "failed to create TopUp message") minterInitCell, err := tlb.ToCell(initData) require.NoError(t, err, "failed to create JettonMinter init data cell") minterContract, deployMsg, err := wrappers.Deploy(deployer, minterCode, minterInitCell, tlb.MustFromTON("1"), topUpMsg) - t.Logf("Deploy trace: %s\n", replaceAddresses(map[string]string{ - deployer.Wallet.Address().String(): "Deployer", - }, deployMsg.Dump())) + debugger := debug.NewDebuggerTreeTrace(map[string]cldf.TypeAndVersion{ + deployer.Wallet.Address().String(): {Type: "Deployer", Version: *semver.MustParse("0.0.1")}, + }) + t.Logf("Deploy trace: %s\n", debugger.DumpReceived(deployMsg)) require.NoError(t, err, "failed to deploy JettonMinter contract") return minterContract } -func replaceAddresses(addressMap map[string]string, text string) string { - for oldAddr, newAddr := range addressMap { - text = strings.ReplaceAll(text, oldAddr, newAddr) - } - return text -} - func createStringCell(t *testing.T, s string) *cell.Cell { builder := cell.BeginCell() err := builder.StoreStringSnake(s) diff --git a/pkg/bindings/jetton/common.go b/pkg/bindings/jetton/common.go new file mode 100644 index 000000000..e47975b5c --- /dev/null +++ b/pkg/bindings/jetton/common.go @@ -0,0 +1,46 @@ +package jetton + +import ( + "github.com/xssnick/tonutils-go/tlb" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +const ( + OpcodeTopUp = 0xd372158c +) + +const ( + ErrorInvalidOp tvm.ExitCode = tvm.ExitCode(72) + ErrorWrongOp tvm.ExitCode = tvm.ExitCode(0xffff) + ErrorNotOwner tvm.ExitCode = tvm.ExitCode(73) + ErrorNotValidWallet tvm.ExitCode = tvm.ExitCode(74) + ErrorWrongWorkchain tvm.ExitCode = tvm.ExitCode(333) +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + TopUp: codec.TLBCodec[TopUpMessage](), + }, + }, +} + +type inMessageBuilder struct { + TopUp codec.CellCodec[TopUpMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + +// For funding the contract with TON +type TopUpMessage struct { + _ tlb.Magic `tlb:"#d372158c"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} diff --git a/pkg/bindings/jetton/minter.go b/pkg/bindings/jetton/minter.go deleted file mode 100644 index ef49d7e5f..000000000 --- a/pkg/bindings/jetton/minter.go +++ /dev/null @@ -1,106 +0,0 @@ -package jetton - -import ( - "fmt" - - "path" - - "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" - - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" -) - -const ( - ErrorInvalidOp tvm.ExitCode = tvm.ExitCode(72) - ErrorWrongOp tvm.ExitCode = tvm.ExitCode(0xffff) - ErrorNotOwner tvm.ExitCode = tvm.ExitCode(73) - ErrorNotValidWallet tvm.ExitCode = tvm.ExitCode(74) - ErrorWrongWorkchain tvm.ExitCode = tvm.ExitCode(333) -) - -// JettonMinter opcodes -const ( - OpcodeMinterMint = 0x642b7d07 - OpcodeMinterBurnNotification = 0x7bdd97de - OpcodeMinterChangeAdmin = 0x6501f354 - OpcodeMinterClaimAdmin = 0xfb88e119 - OpcodeMinterDropAdmin = 0x7431f221 - OpcodeMinterChangeMetadataURL = 0xcb862902 - OpcodeMinterUpgrade = 0x2508d66a - OpcodeMinterInternalTransfer = 0x178d4519 - OpcodeMinterExcesses = 0xd53276db -) - -var MinterContractPath = path.Join(PathToContracts, "JettonMinter.compiled.json") - -type MinterInitData struct { - TotalSupply tlb.Coins `tlb:"."` - Admin *address.Address `tlb:"addr"` - TransferAdmin *address.Address `tlb:"addr"` - WalletCode *cell.Cell `tlb:"^"` - JettonContent *cell.Cell `tlb:"^"` -} - -func MinterCode() (*cell.Cell, error) { - compiledContract, err := wrappers.ParseCompiledContract(MinterContractPath) - if err != nil { - return nil, fmt.Errorf("failed to compile contract: %w", err) - } - return compiledContract, nil -} - -// For funding the contract with TON -type TopUpMessage struct { - _ tlb.Magic `tlb:"#d372158c"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type InternalTransferMessage struct { - _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"."` - From *address.Address `tlb:"addr"` - ResponseAddress *address.Address `tlb:"addr"` - ForwardTonAmount tlb.Coins `tlb:"."` - ForwardPayload *cell.Cell `tlb:"either . ^"` -} - -type MintMessage struct { - _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Destination *address.Address `tlb:"addr"` - TonAmount tlb.Coins `tlb:"."` - MasterMsg InternalTransferMessage `tlb:"^"` -} - -type ChangeAdminMessage struct { - _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewAdmin *address.Address `tlb:"addr"` -} - -type ClaimAdminMessage struct { - _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type DropAdminMessage struct { - _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type ChangeContentMessage struct { - _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Content *cell.Cell `tlb:"^"` -} - -type UpgradeMessage struct { - _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewData *cell.Cell `tlb:"^"` - NewCode *cell.Cell `tlb:"^"` -} diff --git a/pkg/bindings/jetton/minter/codec.go b/pkg/bindings/jetton/minter/codec.go new file mode 100644 index 000000000..3cbc5887d --- /dev/null +++ b/pkg/bindings/jetton/minter/codec.go @@ -0,0 +1,88 @@ +package minter + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +// JettonMinter opcodes +const ( + OpcodeMinterMint = 0x642b7d07 + OpcodeMinterChangeAdmin = 0x6501f354 + OpcodeMinterClaimAdmin = 0xfb88e119 + OpcodeMinterDropAdmin = 0x7431f221 + OpcodeMinterBurnNotification = 0x7bdd97de + OpcodeMinterChangeMetadataURL = 0xcb862902 + OpcodeWalletBurnNotification = 0x7bdd97de +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + Mint: codec.TLBCodec[MintMessage](), + ChangeAdmin: codec.TLBCodec[ChangeAdminMessage](), + ClaimAdmin: codec.TLBCodec[ClaimAdminMessage](), + DropAdmin: codec.TLBCodec[DropAdminMessage](), + ChangeContent: codec.TLBCodec[ChangeContentMessage](), + Upgrade: codec.TLBCodec[UpgradeMessage](), + }, + }, +} + +type inMessageBuilder struct { + Mint codec.CellCodec[MintMessage] + ChangeAdmin codec.CellCodec[ChangeAdminMessage] + ClaimAdmin codec.CellCodec[ClaimAdminMessage] + DropAdmin codec.CellCodec[DropAdminMessage] + ChangeContent codec.CellCodec[ChangeContentMessage] + Upgrade codec.CellCodec[UpgradeMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + +type MintMessage struct { + _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Destination *address.Address `tlb:"addr"` + TonAmount tlb.Coins `tlb:"."` + MasterMsg wallet.InternalTransferMessage `tlb:"^"` +} + +type ChangeAdminMessage struct { + _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewAdmin *address.Address `tlb:"addr"` +} + +type ClaimAdminMessage struct { + _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type DropAdminMessage struct { + _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type ChangeContentMessage struct { + _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Content *cell.Cell `tlb:"^"` +} + +type UpgradeMessage struct { + _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewData *cell.Cell `tlb:"^"` + NewCode *cell.Cell `tlb:"^"` +} diff --git a/pkg/bindings/jetton/minter/minter.go b/pkg/bindings/jetton/minter/minter.go new file mode 100644 index 000000000..d24f9b330 --- /dev/null +++ b/pkg/bindings/jetton/minter/minter.go @@ -0,0 +1,32 @@ +package minter + +import ( + "fmt" + + "path" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" +) + +var MinterContractPath = path.Join(jetton.PathToContracts, "JettonMinter.compiled.json") + +type InitData struct { + TotalSupply tlb.Coins `tlb:"."` + Admin *address.Address `tlb:"addr"` + TransferAdmin *address.Address `tlb:"addr"` + WalletCode *cell.Cell `tlb:"^"` + JettonContent *cell.Cell `tlb:"^"` +} + +func Code() (*cell.Cell, error) { + compiledContract, err := wrappers.ParseCompiledContract(MinterContractPath) + if err != nil { + return nil, fmt.Errorf("failed to compile contract: %w", err) + } + return compiledContract, nil +} diff --git a/pkg/bindings/jetton/wallet/codec.go b/pkg/bindings/jetton/wallet/codec.go new file mode 100644 index 000000000..22617b986 --- /dev/null +++ b/pkg/bindings/jetton/wallet/codec.go @@ -0,0 +1,84 @@ +package wallet + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// JettonWallet opcodes +const ( + OpcodeWalletTransfer = 0x0f8a7ea5 + OpcodeWalletTransferNotification = 0x7362d09c + OpcodeWalletInternalTransfer = 0x178d4519 + OpcodeWalletExcesses = 0xd53276db + OpcodeWalletBurn = 0x595f07bc +) + +const ( + BalanceError tvm.ExitCode = tvm.ExitCode(47) + NotEnoughGas tvm.ExitCode = tvm.ExitCode(48) + InvalidMessage tvm.ExitCode = tvm.ExitCode(49) +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + AskToTransfer: codec.TLBCodec[AskToTransfer](), + InternalTransfer: codec.TLBCodec[InternalTransferMessage](), + }, + Out: outMessageBuilder{ + TransferNotification: codec.TLBCodec[TransferNotification](), + }, + }, +} + +type inMessageBuilder struct { + AskToTransfer codec.CellCodec[AskToTransfer] + InternalTransfer codec.CellCodec[InternalTransferMessage] +} + +type outMessageBuilder struct { + TransferNotification codec.CellCodec[TransferNotification] +} + +type messageBuilder struct { + In inMessageBuilder + Out outMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + +type AskToTransfer struct { + _ tlb.Magic `tlb:"#0f8a7ea5"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + Destination *address.Address `tlb:"addr"` + ResponseDestination *address.Address `tlb:"addr"` + CustomPayload *cell.Cell `tlb:"either . ^"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type InternalTransferMessage struct { + _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + From *address.Address `tlb:"addr"` + ResponseAddress *address.Address `tlb:"addr"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type TransferNotification struct { + _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"^"` + Sender *address.Address `tlb:"addr"` + ForwardPayload *cell.Cell `tlb:"maybe ^"` +} diff --git a/pkg/bindings/jetton/wallet.go b/pkg/bindings/jetton/wallet/wallet.go similarity index 56% rename from pkg/bindings/jetton/wallet.go rename to pkg/bindings/jetton/wallet/wallet.go index e35d5a8fa..a614afdeb 100644 --- a/pkg/bindings/jetton/wallet.go +++ b/pkg/bindings/jetton/wallet/wallet.go @@ -1,4 +1,4 @@ -package jetton +package wallet import ( "fmt" @@ -8,39 +8,30 @@ import ( "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) -// JettonWallet opcodes -const ( - OpcodeWalletTransfer = 0x0f8a7ea5 - OpcodeWalletTransferNotification = 0x7362d09c - OpcodeWalletInternalTransfer = 0x178d4519 - OpcodeWalletExcesses = 0xd53276db - OpcodeWalletBurn = 0x595f07bc - OpcodeWalletBurnNotification = 0x7bdd97de -) - -var WalletContractPath = path.Join(PathToContracts, "JettonWallet.compiled.json") +var WalletContractPath = path.Join(jetton.PathToContracts, "JettonWallet.compiled.json") -type WalletProvider struct { +type Provider struct { MinterAddress *address.Address } -func NewWalletProvider(minterAddress *address.Address) *WalletProvider { - return &WalletProvider{ +func NewWalletProvider(minterAddress *address.Address) *Provider { + return &Provider{ MinterAddress: minterAddress, } } -type WalletInitData struct { +type InitData struct { Status uint8 `tlb:"## 4"` Balance tlb.Coins `tlb:"."` OwnerAddress *address.Address `tlb:"addr"` MasterAddress *address.Address `tlb:"addr"` } -func WalletCode() (*cell.Cell, error) { +func Code() (*cell.Cell, error) { compiledContract, err := wrappers.ParseCompiledContract(WalletContractPath) if err != nil { return nil, fmt.Errorf("failed to compile contract: %w", err) @@ -48,8 +39,8 @@ func WalletCode() (*cell.Cell, error) { return compiledContract, nil } -func (p *WalletProvider) GetWalletInitCell(ownerAddress *address.Address) (*cell.Cell, error) { - initData := WalletInitData{ +func (p *Provider) GetWalletInitCell(ownerAddress *address.Address) (*cell.Cell, error) { + initData := InitData{ Status: 0, Balance: tlb.ZeroCoins, OwnerAddress: ownerAddress, diff --git a/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go new file mode 100644 index 000000000..224ab21ea --- /dev/null +++ b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go @@ -0,0 +1,82 @@ +package ccipsendexecutor + +import ( + "math/big" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" +) + +// CCIPSendExecutor_Execute message structure +type Execute struct { + _ tlb.Magic `tlb:"#AF3C62B3"` //nolint:revive // Ignore opcode tag + OnRampSend onramp.Send `tlb:"."` + Config *cell.Cell `tlb:"^"` + OnRampJettonWallet *address.Address `tlb:"maybe addr"` +} + +// Metadata structure +type Metadata struct { + Sender *address.Address `tlb:"addr"` +} + +// CCIPSendExecutor_Config structure +type Config struct { + FeeQuoter *address.Address `tlb:"addr"` + TokenRegistry *address.Address `tlb:"maybe addr"` +} + +// Initial data structure for CCIPSend Executor +type InitialData struct { + OnRamp *address.Address `tlb:"addr"` + MessageID *big.Int `tlb:"## 224"` +} + +// Addresses structure +type Addresses struct { + OnRamp *address.Address `tlb:"addr"` + FeeQuoter *address.Address `tlb:"addr"` +} + +// State structures +type StateInitialized struct { + TokenRegistry *address.Address `tlb:"maybe addr"` +} + +type StateWaitingForJettons struct { + TokenRegistry *address.Address `tlb:"addr"` +} + +type StateOnGoingFeeValidation struct { + PendingJettonLock *PendingJettonLock `tlb:"maybe ."` +} + +type PendingJettonLock struct { + TokenRegistry *address.Address `tlb:"addr"` + JettonWallet *address.Address `tlb:"addr"` + TokenPool *address.Address `tlb:"addr"` +} + +// OnRamp message types that the executor sends back +type OnRampWithdrawJettons struct { + MsgID *big.Int `tlb:"## 224"` + Tokens common.SnakeRef[TokenAmount] `tlb:"^"` + OnRampJettonWallet *address.Address `tlb:"addr"` +} + +type OnRampExecutorFinishedSuccessfully struct { + MsgID *big.Int `tlb:"## 224"` + Msg *cell.Cell `tlb:"^"` + Metadata Metadata `tlb:"."` + Fee tlb.Coins `tlb:"."` +} + +// TokenAmount structure (reused from router package concept) +type TokenAmount struct { + Amount *big.Int `tlb:"## 256"` + Token *address.Address `tlb:"addr"` +} diff --git a/pkg/ccip/bindings/ccipsendexecutor/codec.go b/pkg/ccip/bindings/ccipsendexecutor/codec.go new file mode 100644 index 000000000..fe0c92468 --- /dev/null +++ b/pkg/ccip/bindings/ccipsendexecutor/codec.go @@ -0,0 +1,37 @@ +package ccipsendexecutor + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// CCIPSend Executor opcodes +const ( + OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') +) + +// CCIPSend Executor exit codes +const ( + ErrorStateNotExpected tvm.ExitCode = tvm.ExitCode(500) + ErrorUnauthorized tvm.ExitCode = tvm.ExitCode(265) // ERROR_UNAUTHORIZED from contract +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + Execute: codec.TLBCodec[Execute](), + }, + }, +} + +type inMessageBuilder struct { + Execute codec.CellCodec[Execute] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/feequoter/codec.go b/pkg/ccip/bindings/feequoter/codec.go new file mode 100644 index 000000000..922013d06 --- /dev/null +++ b/pkg/ccip/bindings/feequoter/codec.go @@ -0,0 +1,41 @@ +package feequoter + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + UpdatePrices: codec.TLBCodec[UpdatePrices](), + UpdateFeeTokens: codec.TLBCodec[UpdateFeeTokens](), + UpdateTokenTransferFeeConfigs: codec.TLBCodec[UpdateTokenTransferFeeConfigs](), + UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigs](), + GetValidatedFee: codec.TLBCodec[GetValidatedFee](), + }, + Out: outMessageBuilder{ + MessageValidated: codec.TLBCodec[MessageValidated](), + }, + }, +} + +type inMessageBuilder struct { + UpdatePrices codec.CellCodec[UpdatePrices] + UpdateFeeTokens codec.CellCodec[UpdateFeeTokens] + UpdateTokenTransferFeeConfigs codec.CellCodec[UpdateTokenTransferFeeConfigs] + UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigs] + GetValidatedFee codec.CellCodec[GetValidatedFee] +} + +type outMessageBuilder struct { + MessageValidated codec.CellCodec[MessageValidated] +} + +type messageBuilder struct { + In inMessageBuilder + Out outMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/feequoter/fee_quoter.go b/pkg/ccip/bindings/feequoter/fee_quoter.go index 7000343cc..0f8745cbc 100644 --- a/pkg/ccip/bindings/feequoter/fee_quoter.go +++ b/pkg/ccip/bindings/feequoter/fee_quoter.go @@ -9,6 +9,30 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// Fee Quoter opcodes +const ( + OpcodeUpdatePrices = 0x20000001 + OpcodeUpdateFeeTokens = 0xD0984986 + OpcodeUpdateTokenTransferFeeConfigs = 0xB2826316 + OpcodeUpdateDestChainConfigs = 0x29950BAA + OpcodeFeeQuoterGetValidatedFee = 0x7496FF56 + OpcodeFeeQuoterMessageValidated = 0x1FA60374 +) + +// Fee Quoter exit codes +const ( + ErrorUnsupportedChainFamilySelector tvm.ExitCode = tvm.ExitCode(1001) + ErrorGasLimitTooHigh tvm.ExitCode = tvm.ExitCode(1002) + ExtraArgOutOfOrderExecutionMustBeTrue tvm.ExitCode = tvm.ExitCode(1003) + ErrorInvalidExtraArgsData tvm.ExitCode = tvm.ExitCode(1004) + ErrorUnsupportedNumberOfTokens tvm.ExitCode = tvm.ExitCode(1005) + ErrorInvalidSuiReceiverAddress tvm.ExitCode = tvm.ExitCode(1006) + ErrorInvalidTokenReceiver tvm.ExitCode = tvm.ExitCode(1007) + ErrorTooManySuiExtraArgsReceiverObjectIDs tvm.ExitCode = tvm.ExitCode(1008) + ErrorMsgDataTooLarge tvm.ExitCode = tvm.ExitCode(1009) ) type Storage struct { @@ -234,6 +258,20 @@ func (c *StaticConfig) FromResult(result *ton.ExecutionResult) error { // Methods +// Generic wrapper for fee quoter messages with metadata +type GetValidatedFee struct { + _ tlb.Magic `tlb:"#7496FF56"` //nolint:revive // Ignore opcode tag + Msg *cell.Cell `tlb:"^"` // Cell containing the CCIPSend message + Metadata *cell.Cell `tlb:"^"` // Cell containing metadata +} + +type MessageValidated struct { + _ tlb.Magic `tlb:"#1FA60374"` //nolint:revive // Ignore opcode tag + Msg *cell.Cell `tlb:"^"` // TODO put content here + Metadata *cell.Cell `tlb:"^"` + Fee *tlb.Coins `tlb:"."` +} + type UpdatePrices struct { _ tlb.Magic `tlb:"#20000001"` //nolint:revive // Ignore opcode tag TokenPrices common.SnakeData[TokenPriceUpdate] `tlb:"^"` diff --git a/pkg/ccip/bindings/onramp/codec.go b/pkg/ccip/bindings/onramp/codec.go new file mode 100644 index 000000000..c5b463091 --- /dev/null +++ b/pkg/ccip/bindings/onramp/codec.go @@ -0,0 +1,35 @@ +package onramp + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + OnRampSend: codec.TLBCodec[Send](), + WithdrawJettons: codec.TLBCodec[WithdrawJettons](), + ExecutorFinishedSuccessfully: codec.TLBCodec[ExecutorFinishedSuccessfully](), + SetDynamicConfig: codec.TLBCodec[SetDynamicConfigMessage](), + UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigsMessage](), + UpdateAllowlists: codec.TLBCodec[UpdateAllowlistsMessage](), + }, + }, +} + +type inMessageBuilder struct { + OnRampSend codec.CellCodec[Send] + WithdrawJettons codec.CellCodec[WithdrawJettons] + ExecutorFinishedSuccessfully codec.CellCodec[ExecutorFinishedSuccessfully] + SetDynamicConfig codec.CellCodec[SetDynamicConfigMessage] + UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigsMessage] + UpdateAllowlists codec.CellCodec[UpdateAllowlistsMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/onramp/onramp.go b/pkg/ccip/bindings/onramp/onramp.go index cf9684f45..03dc34dc7 100644 --- a/pkg/ccip/bindings/onramp/onramp.go +++ b/pkg/ccip/bindings/onramp/onramp.go @@ -12,6 +12,16 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/ocr" ) +// OnRamp opcodes +const ( + OpcodeOnRampSend = 0x40000001 + OpcodeOnRampWithdrawJettons = 0x40000002 + OpcodeOnRampExecutorFinishedSuccessfully = 0x40000003 + OpcodeSetDynamicConfig = 0x10000003 + OpcodeUpdateDestChainConfigs = 0x10000004 + OpcodeUpdateAllowlists = 0x10000005 +) + // CCIPMessageSent uses TVM2AnyRampMessage but with event-specific header (no onramp address) type CCIPMessageSent struct { Message ocr.TVM2AnyRampMessage `tlb:"."` @@ -151,3 +161,44 @@ type UpdateAllowlists struct { } type WithdrawFeeTokens struct{} + +// Message structures that map to the existing types in onramp.go +type Send struct { + _ tlb.Magic `tlb:"#10000002"` //nolint:revive // Ignore opcode tag + Msg *cell.Cell `tlb:"^"` // Cell containing the CCIPSend message + Metadata Metadata `tlb:"."` // Cell containing metadata +} + +type Metadata struct { + Sender *address.Address `tlb:"addr"` +} + +type WithdrawJettons struct { + _ tlb.Magic `tlb:"#266AEACF"` //nolint:revive // Ignore opcode tag + MsgId big.Int `tlb:"## 224"` // Message ID + Tokens *cell.Cell `tlb:"^"` // Token amounts + OnrampJettonWallet *address.Address `tlb:"addr"` // Onramp jetton wallet address +} + +type ExecutorFinishedSuccessfully struct { + _ tlb.Magic `tlb:"#CFA6B336"` //nolint:revive // Ignore opcode tag + MsgId big.Int `tlb:"## 224"` // Message ID + Msg *cell.Cell `tlb:"^"` // Original CCIPSend message + Metadata Metadata `tlb:"."` // Metadata + Fee *tlb.Coins `tlb:"."` // Fee amount +} + +type SetDynamicConfigMessage struct { + _ tlb.Magic `tlb:"#10000003"` //nolint:revive // Ignore opcode tag + Config DynamicConfig `tlb:"."` +} + +type UpdateDestChainConfigsMessage struct { + _ tlb.Magic `tlb:"#10000004"` //nolint:revive // Ignore opcode tag + Updates *cell.Cell `tlb:"^"` // Snake-encoded updates +} + +type UpdateAllowlistsMessage struct { + _ tlb.Magic `tlb:"#10000005"` //nolint:revive // Ignore opcode tag + Updates *cell.Cell `tlb:"^"` // Snake-encoded updates +} diff --git a/pkg/ccip/bindings/router/codec.go b/pkg/ccip/bindings/router/codec.go new file mode 100644 index 000000000..cab33f868 --- /dev/null +++ b/pkg/ccip/bindings/router/codec.go @@ -0,0 +1,40 @@ +package router + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// Router opcodes +const ( + OpcodeSetRamps = 0x10000001 + OpcodeCCIPSend = 0x00000001 +) + +// Router exit codes +const ( + ErrorDestChainNotEnabled tvm.ExitCode = tvm.ExitCode(0x1001) + ErrorUnknownMessage tvm.ExitCode = tvm.ExitCode(0x1002) +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + SetRamps: codec.TLBCodec[SetRamps](), + CCIPSend: codec.TLBCodec[CCIPSend](), + }, + }, +} + +type inMessageBuilder struct { + SetRamps codec.CellCodec[SetRamps] + CCIPSend codec.CellCodec[CCIPSend] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/router/router.go b/pkg/ccip/bindings/router/router.go index eb32eeb76..fc887792a 100644 --- a/pkg/ccip/bindings/router/router.go +++ b/pkg/ccip/bindings/router/router.go @@ -44,11 +44,3 @@ type CCIPSend struct { FeeToken *address.Address `tlb:"addr"` ExtraArgs *cell.Cell `tlb:"^"` } - -type JettonTransferNotification struct { - _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"^"` - Sender *address.Address `tlb:"addr"` - ForwardPayload *cell.Cell `tlb:"maybe ^"` -} diff --git a/pkg/ton/codec/builder.go b/pkg/ton/codec/builder.go new file mode 100644 index 000000000..8d582b43b --- /dev/null +++ b/pkg/ton/codec/builder.go @@ -0,0 +1,28 @@ +package codec + +import ( + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +type CellCodec[T any] interface { + Encode(data T) (*cell.Builder, error) + Decode(src *cell.Slice) (T, error) +} + +func TLBCodec[T any]() CellCodec[T] { + return &tlbCodec[T]{} +} + +type tlbCodec[T any] struct{} + +func (c *tlbCodec[T]) Encode(data T) (*cell.Builder, error) { + cell, err := tlb.ToCell(data) + return cell.ToBuilder(), err +} + +func (c *tlbCodec[T]) Decode(src *cell.Slice) (T, error) { + var data T + err := tlb.LoadFromCell(&data, src) + return data, err +} diff --git a/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go new file mode 100644 index 000000000..85be1c7c3 --- /dev/null +++ b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go @@ -0,0 +1,70 @@ +package ccipsendexecutor + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/ccipsendexecutor" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + payloadDecoders map[cldf.ContractType]lib.ContractDecoder +} + +func NewDecoder(payloadDecoders map[cldf.ContractType]lib.ContractDecoder) lib.ContractDecoder { + return &decoder{payloadDecoders} +} + +// ContractType implements lib.ContractDecoder. +func (d *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.chainlink.ton.ccip.CCIPSendExecutor") +} + +// EventInfo implements lib.ContractDecoder. +func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + if opCode == ccipsendexecutor.OpcodeCCIPSendExecutorExecute { + execute, err := ccipsendexecutor.Builder.Messages.In.Execute.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("CCIPSendExecutorExecute", execute) + } + + // Note: We don't handle JettonTransferNotification or FeeQuoter_MessageValidated here + // because they are already handled by their respective decoders (jetton wallet and fee quoter) + return nil, &lib.UnknownMessageError{} +} + +func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case ccipsendexecutor.ErrorStateNotExpected: + return "ErrorStateNotExpected", nil + case ccipsendexecutor.ErrorUnauthorized: + return "ErrorUnauthorized", nil + default: + return "", &lib.UnknownMessageError{} + } +} diff --git a/pkg/ton/debug/decoders/ccip/common/common.go b/pkg/ton/debug/decoders/ccip/common/common.go new file mode 100644 index 000000000..61d626f7b --- /dev/null +++ b/pkg/ton/debug/decoders/ccip/common/common.go @@ -0,0 +1,66 @@ +package common + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { +} + +// EventInfo implements lib.ContractDecoder. +func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + panic("unimplemented") +} + +// ExitCodeInfo implements lib.ContractDecoder. +func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case common.ErrUnknownDestChainSelector: + return "ErrUnknownDestChainSelector", nil + case common.DestChainNotEnabled: + return "DestChainNotEnabled", nil + case common.FeeTokenNotSupported: + return "FeeTokenNotSupported", nil + case common.StaleGasPrice: + return "StaleGasPrice", nil + case common.InvalidMsgData: + return "InvalidMsgData", nil + case common.SenderNotAllowed: + return "SenderNotAllowed", nil + case common.InvalidMessageDestChainSelector: + return "InvalidMessageDestChainSelector", nil + case common.SourceChainSelectorMismatch: + return "SourceChainSelectorMismatch", nil + case common.TokenNotSupported: + return "TokenNotSupported", nil + case common.Unauthorized: + return "Unauthorized", nil + case common.SourceChainNotEnabled: + return "SourceChainNotEnabled", nil + case common.EmptyReport: + return "EmptyReport", nil + case common.DispatchNotFromMerkleRoot: + return "DispatchNotFromMerkleRoot", nil + default: + return "", &lib.UnknownMessageError{} + } +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) ExternalMessageInfo(body *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) InternalMessageInfo(body *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +func NewDecoder() *decoder { + return &decoder{} +} diff --git a/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go new file mode 100644 index 000000000..7b2560d1d --- /dev/null +++ b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go @@ -0,0 +1,111 @@ +package feequoter + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/feequoter" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { +} + +func NewDecoder() lib.ContractDecoder { + return &decoder{} +} + +// ContractType implements lib.ContractDecoder. +func (d *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.chainlink.ton.ccip.FeeQuoter") +} + +// EventInfo implements lib.ContractDecoder. +func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + switch opCode { + case feequoter.OpcodeUpdatePrices: + updatePrices, err := feequoter.Builder.Messages.In.UpdatePrices.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdatePrices", updatePrices) + case feequoter.OpcodeUpdateFeeTokens: + updateFeeTokens, err := feequoter.Builder.Messages.In.UpdateFeeTokens.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdateFeeTokens", updateFeeTokens) + case feequoter.OpcodeUpdateTokenTransferFeeConfigs: + updateConfigs, err := feequoter.Builder.Messages.In.UpdateTokenTransferFeeConfigs.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdateTokenTransferFeeConfigs", updateConfigs) + case feequoter.OpcodeUpdateDestChainConfigs: + updateDestConfigs, err := feequoter.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestConfigs) + case feequoter.OpcodeFeeQuoterGetValidatedFee: + getValidatedFee, err := feequoter.Builder.Messages.In.GetValidatedFee.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("GetValidatedFee", getValidatedFee) + case feequoter.OpcodeFeeQuoterMessageValidated: + messageValidated, err := feequoter.Builder.Messages.Out.MessageValidated.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("MessageValidated", messageValidated) + } + return nil, &lib.UnknownMessageError{} +} + +func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case feequoter.ErrorUnsupportedChainFamilySelector: + return "ErrorUnsupportedChainFamilySelector", nil + case feequoter.ErrorGasLimitTooHigh: + return "ErrorGasLimitTooHigh", nil + case feequoter.ExtraArgOutOfOrderExecutionMustBeTrue: + return "ExtraArgOutOfOrderExecutionMustBeTrue", nil + case feequoter.ErrorInvalidExtraArgsData: + return "ErrorInvalidExtraArgsData", nil + case feequoter.ErrorUnsupportedNumberOfTokens: + return "ErrorUnsupportedNumberOfTokens", nil + case feequoter.ErrorInvalidSuiReceiverAddress: + return "ErrorInvalidSuiReceiverAddress", nil + case feequoter.ErrorInvalidTokenReceiver: + return "ErrorInvalidTokenReceiver", nil + case feequoter.ErrorTooManySuiExtraArgsReceiverObjectIDs: + return "ErrorTooManySuiExtraArgsReceiverObjectIds", nil + case feequoter.ErrorMsgDataTooLarge: + return "ErrorMsgDataTooLarge", nil + default: + return "", &lib.UnknownMessageError{} + } +} diff --git a/pkg/ton/debug/decoders/ccip/onramp/onramp.go b/pkg/ton/debug/decoders/ccip/onramp/onramp.go new file mode 100644 index 000000000..cafe0a776 --- /dev/null +++ b/pkg/ton/debug/decoders/ccip/onramp/onramp.go @@ -0,0 +1,92 @@ +package onramp + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + payloadDecoders map[cldf.ContractType]lib.ContractDecoder +} + +func NewDecoder(payloadDecoders map[cldf.ContractType]lib.ContractDecoder) lib.ContractDecoder { + return &decoder{payloadDecoders} +} + +// ContractType implements lib.ContractDecoder. +func (d *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.chainlink.ton.ccip.OnRamp") +} + +// EventInfo implements lib.ContractDecoder. +func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + switch opCode { + case onramp.OpcodeOnRampSend: + onRampSend, err := onramp.Builder.Messages.In.OnRampSend.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("OnRampSend", onRampSend) + case onramp.OpcodeOnRampWithdrawJettons: + withdrawJettons, err := onramp.Builder.Messages.In.WithdrawJettons.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("WithdrawJettons", withdrawJettons) + case onramp.OpcodeOnRampExecutorFinishedSuccessfully: + executorFinished, err := onramp.Builder.Messages.In.ExecutorFinishedSuccessfully.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("ExecutorFinishedSuccessfully", executorFinished) + case onramp.OpcodeSetDynamicConfig: + setDynamicConfig, err := onramp.Builder.Messages.In.SetDynamicConfig.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("SetDynamicConfig", setDynamicConfig) + case onramp.OpcodeUpdateDestChainConfigs: + updateDestChainConfigs, err := onramp.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestChainConfigs) + case onramp.OpcodeUpdateAllowlists: + updateAllowlists, err := onramp.Builder.Messages.In.UpdateAllowlists.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("UpdateAllowlists", updateAllowlists) + } + return nil, &lib.UnknownMessageError{} +} + +func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + return common.NewDecoder().ExitCodeInfo(exitCode) +} diff --git a/pkg/ton/debug/decoders/ccip/router/router.go b/pkg/ton/debug/decoders/ccip/router/router.go new file mode 100644 index 000000000..281bc8338 --- /dev/null +++ b/pkg/ton/debug/decoders/ccip/router/router.go @@ -0,0 +1,74 @@ +package router + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/router" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + payloadDecoders map[cldf.ContractType]lib.ContractDecoder +} + +func NewDecoder(payloadDecoders map[cldf.ContractType]lib.ContractDecoder) lib.ContractDecoder { + return &decoder{payloadDecoders} +} + +// ContractType implements lib.ContractDecoder. +func (d *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.chainlink.ton.ccip.Router") +} + +// EventInfo implements lib.ContractDecoder. +func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + switch opCode { + case router.OpcodeSetRamps: + setRamps, err := router.Builder.Messages.In.SetRamps.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("SetRamps", setRamps) + case router.OpcodeCCIPSend: + ccipSend, err := router.Builder.Messages.In.CCIPSend.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("CCIPSend", ccipSend) + } + return nil, &lib.UnknownMessageError{} +} + +func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case router.ErrorDestChainNotEnabled: + return "ErrorDestChainNotEnabled", nil + case router.ErrorUnknownMessage: + return "ErrorUnknownMessage", nil + default: + return "", &lib.UnknownMessageError{} + } +} diff --git a/pkg/ton/debug/decoders/jetton/common.go b/pkg/ton/debug/decoders/jetton/common.go new file mode 100644 index 000000000..f68d5c787 --- /dev/null +++ b/pkg/ton/debug/decoders/jetton/common.go @@ -0,0 +1,54 @@ +package jetton + +import ( + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { +} + +func NewDecoder() *decoder { + return &decoder{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + if opCode == jetton.OpcodeTopUp { + topUp, err := jetton.Builder.Messages.In.TopUp.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("TopUp", topUp) + } + return nil, &lib.UnknownMessageError{} +} + +func (j *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case jetton.ErrorInvalidOp: + return "ErrorInvalidOp", nil + case jetton.ErrorWrongOp: + return "ErrorWrongOp", nil + case jetton.ErrorNotOwner: + return "ErrorNotOwner", nil + case jetton.ErrorNotValidWallet: + return "ErrorNotValidWallet", nil + case jetton.ErrorWrongWorkchain: + return "ErrorWrongWorkchain", nil + default: + return "", &lib.UnknownMessageError{} + } +} diff --git a/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go new file mode 100644 index 000000000..b5242019e --- /dev/null +++ b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go @@ -0,0 +1,112 @@ +package minter + +import ( + "errors" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/minter" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/wallet" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + payloadDecoders map[cldf.ContractType]lib.ContractDecoder +} + +func NewDecoder(payloadDecoders map[cldf.ContractType]lib.ContractDecoder) lib.ContractDecoder { + return &decoder{payloadDecoders} +} + +// ContractType implements lib.ContractDecoder. +func (j *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.github.ton-blockchain.jetton-contract.contracts.jetton-minter") +} + +// EventInfo implements lib.ContractDecoder. +func (j *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (j *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + switch opCode { + case minter.OpcodeMinterMint: + mint, err := minter.Builder.Messages.In.Mint.Decode(r) + if err != nil { + return nil, err + } + if mint.MasterMsg.ForwardPayload == nil { + return lib.NewMessageInfo("Mint", mint) + } + + payloadInfo, err := j.tryDecodePayload(mint.MasterMsg.ForwardPayload) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("MintWithPayload", MintMessageDescription{ + QueryID: mint.QueryID, + Destination: mint.Destination, + TonAmount: mint.TonAmount, + MasterMsg: wallet.InternalTransferDescription(mint.MasterMsg, payloadInfo), + }) + case minter.OpcodeMinterChangeAdmin: + changeAdmin, err := minter.Builder.Messages.In.ChangeAdmin.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("ChangeAdmin", changeAdmin) + case minter.OpcodeMinterClaimAdmin: + changeContent, err := minter.Builder.Messages.In.ClaimAdmin.Decode(r) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("ClaimAdmin", changeContent) + // TODO missing messages + } + return jetton.NewDecoder().InternalMessageInfo(msg) +} + +func (j *decoder) tryDecodePayload(payloadCell *cell.Cell) (lib.MessageInfo, error) { + for _, d := range j.payloadDecoders { + info, err := d.InternalMessageInfo(payloadCell) + if err == nil { + return info, nil + } + if e := &(lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + return nil, &lib.UnknownMessageError{} +} + +type MintMessageDescription struct { + QueryID uint64 + Destination *address.Address + TonAmount tlb.Coins + MasterMsg wallet.InternalTransferMessageDescription +} + +func (j *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + return jetton.NewDecoder().ExitCodeInfo(exitCode) +} diff --git a/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go new file mode 100644 index 000000000..912728fbb --- /dev/null +++ b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go @@ -0,0 +1,145 @@ +package wallet + +import ( + "errors" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" + jetton_common "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type decoder struct { + payloadDecoders map[cldf.ContractType]lib.ContractDecoder +} + +func NewDecoder(payloadDecoders map[cldf.ContractType]lib.ContractDecoder) lib.ContractDecoder { + return &decoder{payloadDecoders} +} + +// ContractType implements lib.ContractDecoder. +func (j *decoder) ContractType() cldf.ContractType { + return cldf.ContractType("com.github.ton-blockchain.jetton-contract.contracts.jetton-wallet") +} + +// EventInfo implements lib.ContractDecoder. +func (j *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// ExternalMessageInfo implements lib.ContractDecoder. +func (j *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + return nil, &lib.UnknownMessageError{} +} + +// InternalMessageInfo implements lib.ContractDecoder. +func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { + r := msg.BeginParse() + if r.BitsLeft() == 0 { + return nil, &lib.UnknownMessageError{} + } + opCode, err := r.PreloadUInt(32) + if err != nil { + return nil, err + } + switch opCode { + case wallet.OpcodeWalletTransfer: + askToTransfer, err := wallet.Builder.Messages.In.AskToTransfer.Decode(r) + if err != nil { + return nil, err + } + if askToTransfer.CustomPayload == nil { + return lib.NewMessageInfo("AskToTransfer", askToTransfer) + } + + payloadInfo, err := j.tryDecodePayload(askToTransfer.CustomPayload) + if err == nil { + return lib.NewMessageInfo("AskToTransferWithPayload", AskToTransferMessageDescription{ + QueryID: askToTransfer.QueryID, + Amount: askToTransfer.Amount, + Destination: askToTransfer.Destination, + ResponseDestination: askToTransfer.ResponseDestination, + CustomPayload: askToTransfer.CustomPayload, + ForwardTonAmount: askToTransfer.ForwardTonAmount, + ForwardPayload: lib.Wrapper{Type: payloadInfo.Name(), Value: payloadInfo.Body()}, + }) + } + case wallet.OpcodeWalletInternalTransfer: + internalTransfer, err := wallet.Builder.Messages.In.InternalTransfer.Decode(r) + if err != nil { + return nil, err + } + if internalTransfer.ForwardPayload == nil { + return lib.NewMessageInfo("InternalTransfer", internalTransfer) + } + + payloadInfo, err := j.tryDecodePayload(internalTransfer.ForwardPayload) + if err == nil { + return lib.NewMessageInfo("InternalTransferWithPayload", InternalTransferDescription(internalTransfer, payloadInfo)) + } + } + return jetton_common.NewDecoder().InternalMessageInfo(msg) +} + +func InternalTransferDescription(internalTransfer wallet.InternalTransferMessage, payloadInfo lib.MessageInfo) InternalTransferMessageDescription { + return InternalTransferMessageDescription{ + QueryID: internalTransfer.QueryID, + Amount: internalTransfer.Amount, + From: internalTransfer.From, + ResponseAddress: internalTransfer.ResponseAddress, + ForwardTonAmount: internalTransfer.ForwardTonAmount, + ForwardPayload: lib.Wrapper{Type: payloadInfo.Name(), Value: payloadInfo.Body()}, + } +} + +func (j *decoder) tryDecodePayload(payloadCell *cell.Cell) (lib.MessageInfo, error) { + for _, d := range j.payloadDecoders { + info, err := d.InternalMessageInfo(payloadCell) + if err == nil { + return info, nil + } + if e := &(lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + return nil, &lib.UnknownMessageError{} +} + +type AskToTransferMessageDescription struct { + QueryID uint64 + Amount tlb.Coins + Destination *address.Address + ResponseDestination *address.Address + CustomPayload *cell.Cell + ForwardTonAmount tlb.Coins + ForwardPayload any +} + +type InternalTransferMessageDescription struct { + QueryID uint64 + Amount tlb.Coins + From *address.Address + ResponseAddress *address.Address + ForwardTonAmount tlb.Coins + ForwardPayload any +} + +func (j *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { + switch exitCode { + case wallet.BalanceError: + return "BalanceError", nil + case wallet.NotEnoughGas: + return "NotEnoughGas", nil + case wallet.InvalidMessage: + return "InvalidMessage", nil + default: + return jetton_common.NewDecoder().ExitCodeInfo(exitCode) + } +} diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go new file mode 100644 index 000000000..cd315b41c --- /dev/null +++ b/pkg/ton/debug/explorer/explorer.go @@ -0,0 +1,134 @@ +package explorer + +import ( + "context" + "encoding/hex" + "fmt" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" +) + +// PrintTrace connects to the specified TON network, retrieves the transaction +// by the given source address and transaction hash, and prints the full execution +// trace of the transaction, including all outgoing messages and their subsequent +// messages. +// +// Parameters: +// - ctx: The context for managing request deadlines and cancellation. +// - net: The TON network to connect to (e.g., "mainnet", "testnet", "mylocalton", "http://127.0.0.1:8000/localhost.global.config.json""). +// - srcAddresstr: The source address of the transaction in string format. +func PrintTrace(ctx context.Context, net string, srcAddresstr string, txHashStr string, verbose bool) error { + client, err := connect(ctx, net) + if err != nil { + return err + } + + return PrintTraceWithClient(ctx, client, srcAddresstr, txHashStr, verbose) +} + +func PrintTraceWithClient(ctx context.Context, client *ton.APIClient, srcAddresstr string, txHashStr string, verbose bool) error { + senderAddr, err := address.ParseAddr(srcAddresstr) + if err != nil { + return fmt.Errorf("failed to parse transaction address: %w", err) + } + txHash, err := hex.DecodeString(txHashStr) + if err != nil { + return fmt.Errorf("failed to decode tx hash: %w", err) + } + + tx, err := findTx(ctx, client, senderAddr, txHash) + if err != nil { + return err + } + + fmt.Println("tx found in lt:", tx.LT) + + recvMsg, err := tracetracking.MapToReceivedMessage(tx) + if err != nil { + return fmt.Errorf("failed to map transaction to received message: %w", err) + } + + fmt.Println("waiting for full trace...") + + err = recvMsg.WaitForTrace(client) + if err != nil { + return fmt.Errorf("failed to wait for trace: %w", err) + } + + fmt.Println("full trace received:") + + debugger := debug.NewDebuggerTreeTrace(map[string]deployment.TypeAndVersion{}) + fmt.Println(debugger.DumpReceived(&recvMsg, verbose)) + + return nil +} + +func findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { + block, err := api.GetMasterchainInfo(ctx) + if err != nil { + return nil, fmt.Errorf("get masterchain info: %w", err) + } + account, err := api.GetAccount(ctx, block, srcAddr) + if err != nil { + return nil, fmt.Errorf("get account: %w", err) + } + + const pageSize uint32 = 10 + + // Start from the latest transaction + maxLT := account.LastTxLT + maxHash := account.LastTxHash + for range uint64(20) { + txs, err := api.ListTransactions(ctx, srcAddr, pageSize, maxLT, maxHash) + if err != nil { + return nil, fmt.Errorf("get transaction: %w", err) + } + for _, tx := range txs { + if equalHash(tx.Hash, txHash) { + return tx, nil + } + } + // Move to the previous page + last := txs[len(txs)-1] + maxLT = last.PrevTxLT + maxHash = last.PrevTxHash + } + return nil, fmt.Errorf("transaction not found") +} + +func equalHash(a, b []byte) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +func connect(ctx context.Context, net string) (*ton.APIClient, error) { + configURL := net + switch net { + case "mainnet": + configURL = "https://ton-blockchain.github.io/global.config.json" + case "testnet": + configURL = "https://ton.org/testnet-global.config.json" + case "mylocalton": + configURL = "http://127.0.0.1:8000/localhost.global.config.json" + } + pool := liteclient.NewConnectionPool() + err := pool.AddConnectionsFromConfigUrl(ctx, configURL) + if err != nil { + return nil, fmt.Errorf("failed to add connections from config url: %w", err) + } + return ton.NewAPIClient(pool, ton.ProofCheckPolicyFast), nil +} diff --git a/pkg/ton/debug/lib/lib.go b/pkg/ton/debug/lib/lib.go new file mode 100644 index 000000000..a61265c1e --- /dev/null +++ b/pkg/ton/debug/lib/lib.go @@ -0,0 +1,101 @@ +package lib + +import ( + "encoding/json" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type TxInfo struct { + Msg MessageInfo + ExitCode string +} + +type MessageInfo interface { + Name() string + Body() BodyInfo +} + +type BodyInfo interface { + Compact() string + Describe() string +} + +type UnknownMessageError struct{} + +func (e *UnknownMessageError) Error() string { + return "unknown message" +} + +type ContractDecoder interface { + ContractType() cldf.ContractType + InternalMessageInfo(body *cell.Cell) (MessageInfo, error) + ExternalMessageInfo(body *cell.Cell) (MessageInfo, error) + EventInfo(dstAddr *address.Address, msg *cell.Cell) (MessageInfo, error) + ExitCodeInfo(exitCode tvm.ExitCode) (string, error) +} + +func NewMessageInfo[T any](name string, msg T) (MessageInfo, error) { + short, err := json.Marshal(msg) + if err != nil { + return nil, err + } + long, err := json.MarshalIndent(msg, "", " ") + if err != nil { + return nil, err + } + return messageInfo{ + name: name, + short: string(short), + long: string(long), + }, nil +} + +type messageInfo struct { + name string + short string + long string +} + +// Body implements lib.MessageInfo. +func (m messageInfo) Body() BodyInfo { + return m +} + +// Name implements lib.MessageInfo. +func (m messageInfo) Name() string { + return m.name +} + +func (m messageInfo) Compact() string { + return m.short +} + +func (m messageInfo) Describe() string { + return m.long +} + +type Wrapper struct { + Type string + Value any +} + +func (w Wrapper) MarshalJSON() ([]byte, error) { + // Marshal the Value first + valueJSON, err := json.Marshal(w.Value) + if err != nil { + return nil, err + } + + // Build an object like: {"": } + // Note: json.Marshal needs a map[string]json.RawMessage + obj := map[string]json.RawMessage{ + w.Type: valueJSON, + } + return json.Marshal(obj) +} diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go new file mode 100644 index 000000000..e824e74eb --- /dev/null +++ b/pkg/ton/debug/pretty_print.go @@ -0,0 +1,345 @@ +package debug + +import ( + "encoding/hex" + "errors" + "fmt" + + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/ccipsendexecutor" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/feequoter" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/onramp" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/router" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/minter" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/wallet" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/event" + tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +type DebuggerWriter interface { + AddActor(address string, contractType cldf.ContractType, name string) + NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) DebuggerWriter + NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) DebuggerWriter + NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) + String() string +} + +type DebuggerEnvironment struct { + existingAddresses map[string]cldf.TypeAndVersion + contracts map[cldf.ContractType]lib.ContractDecoder + writerFactory func(DebuggerEnvironment) DebuggerWriter +} + +// func NewDebuggerFromEnv(env cldf.Environment, writer DebuggerWriter) Debugger { +// return Debugger{ +// ExistingAddresses: env.GetAddressBook(), +// Contracts: make(map[*cldf.ContractType]lib.ContractDecoder), +// Writer: writer, +// } +// } + +func NewDebuggerTreeTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvironment { + return DebuggerEnvironment{ + existingAddresses: addresses, + contracts: defaultDecoders(), + writerFactory: func(d DebuggerEnvironment) DebuggerWriter { + writer := &TreeDiagram{ + Actors: make(map[string]string), + } + for addr, typeAndVersion := range d.existingAddresses { + writer.AddActor(addr, typeAndVersion.Type, "") + } + return writer + }, + } +} + +func defaultDecoders() map[cldf.ContractType]lib.ContractDecoder { + t := make(map[cldf.ContractType]lib.ContractDecoder) + registerDecoder(t, wallet.NewDecoder(t)) + registerDecoder(t, minter.NewDecoder(t)) + registerDecoder(t, router.NewDecoder(t)) + registerDecoder(t, onramp.NewDecoder(t)) + registerDecoder(t, feequoter.NewDecoder()) + registerDecoder(t, ccipsendexecutor.NewDecoder(t)) + return t +} + +func registerDecoder(t map[cldf.ContractType]lib.ContractDecoder, decoder lib.ContractDecoder) { + t[decoder.ContractType()] = decoder +} + +func (d *DebuggerEnvironment) RegisterDecoders(decoders ...lib.ContractDecoder) { + for _, v := range decoders { + d.contracts[v.ContractType()] = v + } +} + +func (d DebuggerEnvironment) NewInstance() debugger { + return debugger{ + environment: d, + Writer: d.writerFactory(d), + } +} + +type debugger struct { + environment DebuggerEnvironment + Writer DebuggerWriter +} + +func (d DebuggerEnvironment) DumpSent(m *tt.SentMessage, verbose ...bool) string { + instance := d.NewInstance() + var verboseFlag bool + if len(verbose) == 1 { + verboseFlag = verbose[0] + } + return instance.dumpSent(m, verboseFlag) +} + +func (d debugger) dumpSent(m *tt.SentMessage, verbose bool) string { + info, err := d.environment.describeSentMessage(m, verbose) + if err != nil { + return fmt.Sprintf("error describing sent message: %v", err) + } + _ = d.Writer.NewSentMessage(m, info) + return d.Writer.String() +} + +// Outputs a nicely indented string representation of the trace tree, with the exit codes, bounced tags and sender-receiver +func (d DebuggerEnvironment) DumpReceived(m *tt.ReceivedMessage, verbose ...bool) string { + instance := d.NewInstance() + var verboseFlag bool + if len(verbose) == 1 { + verboseFlag = verbose[0] + } + val, err := instance.dumpReceived(m, verboseFlag) + if err != nil { + return fmt.Sprintf("error dumping received message: %v", err) + } + return val +} + +func (d debugger) dumpReceived(m *tt.ReceivedMessage, verbose bool) (string, error) { + err := d.dumpRec(m, verbose) + if err != nil { + return "", fmt.Errorf("error dumping received message: %w", err) + } + return d.Writer.String(), nil +} + +func (d debugger) dumpRec(m *tt.ReceivedMessage, verbose bool) error { + var subcontext DebuggerWriter + info, err := d.environment.describeReceivedMessage(m, verbose) + if err != nil { + return fmt.Errorf("error describing received message: %w", err) + } + subcontext = d.Writer.NewReceivedMessage(m, *info) // TODO rm reference + subD := d.withSubcontext(subcontext) + for _, received := range m.OutgoingInternalReceivedMessages { + err = subD.dumpRec(received, verbose) + if err != nil { + return fmt.Errorf("error describing received message: %w", err) + } + } + for _, sentMessage := range m.OutgoingInternalSentMessages { + msgInfo, err := subD.environment.describeSentMessage(sentMessage, verbose) + if err != nil { + return fmt.Errorf("error describing sent message: %w", err) + } + subD.Writer.NewSentMessage(sentMessage, msgInfo) + } + for _, externalMessage := range m.OutgoingExternalMessages { + msgInfo, err := subD.environment.describeExternalOutMsg(externalMessage, verbose) + if err != nil { + return fmt.Errorf("error describing external message: %w", err) + } + subD.Writer.NewEvent(&externalMessage, *msgInfo) // TODO rm reference + } + return nil +} + +func (d debugger) withSubcontext(subcontext DebuggerWriter) debugger { + return debugger{ + environment: d.environment, + Writer: subcontext, + } +} + +func (d DebuggerEnvironment) describeReceivedMessage(m *tt.ReceivedMessage, verbose bool) (*lib.TxInfo, error) { + var msgInfo *lib.MessageInfo + var exitCodeDescription *string + var err error + for _, contract := range d.contracts { + if msgInfo == nil { + var t lib.MessageInfo + if m.InternalMsg != nil { + t, err = contract.InternalMessageInfo(m.InternalMsg.Body) + } else if m.ExternalMsg != nil { + t, err = contract.ExternalMessageInfo(m.ExternalMsg.Body) + } + if err == nil { + msgInfo = &t + } else if e := (&lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + if exitCodeDescription == nil { + newVar, err := contract.ExitCodeInfo(m.ExitCode) + if err == nil { + exitCodeDescription = &newVar + } else if e := &(lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + } + if msgInfo == nil { + if m.InternalMsg != nil { + basicDescription := describeBody(m.InternalMsg.Body, verbose) + msgInfo = &basicDescription + } else { + basicDescription := describeBody(m.ExternalMsg.Body, verbose) + msgInfo = &basicDescription + } + } + if exitCodeDescription == nil { + newVar := describeExitCode(&m.ExitCode) + exitCodeDescription = &newVar + } + return &lib.TxInfo{ + Msg: *msgInfo, + ExitCode: *exitCodeDescription, + }, nil +} + +func (d DebuggerEnvironment) describeSentMessage(m *tt.SentMessage, verbose bool) (lib.MessageInfo, error) { + var info lib.MessageInfo + var err error + for _, contract := range d.contracts { + info, err = contract.InternalMessageInfo(m.InternalMsg.Body) + if err == nil { + return info, nil + } + if e := &(lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + basicDescription := describeBody(m.InternalMsg.Body, verbose) + return basicDescription, nil +} + +func (d DebuggerEnvironment) describeExternalOutMsg(m tt.OutgoingExternalMessages, verbose bool) (*lib.MessageInfo, error) { + var info lib.MessageInfo + var err error + for _, contract := range d.contracts { + info, err = contract.EventInfo(m.DstAddr, m.Body) + if err == nil { + return &info, nil + } + if e := &(lib.UnknownMessageError{}); !errors.As(err, &e) { + return nil, err + } + } + simpleDescription := describeEmitBody(m.DstAddr, m.Body, verbose) + return &simpleDescription, nil +} + +func describeExitCode(exitCode *tvm.ExitCode) string { + if exitCode == nil { + return "pending" + } + if *exitCode == 0 { + return "exit code 0" + } + return fmt.Sprintf("exit code: %d (%s)", *exitCode, exitCode.Describe()) +} + +type SimpleInfo struct { + name string + body string +} + +func (i SimpleInfo) Name() string { + return i.name +} + +func (i SimpleInfo) Body() lib.BodyInfo { + return SimpleBody(i.body) +} + +type SimpleBody string + +func (b SimpleBody) Compact() string { + return string(b) +} + +func (b SimpleBody) Describe() string { + return string(b) +} + +func NewSimpleInfo(name, body string) SimpleInfo { + return SimpleInfo{ + name: name, + body: body, + } +} + +func NewSimpleInfoUnknown(body string) SimpleInfo { + return SimpleInfo{ + name: "unknown", + body: body, + } +} + +func describeBody(body *cell.Cell, verbose bool) lib.MessageInfo { + slice := body.BeginParse() + if slice.BitsLeft() == 0 { + return NewSimpleInfoUnknown("empty") + } + if !verbose { + opcode, err := slice.LoadUInt(32) + if err == nil { + return NewSimpleInfoUnknown(fmt.Sprintf("opcode: 0x %x", opcode)) + } + } + strSnake, err := body.BeginParse().LoadStringSnake() + if err == nil { + return NewSimpleInfoUnknown(fmt.Sprintf("stringSnake: %x", strSnake)) + } + return NewSimpleInfoUnknown("body:" + hex.EncodeToString(body.ToBOC())) +} + +func describeEmitBody(dstAddr *address.Address, body *cell.Cell, verbose bool) lib.MessageInfo { + extOutLogBucket := event.NewExtOutLogBucket(dstAddr) + var eventName string + { + eventTopic, err := extOutLogBucket.DecodeEventTopic() + if err == nil { + eventName = fmt.Sprintf("topic: 0x%x", eventTopic) + } else { + eventName = fmt.Sprintf("topic: unknown (%s)", dstAddr.String()) + } + } + + slice := body.BeginParse() + if slice.BitsLeft() == 0 { + return NewSimpleInfo(eventName, "empty") + } + + strSnake, err := body.BeginParse().LoadStringSnake() + if err == nil { + return NewSimpleInfo(eventName, fmt.Sprintf("stringSnake: %x", strSnake)) + } + if !verbose { + opcode, err := slice.LoadUInt(32) + if err == nil { + return NewSimpleInfo(eventName, fmt.Sprintf("opcode: %x", opcode)) + } + } + return NewSimpleInfo(eventName, "body:"+hex.EncodeToString(body.ToBOC())) +} diff --git a/pkg/ton/debug/pretty_print_test.go b/pkg/ton/debug/pretty_print_test.go new file mode 100644 index 000000000..da6cda662 --- /dev/null +++ b/pkg/ton/debug/pretty_print_test.go @@ -0,0 +1,41 @@ +package debug + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTreeDescription(t *testing.T) { + tree := treeNode{ + description: "root", + children: &[]treeNode{ + { + description: "branch", + children: &[]treeNode{ + { + description: "child1", + }, + { + description: "child2", + children: &[]treeNode{ + { + description: "grandchild1", + }, + }, + }, + }, + }, { + description: "anotherBranch", + }, + }, + } + + expected := `root +├── branch +│ ├── child1 +│ └── child2 +│ └── grandchild1 +└── anotherBranch` + assert.Equal(t, expected, tree.ToString()) +} diff --git a/pkg/ton/debug/sequencediagram.go b/pkg/ton/debug/sequencediagram.go new file mode 100644 index 000000000..3de795d6a --- /dev/null +++ b/pkg/ton/debug/sequencediagram.go @@ -0,0 +1,5 @@ +package debug + +type SequenceDiagram struct { + Actors map[string]string // address -> name +} diff --git a/pkg/ton/debug/tree_diagram.go b/pkg/ton/debug/tree_diagram.go new file mode 100644 index 000000000..8c3475775 --- /dev/null +++ b/pkg/ton/debug/tree_diagram.go @@ -0,0 +1,163 @@ +package debug + +import ( + "fmt" + "strings" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" +) + +func (n treeNode) ToString() string { + return n.description + "\n" + strings.Join(n.toTreeLines(""), "\n") +} + +func (n treeNode) toTreeLines(prefix string) []string { + var lines []string + + if n.children != nil { + for i, value := range *n.children { + isLastChild := i == len(*n.children)-1 + var connector, nextPrefix string + + if isLastChild { + connector = "└── " + nextPrefix = prefix + " " + } else { + connector = "├── " + nextPrefix = prefix + "│ " + } + + lines = append(lines, prefix+connector+value.description) + subLines := value.toTreeLines(nextPrefix) + lines = append(lines, subLines...) + } + } + + return lines +} + +type treeNode struct { + description string + children *[]treeNode +} + +func (n *treeNode) insertMsg(msg string) *treeNode { + newNode := &treeNode{ + description: msg, + children: &[]treeNode{}, + } + *n.children = append(*n.children, *newNode) + return newNode +} + +type TreeDiagram struct { + Actors map[string]string // address -> name + Root *treeNode +} + +func NewTreeDiagram() DebuggerWriter { + return &TreeDiagram{ + Actors: make(map[string]string), + Root: nil, + } +} + +func (w *TreeDiagram) String() string { + if w.Root == nil { + return "no messages" + } + return w.Root.ToString() +} + +func (w *TreeDiagram) AddActor(address string, contractType deployment.ContractType, name string) { + if _, exists := w.Actors[address]; !exists { + if name != "" { + w.Actors[address] = name + } else { + w.Actors[address] = contractType.String() + } + } +} + +func (w *TreeDiagram) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) DebuggerWriter { + newVar := w.describeInternalMsg(msg.InternalMsg, info, nil) + return w.insertMsg(newVar) +} + +func (w *TreeDiagram) insertMsg(description string) DebuggerWriter { + if w.Root == nil { + w.Root = &treeNode{ + description: description, + children: &[]treeNode{}, + } + return w + } + newNode := w.Root.insertMsg(description) + return &TreeDiagram{ + Actors: w.Actors, + Root: newNode, + } +} + +func (w *TreeDiagram) NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) { + w.insertMsg(w.describeExternalOutMsg(msg, info)) +} + +func (w *TreeDiagram) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) DebuggerWriter { + return w.insertMsg(w.DescribeReceivedMessage(msg, info)) +} + +func (w *TreeDiagram) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib.TxInfo) string { + if m.ExternalMsg != nil { + return w.describeExternalInMsg(m.ExternalMsg, info) + } else if m.InternalMsg != nil { + return w.describeInternalMsg(m.InternalMsg, info.Msg, &info.ExitCode) + } + return "unknown message type" +} + +func (w *TreeDiagram) describeAddr(addr *address.Address) string { + addrStr := addr.String() + if name, exists := w.Actors[addrStr]; exists { + return name + } + return addrStr +} + +func (w *TreeDiagram) describeExternalInMsg(msg *tlb.ExternalMessageIn, info lib.TxInfo) string { + bodyDescription := info.Msg.Body().Compact() + description := fmt.Sprintf("%s, %s{%s}", info.ExitCode, info.Msg.Name(), bodyDescription) + return fmt.Sprintf("%s --> %s", + description, w.describeAddr(msg.DstAddr)) +} + +func (w *TreeDiagram) describeExternalOutMsg(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) string { + bodyDescription := info.Body().Compact() + return fmt.Sprintf("event: {%s, %s}", info.Name(), bodyDescription) +} + +func (w *TreeDiagram) describeInternalMsg(msg *tlb.InternalMessage, info lib.MessageInfo, exitCode *string) string { + description := "amount: " + msg.Amount.String() + if msg.Bounced { + description += ", bounce" + } + if exitCode != nil { + description += ", " + *exitCode + } + description += fmt.Sprintf(", %s{%s}", info.Name(), replaceAddresses(w.Actors, info.Body().Compact())) + return fmt.Sprintf("%s --> %s", + description, w.describeAddr(msg.DstAddr)) +} + +func replaceAddresses(addressMap map[string]string, text string) string { + for oldAddr, newAddr := range addressMap { + text = strings.ReplaceAll(text, oldAddr, newAddr) + } + return text +} diff --git a/pkg/ton/tracetracking/message.go b/pkg/ton/tracetracking/message.go index e6be50cd3..3cd879899 100644 --- a/pkg/ton/tracetracking/message.go +++ b/pkg/ton/tracetracking/message.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/xssnick/tonutils-go/address" "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/ton" "github.com/xssnick/tonutils-go/tvm/cell" @@ -85,6 +86,7 @@ type ReceivedMessage struct { // OutgoingExternalMessages represents external messages sent by a contract, // typically used for events or notifications that are emitted to external systems. type OutgoingExternalMessages struct { + DstAddr *address.Address CreatedAt uint32 LT uint64 Body *cell.Cell @@ -309,7 +311,7 @@ func (m *ReceivedMessage) mapOutgoingMessages(outgoingMessages []tlb.Message) { // External messages are typically used for events or notifications that are // emitted by contracts to communicate with external systems. func (m *ReceivedMessage) AppendEvent(outMsg *tlb.ExternalMessageOut) { - e := OutgoingExternalMessages{outMsg.CreatedAt, outMsg.CreatedLT, outMsg.Body} + e := OutgoingExternalMessages{outMsg.DstAddr, outMsg.CreatedAt, outMsg.CreatedLT, outMsg.Body} m.OutgoingExternalMessages = append(m.OutgoingExternalMessages, e) } diff --git a/pkg/ton/tracetracking/pretty_print.go b/pkg/ton/tracetracking/pretty_print.go deleted file mode 100644 index bec19c44b..000000000 --- a/pkg/ton/tracetracking/pretty_print.go +++ /dev/null @@ -1,124 +0,0 @@ -package tracetracking - -import ( - "fmt" - "strings" - - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" - - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -func (m *SentMessage) Dump() string { - if m.InternalMsg != nil { - return describeInternalMsg(m.InternalMsg, nil) - } - return "event?" -} - -// Outputs a nicely indented string representation of the trace tree, with the exit codes, bounced tags and sender-receiver -func (m *ReceivedMessage) Dump() string { - lines := dumpRec(m) - return strings.Join(lines, "\n") -} - -func dumpRec(m *ReceivedMessage) []string { - output := make([]string, 1) - if m.InternalMsg != nil { - output[0] = describeInternalMsg(m.InternalMsg, &m.ExitCode) - } else if m.ExternalMsg != nil { - output[0] = describeExternalInMsg(m.ExternalMsg, &m.ExitCode) - } - for _, sentMessage := range m.OutgoingInternalReceivedMessages { - for j, line := range dumpRec(sentMessage) { - if j == 0 { - output = append(output, "└ "+line) - } else { - output = append(output, "│ "+line) - } - } - } - for _, sentMessage := range m.OutgoingInternalSentMessages { - output = append(output, "└ "+sentMessage.Dump()) - } - var from string - if m.InternalMsg != nil { - from = m.InternalMsg.DstAddr.String() - } else if m.ExternalMsg != nil { - from = m.ExternalMsg.DstAddr.String() - } - for _, externalMessage := range m.OutgoingExternalMessages { - output = append(output, "└ "+describeExternalOutMsg(from, externalMessage)) - } - return output -} - -func describeExternalInMsg(msg *tlb.ExternalMessageIn, exitCode *tvm.ExitCode) string { - description := describeBody(msg.Body) - description += ", " + describeExitCode(exitCode) - return fmt.Sprintf("%s -- (%s) --> %s", - msg.SrcAddr.String(), description, msg.DstAddr.String()) -} - -func describeExternalOutMsg(src string, msg OutgoingExternalMessages) string { - description := describeEmitBody(msg.Body) - return fmt.Sprintf("%s emit: (%s)", src, description) -} - -func describeInternalMsg(msg *tlb.InternalMessage, exitCode *tvm.ExitCode) string { - description := describeBody(msg.Body) - description += ", amount: " + msg.Amount.String() - if msg.Bounced { - description += ", bounce" - } - description += ", " + describeExitCode(exitCode) - srcAddr := msg.SrcAddr.String() - if srcAddr == "NONE" { - srcAddr = "external" - } - return fmt.Sprintf("%s -- (%s) --> %s", - srcAddr, description, msg.DstAddr.String()) -} - -func describeExitCode(exitCode *tvm.ExitCode) string { - if exitCode == nil { - return "pending" - } - if *exitCode == 0 { - return "exit code 0" - } - return fmt.Sprintf("exit code: %d (%s)", *exitCode, exitCode.Describe()) -} - -func describeBody(body *cell.Cell) string { - slice := body.BeginParse() - if slice.BitsLeft() == 0 { - return "empty" - } - opcode, err := slice.LoadUInt(32) - if err == nil { - return fmt.Sprintf("opcode: 0x %x", opcode) - } - strSnake, err := body.BeginParse().LoadStringSnake() - if err == nil { - return fmt.Sprintf("stringSnake: %x", strSnake) - } - return "body: %s" + body.DumpBits() -} - -func describeEmitBody(body *cell.Cell) string { - slice := body.BeginParse() - if slice.BitsLeft() == 0 { - return "empty" - } - strSnake, err := body.BeginParse().LoadStringSnake() - if err == nil { - return fmt.Sprintf("stringSnake: %x", strSnake) - } - opcode, err := slice.LoadUInt(32) - if err == nil { - return fmt.Sprintf("opcode: %x", opcode) - } - return "body: %s" + body.DumpBits() -} diff --git a/pkg/ton/tvm/exit_codes.go b/pkg/ton/tvm/exit_codes.go index 76c1a217e..9e4effa33 100644 --- a/pkg/ton/tvm/exit_codes.go +++ b/pkg/ton/tvm/exit_codes.go @@ -10,16 +10,6 @@ import ( // - TON documentation: https://docs.ton.org/v3/documentation/tvm/tvm-exit-codes type ExitCode int32 -// ExitCode for the message that deploys a contract can be different depending on the contract implementation. -// If the contract has an empty received message handler, and you are deploying it with an empty message, it will return ExitCodeSuccess. -// If the contract does not handle empty messages, it will return ExitCode_Tolk_UnmatchedOpcode or ExitCode_Tact_InvalidIncomingMessage. -// [NOT IMPLEMENTED] If you are deploying a contract with a non-empty message, it will return ExitCodeSuccess if the contract handles the message correctly. -// TODO it can also be other exit codes. This is the code returned by contracts not implementing the empty received message handler. -func (c ExitCode) IsSuccessfulDeployment() bool { - return c == ExitCodeSuccess || // If contract has empty receiver - c == ExitCodeTolkUnmatchedOpcode || c == ExitCodeTactInvalidIncomingMessage // If contract doesn't handle empty messages -} - const ( /// TVM exit codes From 8a6dc1f084b78c7ed1a13b67683406b862f4f742 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 3 Oct 2025 16:20:16 -0300 Subject: [PATCH 02/45] fix: update mod --- pkg/ton/debug/explorer/explorer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index cd315b41c..4fabb9c00 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -85,7 +85,7 @@ func findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, t // Start from the latest transaction maxLT := account.LastTxLT maxHash := account.LastTxHash - for range uint64(20) { + for range uint64(200) { txs, err := api.ListTransactions(ctx, srcAddr, pageSize, maxLT, maxHash) if err != nil { return nil, fmt.Errorf("get transaction: %w", err) From b88c2763c11a4beea5559fd7a555592565f99f89 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 3 Oct 2025 16:26:53 -0300 Subject: [PATCH 03/45] fix: update mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index bc65eb08a..d3c5ed4f1 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 - github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358 + github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d github.com/spf13/cobra v1.10.1 github.com/stretchr/testify v1.11.1 github.com/xssnick/tonutils-go v1.14.1 From a68f423c631489cac776bb8e0efc5d096114a019 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 15:10:32 -0300 Subject: [PATCH 04/45] doc: explaing builder interface --- pkg/ton/codec/builder.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/ton/codec/builder.go b/pkg/ton/codec/builder.go index 8d582b43b..03241e809 100644 --- a/pkg/ton/codec/builder.go +++ b/pkg/ton/codec/builder.go @@ -5,11 +5,14 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" ) +// CellCodec is an interface for encoding and decoding data of type T to and from TON Cells. type CellCodec[T any] interface { Encode(data T) (*cell.Builder, error) Decode(src *cell.Slice) (T, error) } +// TLBCodec returns a CellCodec implementation that uses struct tlb tags for encoding and decoding. +// It wraps the `tlb.ToCell` and `tlb.LoadFromCell` functions from the tonutils-go/tlb package. func TLBCodec[T any]() CellCodec[T] { return &tlbCodec[T]{} } From a7b1485ae5802ce5af491ef9fa3b454c79cfa2f8 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 15:11:16 -0300 Subject: [PATCH 05/45] fix: bump nix sha --- cmd/chainlink-ton/lock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index fa60d1d74..a214735b5 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `nix-lock-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-6a0atpcomw37rgr09whm3AsBp7GUZf6JORM7MQnnnPg="; + chainlink-ton = "sha256-IDxbmr//NcGL1hhH2v9CyokV3HvWSzwNyzuWBYChW4A="; } From 82e927e47410d44005cd95546512f6705f3ab609 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 15:51:12 -0300 Subject: [PATCH 06/45] ref: paging --- cmd/explorer/main.go | 10 ++++- pkg/ton/debug/lib/writer.go | 14 +++++++ pkg/ton/debug/pretty_print.go | 41 ++++++++----------- .../{ => visualizations/tree}/tree_diagram.go | 14 +++---- .../tree/tree_test.go} | 2 +- 5 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 pkg/ton/debug/lib/writer.go rename pkg/ton/debug/{ => visualizations/tree}/tree_diagram.go (92%) rename pkg/ton/debug/{pretty_print_test.go => visualizations/tree/tree_test.go} (97%) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 29c120b99..03784f299 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -15,6 +15,8 @@ var ( txHashStr string net string verbose bool + pageSize uint32 + maxPages uint32 ) var rootCmd = &cobra.Command{ @@ -28,7 +30,11 @@ This tool helps debug and understand transaction flows on the TON network.`, } ctx := context.Background() - err := explorer.PrintTrace(ctx, net, destAddressStr, txHashStr, verbose) + client, err := explorer.Connect(net, verbose, pageSize, maxPages) + if err != nil { + return fmt.Errorf("failed to initialize explorer: %w", err) + } + err = client.PrintTrace(ctx, destAddressStr, txHashStr) if err != nil { return fmt.Errorf("failed to execute trace: %w", err) } @@ -41,6 +47,8 @@ func init() { rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (required)") rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") + rootCmd.Flags().Uint32VarP(&pageSize, "page-size", "s", 10, "Number of blocks to fetch per page") + rootCmd.Flags().Uint32VarP(&maxPages, "max-pages", "p", 10, "Maximum number of pages to fetch") if err := rootCmd.MarkFlagRequired("address"); err != nil { panic(err) diff --git a/pkg/ton/debug/lib/writer.go b/pkg/ton/debug/lib/writer.go new file mode 100644 index 000000000..ca97ec17d --- /dev/null +++ b/pkg/ton/debug/lib/writer.go @@ -0,0 +1,14 @@ +package lib + +import ( + cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" +) + +type DebuggerVisualization interface { + NewActor(address string, contractType cldf.ContractType, name string) + NewSentMessage(msg *tt.SentMessage, info MessageInfo) DebuggerVisualization + NewReceivedMessage(msg *tt.ReceivedMessage, info TxInfo) DebuggerVisualization + NewEvent(msg *tt.OutgoingExternalMessages, info MessageInfo) + ToString() string +} diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go index e824e74eb..db4bc0b76 100644 --- a/pkg/ton/debug/pretty_print.go +++ b/pkg/ton/debug/pretty_print.go @@ -17,26 +17,13 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/minter" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/wallet" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/visualizations/tree" "github.com/smartcontractkit/chainlink-ton/pkg/ton/event" tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" ) -type DebuggerWriter interface { - AddActor(address string, contractType cldf.ContractType, name string) - NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) DebuggerWriter - NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) DebuggerWriter - NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) - String() string -} - -type DebuggerEnvironment struct { - existingAddresses map[string]cldf.TypeAndVersion - contracts map[cldf.ContractType]lib.ContractDecoder - writerFactory func(DebuggerEnvironment) DebuggerWriter -} - -// func NewDebuggerFromEnv(env cldf.Environment, writer DebuggerWriter) Debugger { +// func NewDebuggerFromEnv(env cldf.Environment, writer lib.DebuggerWriter) Debugger { // return Debugger{ // ExistingAddresses: env.GetAddressBook(), // Contracts: make(map[*cldf.ContractType]lib.ContractDecoder), @@ -44,16 +31,22 @@ type DebuggerEnvironment struct { // } // } +type DebuggerEnvironment struct { + existingAddresses map[string]cldf.TypeAndVersion + contracts map[cldf.ContractType]lib.ContractDecoder + writerFactory func(DebuggerEnvironment) lib.DebuggerVisualization +} + func NewDebuggerTreeTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvironment { return DebuggerEnvironment{ existingAddresses: addresses, contracts: defaultDecoders(), - writerFactory: func(d DebuggerEnvironment) DebuggerWriter { - writer := &TreeDiagram{ + writerFactory: func(d DebuggerEnvironment) lib.DebuggerVisualization { + writer := &tree.TreeDiagram{ Actors: make(map[string]string), } for addr, typeAndVersion := range d.existingAddresses { - writer.AddActor(addr, typeAndVersion.Type, "") + writer.NewActor(addr, typeAndVersion.Type, "") } return writer }, @@ -75,7 +68,7 @@ func registerDecoder(t map[cldf.ContractType]lib.ContractDecoder, decoder lib.Co t[decoder.ContractType()] = decoder } -func (d *DebuggerEnvironment) RegisterDecoders(decoders ...lib.ContractDecoder) { +func (d DebuggerEnvironment) RegisterDecoders(decoders ...lib.ContractDecoder) { for _, v := range decoders { d.contracts[v.ContractType()] = v } @@ -90,7 +83,7 @@ func (d DebuggerEnvironment) NewInstance() debugger { type debugger struct { environment DebuggerEnvironment - Writer DebuggerWriter + Writer lib.DebuggerVisualization } func (d DebuggerEnvironment) DumpSent(m *tt.SentMessage, verbose ...bool) string { @@ -108,7 +101,7 @@ func (d debugger) dumpSent(m *tt.SentMessage, verbose bool) string { return fmt.Sprintf("error describing sent message: %v", err) } _ = d.Writer.NewSentMessage(m, info) - return d.Writer.String() + return d.Writer.ToString() } // Outputs a nicely indented string representation of the trace tree, with the exit codes, bounced tags and sender-receiver @@ -130,11 +123,11 @@ func (d debugger) dumpReceived(m *tt.ReceivedMessage, verbose bool) (string, err if err != nil { return "", fmt.Errorf("error dumping received message: %w", err) } - return d.Writer.String(), nil + return d.Writer.ToString(), nil } func (d debugger) dumpRec(m *tt.ReceivedMessage, verbose bool) error { - var subcontext DebuggerWriter + var subcontext lib.DebuggerVisualization info, err := d.environment.describeReceivedMessage(m, verbose) if err != nil { return fmt.Errorf("error describing received message: %w", err) @@ -164,7 +157,7 @@ func (d debugger) dumpRec(m *tt.ReceivedMessage, verbose bool) error { return nil } -func (d debugger) withSubcontext(subcontext DebuggerWriter) debugger { +func (d debugger) withSubcontext(subcontext lib.DebuggerVisualization) debugger { return debugger{ environment: d.environment, Writer: subcontext, diff --git a/pkg/ton/debug/tree_diagram.go b/pkg/ton/debug/visualizations/tree/tree_diagram.go similarity index 92% rename from pkg/ton/debug/tree_diagram.go rename to pkg/ton/debug/visualizations/tree/tree_diagram.go index 8c3475775..66f7ae5c0 100644 --- a/pkg/ton/debug/tree_diagram.go +++ b/pkg/ton/debug/visualizations/tree/tree_diagram.go @@ -1,4 +1,4 @@ -package debug +package tree import ( "fmt" @@ -61,21 +61,21 @@ type TreeDiagram struct { Root *treeNode } -func NewTreeDiagram() DebuggerWriter { +func NewTreeDiagram() lib.DebuggerVisualization { return &TreeDiagram{ Actors: make(map[string]string), Root: nil, } } -func (w *TreeDiagram) String() string { +func (w *TreeDiagram) ToString() string { if w.Root == nil { return "no messages" } return w.Root.ToString() } -func (w *TreeDiagram) AddActor(address string, contractType deployment.ContractType, name string) { +func (w *TreeDiagram) NewActor(address string, contractType deployment.ContractType, name string) { if _, exists := w.Actors[address]; !exists { if name != "" { w.Actors[address] = name @@ -85,12 +85,12 @@ func (w *TreeDiagram) AddActor(address string, contractType deployment.ContractT } } -func (w *TreeDiagram) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) DebuggerWriter { +func (w *TreeDiagram) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) lib.DebuggerVisualization { newVar := w.describeInternalMsg(msg.InternalMsg, info, nil) return w.insertMsg(newVar) } -func (w *TreeDiagram) insertMsg(description string) DebuggerWriter { +func (w *TreeDiagram) insertMsg(description string) lib.DebuggerVisualization { if w.Root == nil { w.Root = &treeNode{ description: description, @@ -109,7 +109,7 @@ func (w *TreeDiagram) NewEvent(msg *tt.OutgoingExternalMessages, info lib.Messag w.insertMsg(w.describeExternalOutMsg(msg, info)) } -func (w *TreeDiagram) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) DebuggerWriter { +func (w *TreeDiagram) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) lib.DebuggerVisualization { return w.insertMsg(w.DescribeReceivedMessage(msg, info)) } diff --git a/pkg/ton/debug/pretty_print_test.go b/pkg/ton/debug/visualizations/tree/tree_test.go similarity index 97% rename from pkg/ton/debug/pretty_print_test.go rename to pkg/ton/debug/visualizations/tree/tree_test.go index da6cda662..ccd0e6b27 100644 --- a/pkg/ton/debug/pretty_print_test.go +++ b/pkg/ton/debug/visualizations/tree/tree_test.go @@ -1,4 +1,4 @@ -package debug +package tree import ( "testing" From 8f54da1a563c1f0f529f7f731139c67c896c1e68 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 15:56:37 -0300 Subject: [PATCH 07/45] ref: paging --- cmd/explorer/main.go | 39 +++++++++++++-------- pkg/ton/debug/explorer/explorer.go | 54 +++++++++++++++++++----------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 03784f299..018cdc294 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -20,13 +20,31 @@ var ( ) var rootCmd = &cobra.Command{ - Use: "explorer", + Use: "explorer
", Short: "TON blockchain explorer and trace analyzer", Long: `A command-line tool for exploring TON blockchain transactions and analyzing traces. -This tool helps debug and understand transaction flows on the TON network.`, +This tool helps debug and understand transaction flows on the TON network. + +Arguments: + address Destination address in base64 + tx-hash Transaction hash in hex`, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 2 { + return fmt.Errorf("requires exactly 2 arguments:
") + } + return nil + }, RunE: func(cmd *cobra.Command, args []string) error { - if destAddressStr == "" || txHashStr == "" { - return fmt.Errorf("both --address and --tx flags are required") + // Use positional arguments if provided, otherwise fall back to flags + address := args[0] + txHash := args[1] + + // Override with flags if they were explicitly provided + if destAddressStr != "" { + address = destAddressStr + } + if txHashStr != "" { + txHash = txHashStr } ctx := context.Background() @@ -34,7 +52,7 @@ This tool helps debug and understand transaction flows on the TON network.`, if err != nil { return fmt.Errorf("failed to initialize explorer: %w", err) } - err = client.PrintTrace(ctx, destAddressStr, txHashStr) + err = client.PrintTrace(ctx, address, txHash) if err != nil { return fmt.Errorf("failed to execute trace: %w", err) } @@ -43,19 +61,12 @@ This tool helps debug and understand transaction flows on the TON network.`, } func init() { - rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (required)") - rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (required)") + rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (optional if provided as argument)") + rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") rootCmd.Flags().Uint32VarP(&pageSize, "page-size", "s", 10, "Number of blocks to fetch per page") rootCmd.Flags().Uint32VarP(&maxPages, "max-pages", "p", 10, "Maximum number of pages to fetch") - - if err := rootCmd.MarkFlagRequired("address"); err != nil { - panic(err) - } - if err := rootCmd.MarkFlagRequired("tx"); err != nil { - panic(err) - } } func main() { diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 4fabb9c00..5de3160df 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -15,6 +15,34 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) +// Connect establishes a connection to the specified TON network and returns an +// explorer instance for tracing transactions. +// +// Parameters: +// - net: The TON network to connect to (e.g., "mainnet", "testnet", "mylocalton", "http://127.0.0.1:8000/localhost.global.config.json"). +// - verbose: Whether to enable verbose output. +// - pageSize: The number of transactions to fetch per page. +// - maxPages: The maximum number of pages to fetch. +func Connect(net string, verbose bool, pageSize uint32, maxPages uint32) (*client, error) { + apiClient, err := connect(context.Background(), net) + if err != nil { + return nil, fmt.Errorf("failed to connect to network: %w", err) + } + return &client{ + connection: apiClient, + verbose: verbose, + pageSize: pageSize, + maxPages: maxPages, + }, nil +} + +type client struct { + connection *ton.APIClient + verbose bool + pageSize uint32 + maxPages uint32 +} + // PrintTrace connects to the specified TON network, retrieves the transaction // by the given source address and transaction hash, and prints the full execution // trace of the transaction, including all outgoing messages and their subsequent @@ -22,18 +50,8 @@ import ( // // Parameters: // - ctx: The context for managing request deadlines and cancellation. -// - net: The TON network to connect to (e.g., "mainnet", "testnet", "mylocalton", "http://127.0.0.1:8000/localhost.global.config.json""). // - srcAddresstr: The source address of the transaction in string format. -func PrintTrace(ctx context.Context, net string, srcAddresstr string, txHashStr string, verbose bool) error { - client, err := connect(ctx, net) - if err != nil { - return err - } - - return PrintTraceWithClient(ctx, client, srcAddresstr, txHashStr, verbose) -} - -func PrintTraceWithClient(ctx context.Context, client *ton.APIClient, srcAddresstr string, txHashStr string, verbose bool) error { +func (e *client) PrintTrace(ctx context.Context, srcAddresstr string, txHashStr string) error { senderAddr, err := address.ParseAddr(srcAddresstr) if err != nil { return fmt.Errorf("failed to parse transaction address: %w", err) @@ -43,7 +61,7 @@ func PrintTraceWithClient(ctx context.Context, client *ton.APIClient, srcAddress return fmt.Errorf("failed to decode tx hash: %w", err) } - tx, err := findTx(ctx, client, senderAddr, txHash) + tx, err := e.findTx(ctx, e.connection, senderAddr, txHash) if err != nil { return err } @@ -57,7 +75,7 @@ func PrintTraceWithClient(ctx context.Context, client *ton.APIClient, srcAddress fmt.Println("waiting for full trace...") - err = recvMsg.WaitForTrace(client) + err = recvMsg.WaitForTrace(e.connection) if err != nil { return fmt.Errorf("failed to wait for trace: %w", err) } @@ -65,12 +83,12 @@ func PrintTraceWithClient(ctx context.Context, client *ton.APIClient, srcAddress fmt.Println("full trace received:") debugger := debug.NewDebuggerTreeTrace(map[string]deployment.TypeAndVersion{}) - fmt.Println(debugger.DumpReceived(&recvMsg, verbose)) + fmt.Println(debugger.DumpReceived(&recvMsg, e.verbose)) return nil } -func findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { +func (e *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { block, err := api.GetMasterchainInfo(ctx) if err != nil { return nil, fmt.Errorf("get masterchain info: %w", err) @@ -80,13 +98,11 @@ func findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, t return nil, fmt.Errorf("get account: %w", err) } - const pageSize uint32 = 10 - // Start from the latest transaction maxLT := account.LastTxLT maxHash := account.LastTxHash - for range uint64(200) { - txs, err := api.ListTransactions(ctx, srcAddr, pageSize, maxLT, maxHash) + for range e.maxPages { + txs, err := api.ListTransactions(ctx, srcAddr, e.pageSize, maxLT, maxHash) if err != nil { return nil, fmt.Errorf("get transaction: %w", err) } From 884a175faef2f367c058934489a87a00b772f1a2 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 16:51:45 -0300 Subject: [PATCH 08/45] feat: extend with toncenter --- cmd/explorer/main.go | 87 +++++++++++++++++++++++------- pkg/ton/debug/explorer/explorer.go | 80 +++++++++++++++++++++++++-- 2 files changed, 145 insertions(+), 22 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 018cdc294..9315defa9 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -2,8 +2,11 @@ package main import ( "context" + "encoding/hex" "fmt" + "net/url" "os" + "strings" "github.com/spf13/cobra" @@ -19,42 +22,90 @@ var ( maxPages uint32 ) +// parseURL extracts transaction hash and network from tonscan URL +// Supports tonscan.org URL formats +func parseURL(urlStr string) (txHash, address, network string, err error) { + u, err := url.Parse(urlStr) + if err != nil { + return "", "", "", fmt.Errorf("invalid URL: %w", err) + } + + // Determine network from subdomain (tonscan.org format) + network = "mainnet" // default + if strings.Contains(u.Host, "testnet.tonscan.org") { + network = "testnet" + } else if strings.Contains(u.Host, "tonscan.org") { + network = "mainnet" + } + + // Handle tonscan.org transaction URLs: /tx/{hash} + if strings.Contains(u.Host, "tonscan.org") { + pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") + if len(pathParts) >= 2 && pathParts[0] == "tx" { + txHash = pathParts[1] + return txHash, address, network, nil + } + } + + return "", "", "", fmt.Errorf("unsupported URL format") +} + var rootCmd = &cobra.Command{ - Use: "explorer
", + Use: "explorer
| ", Short: "TON blockchain explorer and trace analyzer", Long: `A command-line tool for exploring TON blockchain transactions and analyzing traces. This tool helps debug and understand transaction flows on the TON network. +Usage: + explorer
- Analyze transaction with address and hash + explorer - Analyze transaction from URL + Arguments: address Destination address in base64 - tx-hash Transaction hash in hex`, + tx-hash Transaction hash in hex + url tonscan TX URL`, Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 2 { - return fmt.Errorf("requires exactly 2 arguments:
") + if len(args) != 1 && len(args) != 2 { + return fmt.Errorf("requires 1 argument (URL) or 2 arguments (
)") } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - // Use positional arguments if provided, otherwise fall back to flags - address := args[0] - txHash := args[1] + var txHash, address, parsedNet string - // Override with flags if they were explicitly provided - if destAddressStr != "" { - address = destAddressStr + urlOrTx := args[0] + var parseURLErr error + txHash, address, parsedNet, parseURLErr = parseURL(urlOrTx) + if parseURLErr == nil { + if cmd.Root().Flags().Changed("net") { + return fmt.Errorf("cannot specify network flag when using URL") + } + net = parsedNet + } else { + // Not a URL, treat as tx-hash + if len(urlOrTx) == 64 || (len(urlOrTx) == 66 && strings.HasPrefix(urlOrTx, "0x")) { + _, err := hex.DecodeString(strings.TrimPrefix(urlOrTx, "0x")) + if err != nil { + return fmt.Errorf("invalid transaction hash or url: %w", err) + } + txHash = urlOrTx + } else { + return fmt.Errorf("failed to parse URL: %w", parseURLErr) + } } - if txHashStr != "" { - txHash = txHashStr + + if len(args) == 2 { + address = args[1] } ctx := context.Background() - client, err := explorer.Connect(net, verbose, pageSize, maxPages) - if err != nil { - return fmt.Errorf("failed to initialize explorer: %w", err) + client, parseURLErr := explorer.Connect(net, verbose, pageSize, maxPages) + if parseURLErr != nil { + return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) } - err = client.PrintTrace(ctx, address, txHash) - if err != nil { - return fmt.Errorf("failed to execute trace: %w", err) + parseURLErr = client.PrintTrace(ctx, txHash, address) + if parseURLErr != nil { + return fmt.Errorf("failed to execute trace: %w", parseURLErr) } return nil }, diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 5de3160df..a34fc3a5b 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -3,7 +3,9 @@ package explorer import ( "context" "encoding/hex" + "encoding/json" "fmt" + "net/http" "github.com/xssnick/tonutils-go/address" "github.com/xssnick/tonutils-go/liteclient" @@ -30,6 +32,7 @@ func Connect(net string, verbose bool, pageSize uint32, maxPages uint32) (*clien } return &client{ connection: apiClient, + net: net, verbose: verbose, pageSize: pageSize, maxPages: maxPages, @@ -38,6 +41,7 @@ func Connect(net string, verbose bool, pageSize uint32, maxPages uint32) (*clien type client struct { connection *ton.APIClient + net string verbose bool pageSize uint32 maxPages uint32 @@ -51,10 +55,25 @@ type client struct { // Parameters: // - ctx: The context for managing request deadlines and cancellation. // - srcAddresstr: The source address of the transaction in string format. -func (e *client) PrintTrace(ctx context.Context, srcAddresstr string, txHashStr string) error { - senderAddr, err := address.ParseAddr(srcAddresstr) - if err != nil { - return fmt.Errorf("failed to parse transaction address: %w", err) +func (e *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string) error { + var senderAddr *address.Address + var err error + if srcAddresstr == "" { + if e.verbose { + fmt.Println("source address not provided, attempting to fetch from toncenter by hash...") + } + senderAddr, err = e.GetSenderAddressFromTxHash(ctx, txHashStr) + if err != nil { + return fmt.Errorf("failed to get sender address from tx hash: %w", err) + } + if e.verbose { + fmt.Println("source address found:", senderAddr.String()) + } + } else { + senderAddr, err = address.ParseAddr(srcAddresstr) + if err != nil { + return fmt.Errorf("failed to parse transaction address: %w", err) + } } txHash, err := hex.DecodeString(txHashStr) if err != nil { @@ -88,6 +107,59 @@ func (e *client) PrintTrace(ctx context.Context, srcAddresstr string, txHashStr return nil } +func (e *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { + if e.net == "mainnet" || e.net == "testnet" { + // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr + var apiURL string + if e.net == "mainnet" { + apiURL = "https://toncenter.com/api/v3/transactions?hash=" + txHashStr + } else { + apiURL = "https://testnet.toncenter.com/api/v3/transactions?hash=" + txHashStr + } + type txResult struct { + Account string `json:"account"` + } + type addrEntry struct { + UserFriendly string `json:"user_friendly"` + } + type apiResponse struct { + Transactions []txResult `json:"transactions"` + AddressBook map[string]addrEntry `json:"address_book"` + } + resp, err := http.Get(apiURL) + if err != nil { + return nil, fmt.Errorf("failed to fetch transaction info from toncenter: %w", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code from toncenter: %d", resp.StatusCode) + } + var respData apiResponse + err = json.NewDecoder(resp.Body).Decode(&respData) + if err != nil { + return nil, fmt.Errorf("failed to decode toncenter response: %w", err) + } + if len(respData.Transactions) != 1 { + return nil, fmt.Errorf("transaction not found in toncenter response") + } + addr, err := address.ParseRawAddr(respData.Transactions[0].Account) + if err != nil { + return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) + } + + // entry, ok := respData.AddressBook[respData.Transactions[0].Account] + // if !ok { + // return nil, fmt.Errorf("source address not found in toncenter response") + // } + // addr, err := address.ParseAddr(entry.UserFriendly) + // if err != nil { + // return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) + // } + return addr, nil + } + return nil, fmt.Errorf("source address is required for non-mainnet/testnet networks") +} + func (e *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { block, err := api.GetMasterchainInfo(ctx) if err != nil { From 18dd90db95739ec044156897edd35bb875c27586 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 6 Oct 2025 16:52:29 -0300 Subject: [PATCH 09/45] ref: rm extra context --- pkg/ton/debug/explorer/explorer.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index a34fc3a5b..77190f741 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -119,12 +119,8 @@ func (e *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr strin type txResult struct { Account string `json:"account"` } - type addrEntry struct { - UserFriendly string `json:"user_friendly"` - } type apiResponse struct { - Transactions []txResult `json:"transactions"` - AddressBook map[string]addrEntry `json:"address_book"` + Transactions []txResult `json:"transactions"` } resp, err := http.Get(apiURL) if err != nil { @@ -146,15 +142,6 @@ func (e *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr strin if err != nil { return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) } - - // entry, ok := respData.AddressBook[respData.Transactions[0].Account] - // if !ok { - // return nil, fmt.Errorf("source address not found in toncenter response") - // } - // addr, err := address.ParseAddr(entry.UserFriendly) - // if err != nil { - // return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) - // } return addr, nil } return nil, fmt.Errorf("source address is required for non-mainnet/testnet networks") From eaa7ccbf88dd25ed37fe8c7f15b7139089e99782 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 7 Oct 2025 09:56:29 -0300 Subject: [PATCH 10/45] feat: query contract type --- cmd/explorer/main.go | 35 +---- .../ccip/ccipsend_executor/contract.tolk | 9 ++ go.mod | 1 + go.sum | 2 + pkg/ton/debug/explorer/explorer.go | 131 ++++++++++++++-- pkg/ton/debug/explorer/utils.go | 35 +++++ pkg/ton/debug/lib/lib.go | 2 +- pkg/ton/debug/pretty_print.go | 17 ++- .../visualizations/sequence/sanitizer.go | 115 ++++++++++++++ .../sequence/sequence_diagram.go | 140 ++++++++++++++++++ .../debug/visualizations/tree/tree_diagram.go | 68 ++++----- pkg/ton/tracetracking/message.go | 3 +- 12 files changed, 475 insertions(+), 83 deletions(-) create mode 100644 pkg/ton/debug/explorer/utils.go create mode 100644 pkg/ton/debug/visualizations/sequence/sanitizer.go create mode 100644 pkg/ton/debug/visualizations/sequence/sequence_diagram.go diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 9315defa9..04f7519c7 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "net/url" "os" "strings" @@ -20,36 +19,9 @@ var ( verbose bool pageSize uint32 maxPages uint32 + format string ) -// parseURL extracts transaction hash and network from tonscan URL -// Supports tonscan.org URL formats -func parseURL(urlStr string) (txHash, address, network string, err error) { - u, err := url.Parse(urlStr) - if err != nil { - return "", "", "", fmt.Errorf("invalid URL: %w", err) - } - - // Determine network from subdomain (tonscan.org format) - network = "mainnet" // default - if strings.Contains(u.Host, "testnet.tonscan.org") { - network = "testnet" - } else if strings.Contains(u.Host, "tonscan.org") { - network = "mainnet" - } - - // Handle tonscan.org transaction URLs: /tx/{hash} - if strings.Contains(u.Host, "tonscan.org") { - pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") - if len(pathParts) >= 2 && pathParts[0] == "tx" { - txHash = pathParts[1] - return txHash, address, network, nil - } - } - - return "", "", "", fmt.Errorf("unsupported URL format") -} - var rootCmd = &cobra.Command{ Use: "explorer
| ", Short: "TON blockchain explorer and trace analyzer", @@ -75,7 +47,7 @@ Arguments: urlOrTx := args[0] var parseURLErr error - txHash, address, parsedNet, parseURLErr = parseURL(urlOrTx) + txHash, address, parsedNet, parseURLErr = explorer.ParseURL(urlOrTx) if parseURLErr == nil { if cmd.Root().Flags().Changed("net") { return fmt.Errorf("cannot specify network flag when using URL") @@ -103,7 +75,7 @@ Arguments: if parseURLErr != nil { return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) } - parseURLErr = client.PrintTrace(ctx, txHash, address) + parseURLErr = client.PrintTrace(ctx, txHash, address, format) if parseURLErr != nil { return fmt.Errorf("failed to execute trace: %w", parseURLErr) } @@ -113,6 +85,7 @@ Arguments: func init() { rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (optional if provided as argument)") + rootCmd.Flags().StringVarP(&format, "format", "f", "", "Visualization format (tree or sequence)") rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 9a1ef87fe..471499262 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -168,3 +168,12 @@ get fun errorCode(local: uint16): uint16 { return getErrorCode(stringCrc32("com.chainlink.ton.ccip.CCIPSendExecutor"), local); } +// Returns the current code of the contract. +get fun code(): cell { + return contract.getCode(); +} + +// Returns the sha256 hash of the current code of the contract. +get fun codeHash(): int { + return contract.getCode().hash(); +} diff --git a/go.mod b/go.mod index d3c5ed4f1..1d560e927 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/BurntSushi/toml v1.4.0 // indirect github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/TyphonHill/go-mermaid v1.0.0 // indirect github.com/XSAM/otelsql v0.37.0 // indirect github.com/aptos-labs/aptos-go-sdk v1.7.1-0.20250602153733-bb1facae1d43 // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect diff --git a/go.sum b/go.sum index 39eea0ba2..45257a76f 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1 github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/TyphonHill/go-mermaid v1.0.0 h1:VtmgQwgZA+KNHJvG/O591ibBVuDkGhg2+F/olVXnXAs= +github.com/TyphonHill/go-mermaid v1.0.0/go.mod h1:BqMEbKnr2HHpZ4lJJvGjL47v6rZAUpJcOaE/db1Ppwc= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/XSAM/otelsql v0.37.0 h1:ya5RNw028JW0eJW8Ma4AmoKxAYsJSGuNVbC7F1J457A= diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 77190f741..fdd2137f0 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -7,12 +7,14 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/xssnick/tonutils-go/address" "github.com/xssnick/tonutils-go/liteclient" "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/ton" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) @@ -55,18 +57,18 @@ type client struct { // Parameters: // - ctx: The context for managing request deadlines and cancellation. // - srcAddresstr: The source address of the transaction in string format. -func (e *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string) error { +func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, visualization string) error { var senderAddr *address.Address var err error if srcAddresstr == "" { - if e.verbose { + if c.verbose { fmt.Println("source address not provided, attempting to fetch from toncenter by hash...") } - senderAddr, err = e.GetSenderAddressFromTxHash(ctx, txHashStr) + senderAddr, err = c.GetSenderAddressFromTxHash(ctx, txHashStr) if err != nil { return fmt.Errorf("failed to get sender address from tx hash: %w", err) } - if e.verbose { + if c.verbose { fmt.Println("source address found:", senderAddr.String()) } } else { @@ -80,7 +82,7 @@ func (e *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr return fmt.Errorf("failed to decode tx hash: %w", err) } - tx, err := e.findTx(ctx, e.connection, senderAddr, txHash) + tx, err := c.findTx(ctx, c.connection, senderAddr, txHash) if err != nil { return err } @@ -94,24 +96,125 @@ func (e *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr fmt.Println("waiting for full trace...") - err = recvMsg.WaitForTrace(e.connection) + err = recvMsg.WaitForTrace(c.connection) if err != nil { return fmt.Errorf("failed to wait for trace: %w", err) } + knownActors := map[string]deployment.TypeAndVersion{} // TODO fill from cld address book + + fmt.Println("querying actors") + err = c.queryActors(ctx, &recvMsg, knownActors) + if err != nil { + return fmt.Errorf("failed to query actors: %w", err) + } fmt.Println("full trace received:") - debugger := debug.NewDebuggerTreeTrace(map[string]deployment.TypeAndVersion{}) - fmt.Println(debugger.DumpReceived(&recvMsg, e.verbose)) + var debugger debug.DebuggerEnvironment + if visualization == "sequence" { + debugger = debug.NewDebuggerSequenceTrace(knownActors) + } else { + debugger = debug.NewDebuggerTreeTrace(knownActors) + } + fmt.Println(debugger.DumpReceived(&recvMsg, c.verbose)) + + return nil +} + +func (c *client) queryActors(ctx context.Context, message *tracetracking.ReceivedMessage, knownActors map[string]deployment.TypeAndVersion) error { + visited := make(map[string]bool) + block, err := c.connection.CurrentMasterchainInfo(ctx) + if err != nil { + return fmt.Errorf("failed to get masterchain info: %w", err) + } + return c.queryActorsReceivedRec(ctx, block, message, knownActors, visited) +} +func (c *client) queryActorsReceivedRec(ctx context.Context, block *ton.BlockIDExt, message *tracetracking.ReceivedMessage, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { + if message.InternalMsg != nil { + fmt.Println("received internal msg from", message.InternalMsg.SrcAddr.String(), "to", message.InternalMsg.DstAddr.String()) + err := c.queryActorIfNotVisited(ctx, block, message.InternalMsg.SrcAddr, knownActors, visited) + if err != nil { + return err + } + err = c.queryActorIfNotVisited(ctx, block, message.InternalMsg.DstAddr, knownActors, visited) + if err != nil { + return err + } + err = c.queryOutgoingMessages(ctx, block, message.OutgoingInternalSentMessages, message.OutgoingInternalReceivedMessages, knownActors, visited) + if err != nil { + return err + } + } else if message.ExternalMsg != nil { + err := c.queryActorIfNotVisited(ctx, block, message.ExternalMsg.DstAddr, knownActors, visited) + if err != nil { + return err + } + err = c.queryOutgoingMessages(ctx, block, message.OutgoingInternalSentMessages, message.OutgoingInternalReceivedMessages, knownActors, visited) + if err != nil { + return err + } + } + fmt.Println(fmt.Errorf("unknown message type").Error()) + return nil +} + +func (c *client) queryOutgoingMessages(ctx context.Context, block *ton.BlockIDExt, outgoingSentMessages []*tracetracking.SentMessage, outgoingReceivedMessages []*tracetracking.ReceivedMessage, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { + for _, outMsg := range outgoingSentMessages { + err := c.queryActorIfNotVisited(ctx, block, outMsg.InternalMsg.SrcAddr, knownActors, visited) + if err != nil { + return err + } + err = c.queryActorIfNotVisited(ctx, block, outMsg.InternalMsg.DstAddr, knownActors, visited) + if err != nil { + return err + } + } + for _, outMsg := range outgoingReceivedMessages { + err := c.queryActorsReceivedRec(ctx, block, outMsg, knownActors, visited) + if err != nil { + return err + } + } + return nil +} + +func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDExt, addr *address.Address, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { + if visited[addr.String()] { + return nil + } + if _, known := knownActors[addr.String()]; known { + visited[addr.String()] = true + return nil + } + var typeVersion common.TypeAndVersion + result, err := c.connection.RunGetMethod(ctx, block, addr, "typeAndVersion") + defer func() { + }() + if err != nil { + return nil + } + if err = typeVersion.FromResult(result); err != nil { + return fmt.Errorf("failed to parse typeAndVersion: %w", err) + } + visited[addr.String()] = true + if err != nil { + // No need to return error if contract doesn't implement typeAndVersion + return nil + } + semVer := semver.MustParse(typeVersion.Version) + knownActors[addr.String()] = deployment.TypeAndVersion{ + Version: *semVer, + Type: deployment.ContractType(typeVersion.Type), + } return nil } -func (e *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { - if e.net == "mainnet" || e.net == "testnet" { +func (c *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { + if c.net == "mainnet" || c.net == "testnet" { // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr var apiURL string - if e.net == "mainnet" { + if c.net == "mainnet" { apiURL = "https://toncenter.com/api/v3/transactions?hash=" + txHashStr } else { apiURL = "https://testnet.toncenter.com/api/v3/transactions?hash=" + txHashStr @@ -147,7 +250,7 @@ func (e *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr strin return nil, fmt.Errorf("source address is required for non-mainnet/testnet networks") } -func (e *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { +func (c *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { block, err := api.GetMasterchainInfo(ctx) if err != nil { return nil, fmt.Errorf("get masterchain info: %w", err) @@ -160,8 +263,8 @@ func (e *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *addres // Start from the latest transaction maxLT := account.LastTxLT maxHash := account.LastTxHash - for range e.maxPages { - txs, err := api.ListTransactions(ctx, srcAddr, e.pageSize, maxLT, maxHash) + for range c.maxPages { + txs, err := api.ListTransactions(ctx, srcAddr, c.pageSize, maxLT, maxHash) if err != nil { return nil, fmt.Errorf("get transaction: %w", err) } diff --git a/pkg/ton/debug/explorer/utils.go b/pkg/ton/debug/explorer/utils.go new file mode 100644 index 000000000..ac438a3cc --- /dev/null +++ b/pkg/ton/debug/explorer/utils.go @@ -0,0 +1,35 @@ +package explorer + +import ( + "fmt" + "net/url" + "strings" +) + +// ParseURL extracts transaction hash and network from tonscan URL +// Supports tonscan.org URL formats +func ParseURL(urlStr string) (txHash, address, network string, err error) { + u, err := url.Parse(urlStr) + if err != nil { + return "", "", "", fmt.Errorf("invalid URL: %w", err) + } + + // Determine network from subdomain (tonscan.org format) + network = "mainnet" // default + if strings.Contains(u.Host, "testnet.tonscan.org") { + network = "testnet" + } else if strings.Contains(u.Host, "tonscan.org") { + network = "mainnet" + } + + // Handle tonscan.org transaction URLs: /tx/{hash} + if strings.Contains(u.Host, "tonscan.org") { + pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") + if len(pathParts) >= 2 && pathParts[0] == "tx" { + txHash = pathParts[1] + return txHash, address, network, nil + } + } + + return "", "", "", fmt.Errorf("unsupported URL format") +} diff --git a/pkg/ton/debug/lib/lib.go b/pkg/ton/debug/lib/lib.go index a61265c1e..12403b070 100644 --- a/pkg/ton/debug/lib/lib.go +++ b/pkg/ton/debug/lib/lib.go @@ -45,7 +45,7 @@ func NewMessageInfo[T any](name string, msg T) (MessageInfo, error) { if err != nil { return nil, err } - long, err := json.MarshalIndent(msg, "", " ") + long, err := json.MarshalIndent(msg, "", "__") if err != nil { return nil, err } diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go index db4bc0b76..e10a9b900 100644 --- a/pkg/ton/debug/pretty_print.go +++ b/pkg/ton/debug/pretty_print.go @@ -17,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/minter" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/jetton/wallet" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/visualizations/sequence" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/visualizations/tree" "github.com/smartcontractkit/chainlink-ton/pkg/ton/event" tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" @@ -42,9 +43,21 @@ func NewDebuggerTreeTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvi existingAddresses: addresses, contracts: defaultDecoders(), writerFactory: func(d DebuggerEnvironment) lib.DebuggerVisualization { - writer := &tree.TreeDiagram{ - Actors: make(map[string]string), + writer := tree.NewTreeDiagram() + for addr, typeAndVersion := range d.existingAddresses { + writer.NewActor(addr, typeAndVersion.Type, "") } + return writer + }, + } +} + +func NewDebuggerSequenceTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvironment { + return DebuggerEnvironment{ + existingAddresses: addresses, + contracts: defaultDecoders(), + writerFactory: func(d DebuggerEnvironment) lib.DebuggerVisualization { + writer := sequence.NewVisualization() for addr, typeAndVersion := range d.existingAddresses { writer.NewActor(addr, typeAndVersion.Type, "") } diff --git a/pkg/ton/debug/visualizations/sequence/sanitizer.go b/pkg/ton/debug/visualizations/sequence/sanitizer.go new file mode 100644 index 000000000..7b49aeb3a --- /dev/null +++ b/pkg/ton/debug/visualizations/sequence/sanitizer.go @@ -0,0 +1,115 @@ +package sequence + +import ( + "strings" + "unicode/utf8" +) + +func sanitizeString(s string) string { + var wrapWidth int = 80 + description := wrap(s, wrapWidth) + description = strings.ReplaceAll(description, "\n", "
") + description = strings.ReplaceAll(description, "\"", "'") + return description +} + +// wrap wraps s to the given width. It preserves blank lines as paragraph breaks. +// Words longer than width are split. If width <= 0, s is returned unchanged. +func wrap(s string, width int) string { + if width <= 0 { + return s + } + + var out []string + paras := strings.Split(s, "\n") + + for i := range paras { + p := paras[i] + + // Preserve consecutive blank lines + if strings.TrimSpace(p) == "" { + out = append(out, "") + continue + } + + words := strings.Fields(p) + var line strings.Builder + lineRunes := 0 + + flush := func() { + if line.Len() > 0 { + out = append(out, line.String()) + line.Reset() + lineRunes = 0 + } + } + + for _, w := range words { + wLen := utf8.RuneCountInString(w) + + // If the word itself is longer than width, hard split it. + for wLen > width { + // fill remaining space first if the current line isn't empty + if lineRunes > 0 { + flush() + } + // take 'width' runes of w + part := takeRunes(w, width) + out = append(out, part) + w = dropRunes(w, width) + wLen = utf8.RuneCountInString(w) + } + + if lineRunes == 0 { + // start a new line + line.WriteString(w) + lineRunes = wLen + } else if lineRunes+1+wLen <= width { + // add to current line with a space + line.WriteByte(' ') + line.WriteString(w) + lineRunes += 1 + wLen + } else { + // wrap + flush() + line.WriteString(w) + lineRunes = wLen + } + } + + flush() + } + + // Join lines, but keep single trailing newline behavior similar to input + return strings.Join(out, "\n") +} + +// takeRunes returns the first n runes of s. +func takeRunes(s string, n int) string { + if n <= 0 { + return "" + } + i := 0 + for pos := range s { + if i == n { + return s[:pos] + } + i++ + } + return s // s has <= n runes +} + +// dropRunes drops the first n runes of s and returns the rest. +func dropRunes(s string, n int) string { + if n <= 0 { + return s + } + i := 0 + for pos := range s { + if i == n { + return s[pos:] + } + i++ + } + return "" +} diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go new file mode 100644 index 000000000..744b64eb1 --- /dev/null +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -0,0 +1,140 @@ +package sequence + +import ( + "fmt" + "strings" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + + "github.com/TyphonHill/go-mermaid/diagrams/sequence" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" +) + +type visualization struct { + Actors map[string]string // address -> name + ActiveActors map[string]*sequence.Actor + Diagram *sequence.Diagram +} + +func NewVisualization() lib.DebuggerVisualization { + diagram := sequence.NewDiagram() + diagram.Config.SetMessageAlign("left") + return &visualization{ + Actors: make(map[string]string), + ActiveActors: make(map[string]*sequence.Actor), + Diagram: diagram, + } +} + +func (v *visualization) ToString() string { + return v.Diagram.String() +} + +func (v *visualization) NewActor(address string, contractType deployment.ContractType, name string) { + if _, exists := v.Actors[address]; !exists { + if name != "" { + v.Actors[address] = name + } else { + v.Actors[address] = contractType.String() + } + } +} + +func (v *visualization) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) lib.DebuggerVisualization { + newVar := v.describeInternalMsg(msg.InternalMsg, info, nil) + return v.insertMsg(msg.InternalMsg.SrcAddr, msg.InternalMsg.DstAddr, newVar) +} + +func (v *visualization) insertMsg(from, to *address.Address, description string) lib.DebuggerVisualization { + description = sanitizeString(description) + if from != nil && to != nil { + v.Diagram.AddMessage(v.actorFromAddr(from), v.actorFromAddr(to), sequence.MessageSolidArrow, description) + } else if from != nil && to == nil { + v.Diagram.AddMessage(v.actorFromAddr(from), sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.MessageSolidArrow, description) + } else if from == nil && to != nil { + v.Diagram.AddMessage(sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), v.actorFromAddr(to), sequence.MessageSolidArrow, description) + } else { + v.Diagram.AddMessage(sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.MessageSolidArrow, description) + } + return v +} + +func (v *visualization) NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) { + fromActor := v.actorFromAddr(msg.SrcAddr) + description := v.describeExternalOutMsg(msg, info) + description = sanitizeString(description) + v.Diagram.AddNote(sequence.NoteOver, description, fromActor) +} + +func (v *visualization) actorFromAddr(addr *address.Address) *sequence.Actor { + var actor *sequence.Actor + var ok bool + name := v.describeAddr(addr) + id := strings.Replace(addr.StringRaw(), ":", "_", -1) + if actor, ok = v.ActiveActors[id]; !ok { + actor = v.Diagram.AddActor(id, name, sequence.ActorParticipant) + v.ActiveActors[id] = actor + } + return actor +} + +func (v *visualization) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) lib.DebuggerVisualization { + if msg.ExternalMsg != nil { + return v.insertMsg(nil, msg.ExternalMsg.DstAddr, v.DescribeReceivedMessage(msg, info)) + } else if msg.InternalMsg != nil { + return v.insertMsg(msg.InternalMsg.SrcAddr, msg.InternalMsg.DstAddr, v.DescribeReceivedMessage(msg, info)) + } + panic("unknown message type") +} + +func (v *visualization) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib.TxInfo) string { + if m.ExternalMsg != nil { + return v.describeExternalInMsg(m.ExternalMsg, info) + } else if m.InternalMsg != nil { + return v.describeInternalMsg(m.InternalMsg, info.Msg, &info.ExitCode) + } + return "unknown message type" +} + +func (v *visualization) describeAddr(addr *address.Address) string { + addrStr := addr.String() + if name, exists := v.Actors[addrStr]; exists { + return name + } + return addrStr +} + +func (v *visualization) describeExternalInMsg(msg *tlb.ExternalMessageIn, info lib.TxInfo) string { + bodyDescription := info.Msg.Body().Describe() + description := fmt.Sprintf("%s
%s{%s}", info.ExitCode, info.Msg.Name(), bodyDescription) + return description +} + +func (v *visualization) describeExternalOutMsg(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) string { + bodyDescription := info.Body().Describe() + return fmt.Sprintf("event: {%s
%s}", info.Name(), bodyDescription) +} + +func (v *visualization) describeInternalMsg(msg *tlb.InternalMessage, info lib.MessageInfo, exitCode *string) string { + description := "amount: " + msg.Amount.String() + if msg.Bounced { + description += "
bounce" + } + if exitCode != nil { + description += "
" + *exitCode + } + description += fmt.Sprintf("
%s{%s}", info.Name(), replaceAddresses(v.Actors, info.Body().Describe())) + return description +} + +func replaceAddresses(addressMap map[string]string, text string) string { + for oldAddr, newAddr := range addressMap { + text = strings.ReplaceAll(text, oldAddr, newAddr) + } + return text +} diff --git a/pkg/ton/debug/visualizations/tree/tree_diagram.go b/pkg/ton/debug/visualizations/tree/tree_diagram.go index 66f7ae5c0..d8a494e7c 100644 --- a/pkg/ton/debug/visualizations/tree/tree_diagram.go +++ b/pkg/ton/debug/visualizations/tree/tree_diagram.go @@ -56,93 +56,93 @@ func (n *treeNode) insertMsg(msg string) *treeNode { return newNode } -type TreeDiagram struct { +type visualization struct { Actors map[string]string // address -> name Root *treeNode } func NewTreeDiagram() lib.DebuggerVisualization { - return &TreeDiagram{ + return &visualization{ Actors: make(map[string]string), Root: nil, } } -func (w *TreeDiagram) ToString() string { - if w.Root == nil { +func (v *visualization) ToString() string { + if v.Root == nil { return "no messages" } - return w.Root.ToString() + return v.Root.ToString() } -func (w *TreeDiagram) NewActor(address string, contractType deployment.ContractType, name string) { - if _, exists := w.Actors[address]; !exists { +func (v *visualization) NewActor(address string, contractType deployment.ContractType, name string) { + if _, exists := v.Actors[address]; !exists { if name != "" { - w.Actors[address] = name + v.Actors[address] = name } else { - w.Actors[address] = contractType.String() + v.Actors[address] = contractType.String() } } } -func (w *TreeDiagram) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) lib.DebuggerVisualization { - newVar := w.describeInternalMsg(msg.InternalMsg, info, nil) - return w.insertMsg(newVar) +func (v *visualization) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo) lib.DebuggerVisualization { + newVar := v.describeInternalMsg(msg.InternalMsg, info, nil) + return v.insertMsg(newVar) } -func (w *TreeDiagram) insertMsg(description string) lib.DebuggerVisualization { - if w.Root == nil { - w.Root = &treeNode{ +func (v *visualization) insertMsg(description string) lib.DebuggerVisualization { + if v.Root == nil { + v.Root = &treeNode{ description: description, children: &[]treeNode{}, } - return w + return v } - newNode := w.Root.insertMsg(description) - return &TreeDiagram{ - Actors: w.Actors, + newNode := v.Root.insertMsg(description) + return &visualization{ + Actors: v.Actors, Root: newNode, } } -func (w *TreeDiagram) NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) { - w.insertMsg(w.describeExternalOutMsg(msg, info)) +func (v *visualization) NewEvent(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) { + v.insertMsg(v.describeExternalOutMsg(msg, info)) } -func (w *TreeDiagram) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) lib.DebuggerVisualization { - return w.insertMsg(w.DescribeReceivedMessage(msg, info)) +func (v *visualization) NewReceivedMessage(msg *tt.ReceivedMessage, info lib.TxInfo) lib.DebuggerVisualization { + return v.insertMsg(v.DescribeReceivedMessage(msg, info)) } -func (w *TreeDiagram) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib.TxInfo) string { +func (v *visualization) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib.TxInfo) string { if m.ExternalMsg != nil { - return w.describeExternalInMsg(m.ExternalMsg, info) + return v.describeExternalInMsg(m.ExternalMsg, info) } else if m.InternalMsg != nil { - return w.describeInternalMsg(m.InternalMsg, info.Msg, &info.ExitCode) + return v.describeInternalMsg(m.InternalMsg, info.Msg, &info.ExitCode) } return "unknown message type" } -func (w *TreeDiagram) describeAddr(addr *address.Address) string { +func (v *visualization) describeAddr(addr *address.Address) string { addrStr := addr.String() - if name, exists := w.Actors[addrStr]; exists { + if name, exists := v.Actors[addrStr]; exists { return name } return addrStr } -func (w *TreeDiagram) describeExternalInMsg(msg *tlb.ExternalMessageIn, info lib.TxInfo) string { +func (v *visualization) describeExternalInMsg(msg *tlb.ExternalMessageIn, info lib.TxInfo) string { bodyDescription := info.Msg.Body().Compact() description := fmt.Sprintf("%s, %s{%s}", info.ExitCode, info.Msg.Name(), bodyDescription) return fmt.Sprintf("%s --> %s", - description, w.describeAddr(msg.DstAddr)) + description, v.describeAddr(msg.DstAddr)) } -func (w *TreeDiagram) describeExternalOutMsg(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) string { +func (v *visualization) describeExternalOutMsg(msg *tt.OutgoingExternalMessages, info lib.MessageInfo) string { bodyDescription := info.Body().Compact() return fmt.Sprintf("event: {%s, %s}", info.Name(), bodyDescription) } -func (w *TreeDiagram) describeInternalMsg(msg *tlb.InternalMessage, info lib.MessageInfo, exitCode *string) string { +func (v *visualization) describeInternalMsg(msg *tlb.InternalMessage, info lib.MessageInfo, exitCode *string) string { description := "amount: " + msg.Amount.String() if msg.Bounced { description += ", bounce" @@ -150,9 +150,9 @@ func (w *TreeDiagram) describeInternalMsg(msg *tlb.InternalMessage, info lib.Mes if exitCode != nil { description += ", " + *exitCode } - description += fmt.Sprintf(", %s{%s}", info.Name(), replaceAddresses(w.Actors, info.Body().Compact())) + description += fmt.Sprintf(", %s{%s}", info.Name(), replaceAddresses(v.Actors, info.Body().Compact())) return fmt.Sprintf("%s --> %s", - description, w.describeAddr(msg.DstAddr)) + description, v.describeAddr(msg.DstAddr)) } func replaceAddresses(addressMap map[string]string, text string) string { diff --git a/pkg/ton/tracetracking/message.go b/pkg/ton/tracetracking/message.go index 3cd879899..00d883b76 100644 --- a/pkg/ton/tracetracking/message.go +++ b/pkg/ton/tracetracking/message.go @@ -86,6 +86,7 @@ type ReceivedMessage struct { // OutgoingExternalMessages represents external messages sent by a contract, // typically used for events or notifications that are emitted to external systems. type OutgoingExternalMessages struct { + SrcAddr *address.Address DstAddr *address.Address CreatedAt uint32 LT uint64 @@ -311,7 +312,7 @@ func (m *ReceivedMessage) mapOutgoingMessages(outgoingMessages []tlb.Message) { // External messages are typically used for events or notifications that are // emitted by contracts to communicate with external systems. func (m *ReceivedMessage) AppendEvent(outMsg *tlb.ExternalMessageOut) { - e := OutgoingExternalMessages{outMsg.DstAddr, outMsg.CreatedAt, outMsg.CreatedLT, outMsg.Body} + e := OutgoingExternalMessages{outMsg.SrcAddr, outMsg.DstAddr, outMsg.CreatedAt, outMsg.CreatedLT, outMsg.Body} m.OutgoingExternalMessages = append(m.OutgoingExternalMessages, e) } From b979934f47966aa9ea2c4490e91c5d5b7235b1c9 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 7 Oct 2025 10:25:00 -0300 Subject: [PATCH 11/45] wip: match wallet code --- pkg/ton/debug/explorer/explorer.go | 32 +++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index fdd2137f0..1bb915c4a 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -192,16 +192,12 @@ func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDE defer func() { }() if err != nil { - return nil + return c.tryMatchByCodeHash(ctx, block, addr, knownActors) } if err = typeVersion.FromResult(result); err != nil { return fmt.Errorf("failed to parse typeAndVersion: %w", err) } visited[addr.String()] = true - if err != nil { - // No need to return error if contract doesn't implement typeAndVersion - return nil - } semVer := semver.MustParse(typeVersion.Version) knownActors[addr.String()] = deployment.TypeAndVersion{ Version: *semVer, @@ -210,6 +206,32 @@ func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDE return nil } +func (c *client) tryMatchByCodeHash(ctx context.Context, block *ton.BlockIDExt, addr *address.Address, knownActors map[string]deployment.TypeAndVersion) error { + account, err := c.connection.GetAccount(ctx, block, addr) + if err != nil { + return fmt.Errorf("get account: %w", err) + } + code := account.Code.ToBOC() + codeHex := hex.EncodeToString(code) + fmt.Println("querying actor by code hash", addr.String(), codeHex) + switch codeHex { + case "b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03": // https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/main/build/HighloadWalletV3.compiled.json + knownActors[addr.String()] = deployment.TypeAndVersion{ + Version: *semver.MustParse("3.2.0"), + Type: deployment.ContractType("org.ton.Wallet"), + } + return nil + case "b5ee9c7241021401000281000114ff00f4a413f4bcf2c80b01020120020d020148030402dcd020d749c120915b8f6320d70b1f2082106578746ebd21821073696e74bdb0925f03e082106578746eba8eb48020d72101d074d721fa4030fa44f828fa443058bd915be0ed44d0810141d721f4058307f40e6fa1319130e18040d721707fdb3ce03120d749810280b99130e070e2100f020120050c020120060902016e07080019adce76a2684020eb90eb85ffc00019af1df6a2684010eb90eb858fc00201480a0b0017b325fb51341c75c875c2c7e00011b262fb513435c280200019be5f0f6a2684080a0eb90fa02c0102f20e011e20d70b1f82107369676ebaf2e08a7f0f01e68ef0eda2edfb218308d722028308d723208020d721d31fd31fd31fed44d0d200d31f20d31fd3ffd70a000af90140ccf9109a28945f0adb31e1f2c087df02b35007b0f2d0845125baf2e0855036baf2e086f823bbf2d0882292f800de01a47fc8ca00cb1f01cf16c9ed542092f80fde70db3cd81003f6eda2edfb02f404216e926c218e4c0221d73930709421c700b38e2d01d72820761e436c20d749c008f2e09320d74ac002f2e09320d71d06c712c2005230b0f2d089d74cd7393001a4e86c128407bbf2e093d74ac000f2e093ed55e2d20001c000915be0ebd72c08142091709601d72c081c12e25210b1e30f20d74a111213009601fa4001fa44f828fa443058baf2e091ed44d0810141d718f405049d7fc8ca0040048307f453f2e08b8e14038307f45bf2e08c22d70a00216e01b3b0f2d090e2c85003cf1612f400c9ed54007230d72c08248e2d21f2e092d200ed44d0d2005113baf2d08f54503091319c01810140d721d70a00f2e08ee2c8ca0058cf16c9ed5493f2c08de20010935bdb31e1d74cd0b4d6c35e": // https://github.com/ton-blockchain/wallet-contract-v5/blob/main/build/wallet_v5.compiled.json + knownActors[addr.String()] = deployment.TypeAndVersion{ + Version: *semver.MustParse("3.1.0"), + Type: deployment.ContractType("org.ton.Wallet"), + } + return nil + // TODO add missing wallets + } + return nil +} + func (c *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { if c.net == "mainnet" || c.net == "testnet" { // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr From 500adadc6b30b1585fa286e28ad30c239cc9af59 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 7 Oct 2025 10:35:28 -0300 Subject: [PATCH 12/45] feat: decoding ccipmessagesent --- pkg/ccip/bindings/onramp/codec.go | 8 ++++++++ pkg/ccip/bindings/onramp/onramp.go | 5 +++++ pkg/ton/debug/decoders/ccip/onramp/onramp.go | 15 +++++++++++++++ .../visualizations/sequence/sequence_diagram.go | 1 + 4 files changed, 29 insertions(+) diff --git a/pkg/ccip/bindings/onramp/codec.go b/pkg/ccip/bindings/onramp/codec.go index c5b463091..f2f1581c7 100644 --- a/pkg/ccip/bindings/onramp/codec.go +++ b/pkg/ccip/bindings/onramp/codec.go @@ -15,6 +15,13 @@ var Builder = builder{ UpdateAllowlists: codec.TLBCodec[UpdateAllowlistsMessage](), }, }, + Events: eventBuilder{ + CCIPMessageSent: codec.TLBCodec[CCIPMessageSent](), + }, +} + +type eventBuilder struct { + CCIPMessageSent codec.CellCodec[CCIPMessageSent] } type inMessageBuilder struct { @@ -32,4 +39,5 @@ type messageBuilder struct { type builder struct { Messages messageBuilder + Events eventBuilder } diff --git a/pkg/ccip/bindings/onramp/onramp.go b/pkg/ccip/bindings/onramp/onramp.go index 03dc34dc7..b3234d462 100644 --- a/pkg/ccip/bindings/onramp/onramp.go +++ b/pkg/ccip/bindings/onramp/onramp.go @@ -22,6 +22,11 @@ const ( OpcodeUpdateAllowlists = 0x10000005 ) +// Topics +const ( + TopicCCIPMessageSent = 0xA45D293C // CRC32("CCIPMessageSent") +) + // CCIPMessageSent uses TVM2AnyRampMessage but with event-specific header (no onramp address) type CCIPMessageSent struct { Message ocr.TVM2AnyRampMessage `tlb:"."` diff --git a/pkg/ton/debug/decoders/ccip/onramp/onramp.go b/pkg/ton/debug/decoders/ccip/onramp/onramp.go index cafe0a776..029f969e1 100644 --- a/pkg/ton/debug/decoders/ccip/onramp/onramp.go +++ b/pkg/ton/debug/decoders/ccip/onramp/onramp.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/common" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/event" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" ) @@ -28,6 +29,20 @@ func (d *decoder) ContractType() cldf.ContractType { // EventInfo implements lib.ContractDecoder. func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { + bucket := event.NewExtOutLogBucket(dstAddr) + topic, err := bucket.DecodeEventTopic() + if err != nil { + return nil, &lib.UnknownMessageError{} + } + if topic == onramp.TopicCCIPMessageSent { + + ccipMessageSent, err := onramp.Builder.Events.CCIPMessageSent.Decode(msg.BeginParse()) + if err != nil { + return nil, err + } + return lib.NewMessageInfo("CCIPMessageSent", ccipMessageSent) + } + return nil, &lib.UnknownMessageError{} } diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 744b64eb1..98f793f6e 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -24,6 +24,7 @@ type visualization struct { func NewVisualization() lib.DebuggerVisualization { diagram := sequence.NewDiagram() diagram.Config.SetMessageAlign("left") + diagram.Config.SetNoteAlign("left") return &visualization{ Actors: make(map[string]string), ActiveActors: make(map[string]*sequence.Actor), From a818fc7d83b1b48b0df201e0d12cde7531242626 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 7 Oct 2025 14:02:54 -0300 Subject: [PATCH 13/45] fix: onramp opcodes --- pkg/ccip/bindings/onramp/onramp.go | 6 +++--- pkg/ton/debug/explorer/explorer.go | 3 +-- pkg/ton/debug/pretty_print.go | 15 ++++++++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/pkg/ccip/bindings/onramp/onramp.go b/pkg/ccip/bindings/onramp/onramp.go index b3234d462..2858b3a9d 100644 --- a/pkg/ccip/bindings/onramp/onramp.go +++ b/pkg/ccip/bindings/onramp/onramp.go @@ -14,9 +14,9 @@ import ( // OnRamp opcodes const ( - OpcodeOnRampSend = 0x40000001 - OpcodeOnRampWithdrawJettons = 0x40000002 - OpcodeOnRampExecutorFinishedSuccessfully = 0x40000003 + OpcodeOnRampSend = 0x10000002 + OpcodeOnRampWithdrawJettons = 0x266AEACF + OpcodeOnRampExecutorFinishedSuccessfully = 0xCFA6B336 OpcodeSetDynamicConfig = 0x10000003 OpcodeUpdateDestChainConfigs = 0x10000004 OpcodeUpdateAllowlists = 0x10000005 diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 1bb915c4a..4757ea6e0 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -132,7 +132,6 @@ func (c *client) queryActors(ctx context.Context, message *tracetracking.Receive func (c *client) queryActorsReceivedRec(ctx context.Context, block *ton.BlockIDExt, message *tracetracking.ReceivedMessage, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { if message.InternalMsg != nil { - fmt.Println("received internal msg from", message.InternalMsg.SrcAddr.String(), "to", message.InternalMsg.DstAddr.String()) err := c.queryActorIfNotVisited(ctx, block, message.InternalMsg.SrcAddr, knownActors, visited) if err != nil { return err @@ -213,7 +212,7 @@ func (c *client) tryMatchByCodeHash(ctx context.Context, block *ton.BlockIDExt, } code := account.Code.ToBOC() codeHex := hex.EncodeToString(code) - fmt.Println("querying actor by code hash", addr.String(), codeHex) + // fmt.Println("querying actor by code hash", addr.String(), codeHex) switch codeHex { case "b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03": // https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/main/build/HighloadWalletV3.compiled.json knownActors[addr.String()] = deployment.TypeAndVersion{ diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go index e10a9b900..7b873f8fb 100644 --- a/pkg/ton/debug/pretty_print.go +++ b/pkg/ton/debug/pretty_print.go @@ -317,6 +317,10 @@ func describeBody(body *cell.Cell, verbose bool) lib.MessageInfo { if err == nil { return NewSimpleInfoUnknown(fmt.Sprintf("stringSnake: %x", strSnake)) } + opcode, err := slice.LoadUInt(32) + if err != nil { + return NewSimpleInfoUnknown(fmt.Sprintf("opcode: %x, body: %s", opcode, hex.EncodeToString(body.ToBOC()))) + } return NewSimpleInfoUnknown("body:" + hex.EncodeToString(body.ToBOC())) } @@ -341,11 +345,12 @@ func describeEmitBody(dstAddr *address.Address, body *cell.Cell, verbose bool) l if err == nil { return NewSimpleInfo(eventName, fmt.Sprintf("stringSnake: %x", strSnake)) } + opcode, err := slice.LoadUInt(32) + if err != nil { + return NewSimpleInfo(eventName, "body:"+hex.EncodeToString(body.ToBOC())) + } if !verbose { - opcode, err := slice.LoadUInt(32) - if err == nil { - return NewSimpleInfo(eventName, fmt.Sprintf("opcode: %x", opcode)) - } + return NewSimpleInfo(eventName, fmt.Sprintf("opcode: %x", opcode)) } - return NewSimpleInfo(eventName, "body:"+hex.EncodeToString(body.ToBOC())) + return NewSimpleInfo(eventName, fmt.Sprintf("opcode: %x, body: %s", opcode, hex.EncodeToString(body.ToBOC()))) } From ec002ed4ba2f16a96fbba2491407d519be882b1b Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Thu, 9 Oct 2025 15:37:47 -0300 Subject: [PATCH 14/45] fix: gomods tidy after rebase --- go.mod | 4 ++-- go.sum | 4 ++-- integration-tests/go.mod | 1 + integration-tests/go.sum | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 1d560e927..9ee6b5830 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ toolchain go1.24.6 require github.com/hashicorp/go-plugin v1.6.3 require ( + github.com/Masterminds/semver/v3 v3.4.0 + github.com/TyphonHill/go-mermaid v1.0.0 github.com/ethereum/go-ethereum v1.16.2 github.com/gagliardetto/solana-go v1.13.0 github.com/pelletier/go-toml/v2 v2.2.4 @@ -25,9 +27,7 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/BurntSushi/toml v1.4.0 // indirect - github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/TyphonHill/go-mermaid v1.0.0 // indirect github.com/XSAM/otelsql v0.37.0 // indirect github.com/aptos-labs/aptos-go-sdk v1.7.1-0.20250602153733-bb1facae1d43 // indirect github.com/avast/retry-go/v4 v4.6.1 // indirect diff --git a/go.sum b/go.sum index 45257a76f..c6c0a2b19 100644 --- a/go.sum +++ b/go.sum @@ -609,8 +609,8 @@ github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9 github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358 h1:+NVzR5LZVazRUunzVn34u+lwnpmn6NTVPCeZOVyQHLo= -github.com/smartcontractkit/libocr v0.0.0-20250707144819-babe0ec4e358/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= +github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic6wpKH5F1nwDoRj9+70IxXunvCyNcCkA+9ik0= +github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= github.com/smartcontractkit/mcms v0.25.0 h1:GTkG6jQ2CYoVQFKkRQnA42IvUrR4gObeHqwrQNRhmGM= github.com/smartcontractkit/mcms v0.25.0/go.mod h1:7v5DNfWqIS81nISbuFBrlV1QHZfD+pFQzjsxqqhcK9o= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 03ae377b5..e56c0aba6 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -51,6 +51,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.12.5 // indirect github.com/NethermindEth/starknet.go v0.8.0 // indirect + github.com/TyphonHill/go-mermaid v1.0.0 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/XSAM/otelsql v0.37.0 // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 0e15cb179..08f63d51a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -98,6 +98,8 @@ github.com/NethermindEth/juno v0.12.5 h1:a+KYQg8MxzNJIbbqGHq+vU9nTyuWu3acbyXxcUP github.com/NethermindEth/juno v0.12.5/go.mod h1:XonWmZVRwCVHv1gjoVCoTFiZnYObwdukpd3NCsl04bA= github.com/NethermindEth/starknet.go v0.8.0 h1:mGh7qDWrvuXJPcgGJP31DpifzP6+Ef2gt/BQhaqsV40= github.com/NethermindEth/starknet.go v0.8.0/go.mod h1:slNA8PxtxA/0LQv0FwHnL3lHFDNhVZfTK6U2gjVb7l8= +github.com/TyphonHill/go-mermaid v1.0.0 h1:VtmgQwgZA+KNHJvG/O591ibBVuDkGhg2+F/olVXnXAs= +github.com/TyphonHill/go-mermaid v1.0.0/go.mod h1:BqMEbKnr2HHpZ4lJJvGjL47v6rZAUpJcOaE/db1Ppwc= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= From 796268f130bc22b1d0eeef6aa380ee5754999c18 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Thu, 9 Oct 2025 15:40:29 -0300 Subject: [PATCH 15/45] fix: bump nix hash --- cmd/chainlink-ton/lock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index a214735b5..3579ceb2c 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `nix-lock-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-IDxbmr//NcGL1hhH2v9CyokV3HvWSzwNyzuWBYChW4A="; + chainlink-ton = "sha256-EviBTKmwemqtxJdgB9KE8i+WqSsKZUERz7UF2pvcS5g="; } From 9d7c1e71f8373810b5fb2c7ac34af50f580e4e79 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Thu, 9 Oct 2025 15:49:41 -0300 Subject: [PATCH 16/45] fix: bump contract version --- contracts/contracts/ccip/ccipsend_executor/contract.tolk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 471499262..cf4698574 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -8,7 +8,7 @@ import "../onramp/types" import "../common/messages" import "../../lib/utils" -const CONTRACT_VERSION = "0.0.3"; +const CONTRACT_VERSION = "0.0.4"; const FACILITY_NAME = "com.chainlink.ton.ccip.CCIPSendExecutor"; fun onInternalMessage(in: InMessage) { From b5fdd34f7e3f7a7084b31fda286f82eeee38dd63 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Thu, 9 Oct 2025 16:20:43 -0300 Subject: [PATCH 17/45] fix: golint --- cmd/explorer/main.go | 19 ++-- .../ccip/{common => ccipcommon}/common.go | 2 +- pkg/ton/debug/decoders/ccip/onramp/onramp.go | 5 +- pkg/ton/debug/explorer/explorer.go | 98 ++++++++++++------- pkg/ton/debug/explorer/utils.go | 3 +- pkg/ton/debug/lib/writer.go | 1 + .../visualizations/sequence/sanitizer.go | 9 +- .../sequence/sequence_diagram.go | 11 ++- 8 files changed, 87 insertions(+), 61 deletions(-) rename pkg/ton/debug/decoders/ccip/{common => ccipcommon}/common.go (99%) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 04f7519c7..ecdc603d8 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -3,6 +3,7 @@ package main import ( "context" "encoding/hex" + "errors" "fmt" "os" "strings" @@ -38,7 +39,7 @@ Arguments: url tonscan TX URL`, Args: func(cmd *cobra.Command, args []string) error { if len(args) != 1 && len(args) != 2 { - return fmt.Errorf("requires 1 argument (URL) or 2 arguments (
)") + return errors.New("requires 1 argument (URL) or 2 arguments (
)") } return nil }, @@ -50,20 +51,20 @@ Arguments: txHash, address, parsedNet, parseURLErr = explorer.ParseURL(urlOrTx) if parseURLErr == nil { if cmd.Root().Flags().Changed("net") { - return fmt.Errorf("cannot specify network flag when using URL") + return errors.New("cannot specify network flag when using URL") } net = parsedNet } else { // Not a URL, treat as tx-hash - if len(urlOrTx) == 64 || (len(urlOrTx) == 66 && strings.HasPrefix(urlOrTx, "0x")) { - _, err := hex.DecodeString(strings.TrimPrefix(urlOrTx, "0x")) - if err != nil { - return fmt.Errorf("invalid transaction hash or url: %w", err) - } - txHash = urlOrTx - } else { + if len(urlOrTx) != 64 && (len(urlOrTx) != 66 || !strings.HasPrefix(urlOrTx, "0x")) { return fmt.Errorf("failed to parse URL: %w", parseURLErr) } + + _, err := hex.DecodeString(strings.TrimPrefix(urlOrTx, "0x")) + if err != nil { + return fmt.Errorf("invalid transaction hash or url: %w", err) + } + txHash = urlOrTx } if len(args) == 2 { diff --git a/pkg/ton/debug/decoders/ccip/common/common.go b/pkg/ton/debug/decoders/ccip/ccipcommon/common.go similarity index 99% rename from pkg/ton/debug/decoders/ccip/common/common.go rename to pkg/ton/debug/decoders/ccip/ccipcommon/common.go index 61d626f7b..f43458673 100644 --- a/pkg/ton/debug/decoders/ccip/common/common.go +++ b/pkg/ton/debug/decoders/ccip/ccipcommon/common.go @@ -1,4 +1,4 @@ -package common +package ccipcommon import ( "github.com/xssnick/tonutils-go/address" diff --git a/pkg/ton/debug/decoders/ccip/onramp/onramp.go b/pkg/ton/debug/decoders/ccip/onramp/onramp.go index 029f969e1..43fd99978 100644 --- a/pkg/ton/debug/decoders/ccip/onramp/onramp.go +++ b/pkg/ton/debug/decoders/ccip/onramp/onramp.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/decoders/ccip/ccipcommon" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/lib" "github.com/smartcontractkit/chainlink-ton/pkg/ton/event" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" @@ -35,7 +35,6 @@ func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.Messa return nil, &lib.UnknownMessageError{} } if topic == onramp.TopicCCIPMessageSent { - ccipMessageSent, err := onramp.Builder.Events.CCIPMessageSent.Decode(msg.BeginParse()) if err != nil { return nil, err @@ -103,5 +102,5 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) { - return common.NewDecoder().ExitCodeInfo(exitCode) + return ccipcommon.NewDecoder().ExitCodeInfo(exitCode) } diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 4757ea6e0..467fa055a 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -4,8 +4,11 @@ import ( "context" "encoding/hex" "encoding/json" + "errors" "fmt" "net/http" + "net/url" + "time" "github.com/Masterminds/semver/v3" "github.com/xssnick/tonutils-go/address" @@ -14,6 +17,7 @@ import ( "github.com/xssnick/tonutils-go/ton" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" @@ -154,7 +158,7 @@ func (c *client) queryActorsReceivedRec(ctx context.Context, block *ton.BlockIDE return err } } - fmt.Println(fmt.Errorf("unknown message type").Error()) + fmt.Println(errors.New("unknown message type").Error()) return nil } @@ -232,43 +236,61 @@ func (c *client) tryMatchByCodeHash(ctx context.Context, block *ton.BlockIDExt, } func (c *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { - if c.net == "mainnet" || c.net == "testnet" { - // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr - var apiURL string - if c.net == "mainnet" { - apiURL = "https://toncenter.com/api/v3/transactions?hash=" + txHashStr - } else { - apiURL = "https://testnet.toncenter.com/api/v3/transactions?hash=" + txHashStr - } - type txResult struct { - Account string `json:"account"` - } - type apiResponse struct { - Transactions []txResult `json:"transactions"` - } - resp, err := http.Get(apiURL) - if err != nil { - return nil, fmt.Errorf("failed to fetch transaction info from toncenter: %w", err) - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("unexpected status code from toncenter: %d", resp.StatusCode) - } - var respData apiResponse - err = json.NewDecoder(resp.Body).Decode(&respData) - if err != nil { - return nil, fmt.Errorf("failed to decode toncenter response: %w", err) - } - if len(respData.Transactions) != 1 { - return nil, fmt.Errorf("transaction not found in toncenter response") - } - addr, err := address.ParseRawAddr(respData.Transactions[0].Account) - if err != nil { - return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) - } - return addr, nil + // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr + var baseURL string + switch c.net { + case "mainnet": + baseURL = "https://toncenter.com/api/v3/transactions" + case "testnet": + baseURL = "https://testnet.toncenter.com/api/v3/transactions" + default: + return nil, fmt.Errorf("unsupported network: %s", c.net) + } + type txResult struct { + Account string `json:"account"` + } + type apiResponse struct { + Transactions []txResult `json:"transactions"` + } + // Use url.URL for safer URL construction + u, err := url.Parse(baseURL) + if err != nil { + return nil, fmt.Errorf("invalid base URL: %w", err) + } + + // Add query parameters safely + q := u.Query() + q.Set("hash", txHashStr) // No need for manual encoding when using url.Values + u.RawQuery = q.Encode() + + // Create request with context and timeout + client := &http.Client{Timeout: 30 * time.Second} + req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to fetch transaction info from toncenter: %w", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code from toncenter: %d", resp.StatusCode) + } + var respData apiResponse + err = json.NewDecoder(resp.Body).Decode(&respData) + if err != nil { + return nil, fmt.Errorf("failed to decode toncenter response: %w", err) + } + if len(respData.Transactions) != 1 { + return nil, errors.New("transaction not found in toncenter response") + } + addr, err := address.ParseRawAddr(respData.Transactions[0].Account) + if err != nil { + return nil, fmt.Errorf("failed to parse source address from toncenter response: %w", err) } - return nil, fmt.Errorf("source address is required for non-mainnet/testnet networks") + return addr, nil } func (c *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *address.Address, txHash []byte) (*tlb.Transaction, error) { @@ -299,7 +321,7 @@ func (c *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *addres maxLT = last.PrevTxLT maxHash = last.PrevTxHash } - return nil, fmt.Errorf("transaction not found") + return nil, errors.New("transaction not found") } func equalHash(a, b []byte) bool { diff --git a/pkg/ton/debug/explorer/utils.go b/pkg/ton/debug/explorer/utils.go index ac438a3cc..16aaba063 100644 --- a/pkg/ton/debug/explorer/utils.go +++ b/pkg/ton/debug/explorer/utils.go @@ -1,6 +1,7 @@ package explorer import ( + "errors" "fmt" "net/url" "strings" @@ -31,5 +32,5 @@ func ParseURL(urlStr string) (txHash, address, network string, err error) { } } - return "", "", "", fmt.Errorf("unsupported URL format") + return "", "", "", errors.New("unsupported URL format") } diff --git a/pkg/ton/debug/lib/writer.go b/pkg/ton/debug/lib/writer.go index ca97ec17d..a6fba08ae 100644 --- a/pkg/ton/debug/lib/writer.go +++ b/pkg/ton/debug/lib/writer.go @@ -2,6 +2,7 @@ package lib import ( cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + tt "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) diff --git a/pkg/ton/debug/visualizations/sequence/sanitizer.go b/pkg/ton/debug/visualizations/sequence/sanitizer.go index 7b49aeb3a..0ec332712 100644 --- a/pkg/ton/debug/visualizations/sequence/sanitizer.go +++ b/pkg/ton/debug/visualizations/sequence/sanitizer.go @@ -6,7 +6,7 @@ import ( ) func sanitizeString(s string) string { - var wrapWidth int = 80 + var wrapWidth = 80 description := wrap(s, wrapWidth) description = strings.ReplaceAll(description, "\n", "
") description = strings.ReplaceAll(description, "\"", "'") @@ -60,16 +60,17 @@ func wrap(s string, width int) string { wLen = utf8.RuneCountInString(w) } - if lineRunes == 0 { + switch { + case lineRunes == 0: // start a new line line.WriteString(w) lineRunes = wLen - } else if lineRunes+1+wLen <= width { + case lineRunes+1+wLen <= width: // add to current line with a space line.WriteByte(' ') line.WriteString(w) lineRunes += 1 + wLen - } else { + default: // wrap flush() line.WriteString(w) diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 98f793f6e..1f927f6d2 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -53,13 +53,14 @@ func (v *visualization) NewSentMessage(msg *tt.SentMessage, info lib.MessageInfo func (v *visualization) insertMsg(from, to *address.Address, description string) lib.DebuggerVisualization { description = sanitizeString(description) - if from != nil && to != nil { + switch { + case from != nil && to != nil: v.Diagram.AddMessage(v.actorFromAddr(from), v.actorFromAddr(to), sequence.MessageSolidArrow, description) - } else if from != nil && to == nil { + case from != nil && to == nil: v.Diagram.AddMessage(v.actorFromAddr(from), sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.MessageSolidArrow, description) - } else if from == nil && to != nil { + case from == nil && to != nil: v.Diagram.AddMessage(sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), v.actorFromAddr(to), sequence.MessageSolidArrow, description) - } else { + default: v.Diagram.AddMessage(sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.NewActor("unknown", "unknown", sequence.ActorParticipant), sequence.MessageSolidArrow, description) } return v @@ -76,7 +77,7 @@ func (v *visualization) actorFromAddr(addr *address.Address) *sequence.Actor { var actor *sequence.Actor var ok bool name := v.describeAddr(addr) - id := strings.Replace(addr.StringRaw(), ":", "_", -1) + id := strings.ReplaceAll(addr.StringRaw(), ":", "_") if actor, ok = v.ActiveActors[id]; !ok { actor = v.Diagram.AddActor(id, name, sequence.ActorParticipant) v.ActiveActors[id] = actor From c61402d21a55a3493ffc790c2fe61d590378da10 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 09:10:55 -0300 Subject: [PATCH 18/45] fix: false error --- pkg/ton/debug/explorer/explorer.go | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 467fa055a..9aa5e2a68 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -145,21 +145,16 @@ func (c *client) queryActorsReceivedRec(ctx context.Context, block *ton.BlockIDE return err } err = c.queryOutgoingMessages(ctx, block, message.OutgoingInternalSentMessages, message.OutgoingInternalReceivedMessages, knownActors, visited) - if err != nil { - return err - } + return err } else if message.ExternalMsg != nil { err := c.queryActorIfNotVisited(ctx, block, message.ExternalMsg.DstAddr, knownActors, visited) if err != nil { return err } err = c.queryOutgoingMessages(ctx, block, message.OutgoingInternalSentMessages, message.OutgoingInternalReceivedMessages, knownActors, visited) - if err != nil { - return err - } + return err } - fmt.Println(errors.New("unknown message type").Error()) - return nil + return fmt.Errorf("unknown message type: %+v", message) } func (c *client) queryOutgoingMessages(ctx context.Context, block *ton.BlockIDExt, outgoingSentMessages []*tracetracking.SentMessage, outgoingReceivedMessages []*tracetracking.ReceivedMessage, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { From 9643466483ed9cccd6d85dadd39b0db6372982fa Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 09:53:32 -0300 Subject: [PATCH 19/45] feat: url encoding in explorer --- cmd/explorer/main.go | 29 +++++++++++++- pkg/ton/debug/explorer/explorer.go | 23 +++++++++-- pkg/ton/debug/pretty_print.go | 4 +- pkg/ton/debug/sequencediagram.go | 5 --- .../sequence/sequence_diagram.go | 39 ++++++++++++++++++- 5 files changed, 85 insertions(+), 15 deletions(-) delete mode 100644 pkg/ton/debug/sequencediagram.go diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index ecdc603d8..050222a5e 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -20,6 +20,7 @@ var ( verbose bool pageSize uint32 maxPages uint32 + visualization string format string ) @@ -76,7 +77,11 @@ Arguments: if parseURLErr != nil { return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) } - parseURLErr = client.PrintTrace(ctx, txHash, address, format) + explorerFormat, err := parseFormat(visualization, format) + if err != nil { + return fmt.Errorf("failed to parse format: %w", err) + } + parseURLErr = client.PrintTrace(ctx, txHash, address, explorerFormat) if parseURLErr != nil { return fmt.Errorf("failed to execute trace: %w", parseURLErr) } @@ -84,9 +89,29 @@ Arguments: }, } +func parseFormat(visualization string, format string) (explorer.Format, error) { + switch visualization { + case "tree": + if format != "" { + return explorer.Format(0), fmt.Errorf("format option is not applicable for tree visualization") + } + return explorer.FormatTree, nil + case "sequence": + switch format { + case "", "url": + return explorer.FormatSequenceURL, nil + case "raw": + return explorer.FormatSequenceRaw, nil + } + return explorer.Format(0), fmt.Errorf("invalid sequence format: %s", format) + } + return explorer.Format(0), fmt.Errorf("invalid visualization format: %s", format) +} + func init() { rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (optional if provided as argument)") - rootCmd.Flags().StringVarP(&format, "format", "f", "", "Visualization format (tree or sequence)") + rootCmd.Flags().StringVarP(&visualization, "visualization", "V", "sequence", "Visualization format (sequence or tree)") + rootCmd.Flags().StringVarP(&format, "format", "f", "", "Sequence visualization format (url or raw) (only for sequence visualization)") rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 9aa5e2a68..fbb62080b 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/visualizations/sequence" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) @@ -53,6 +54,14 @@ type client struct { maxPages uint32 } +type Format int + +const ( + FormatTree Format = iota + FormatSequenceURL + FormatSequenceRaw +) + // PrintTrace connects to the specified TON network, retrieves the transaction // by the given source address and transaction hash, and prints the full execution // trace of the transaction, including all outgoing messages and their subsequent @@ -60,8 +69,9 @@ type client struct { // // Parameters: // - ctx: The context for managing request deadlines and cancellation. +// - txHashStr: The transaction hash in hexadecimal format. // - srcAddresstr: The source address of the transaction in string format. -func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, visualization string) error { +func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, format Format) error { var senderAddr *address.Address var err error if srcAddresstr == "" { @@ -115,10 +125,15 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr fmt.Println("full trace received:") var debugger debug.DebuggerEnvironment - if visualization == "sequence" { - debugger = debug.NewDebuggerSequenceTrace(knownActors) - } else { + switch format { + case FormatSequenceURL: + debugger = debug.NewDebuggerSequenceTrace(knownActors, sequence.OutputFmtURL) + case FormatSequenceRaw: + debugger = debug.NewDebuggerSequenceTrace(knownActors, sequence.OutputFmtRaw) + case FormatTree: debugger = debug.NewDebuggerTreeTrace(knownActors) + default: + return errors.New("unknown format") } fmt.Println(debugger.DumpReceived(&recvMsg, c.verbose)) diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go index 7b873f8fb..5c392742d 100644 --- a/pkg/ton/debug/pretty_print.go +++ b/pkg/ton/debug/pretty_print.go @@ -52,12 +52,12 @@ func NewDebuggerTreeTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvi } } -func NewDebuggerSequenceTrace(addresses map[string]cldf.TypeAndVersion) DebuggerEnvironment { +func NewDebuggerSequenceTrace(addresses map[string]cldf.TypeAndVersion, outputFmt sequence.OutputFmt) DebuggerEnvironment { return DebuggerEnvironment{ existingAddresses: addresses, contracts: defaultDecoders(), writerFactory: func(d DebuggerEnvironment) lib.DebuggerVisualization { - writer := sequence.NewVisualization() + writer := sequence.NewVisualization(outputFmt) for addr, typeAndVersion := range d.existingAddresses { writer.NewActor(addr, typeAndVersion.Type, "") } diff --git a/pkg/ton/debug/sequencediagram.go b/pkg/ton/debug/sequencediagram.go deleted file mode 100644 index 3de795d6a..000000000 --- a/pkg/ton/debug/sequencediagram.go +++ /dev/null @@ -1,5 +0,0 @@ -package debug - -type SequenceDiagram struct { - Actors map[string]string // address -> name -} diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 1f927f6d2..f7b03e18a 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -1,7 +1,11 @@ package sequence import ( + "bytes" + "compress/zlib" + "encoding/base64" "fmt" + "net/url" "strings" "github.com/xssnick/tonutils-go/address" @@ -19,9 +23,17 @@ type visualization struct { Actors map[string]string // address -> name ActiveActors map[string]*sequence.Actor Diagram *sequence.Diagram + Format OutputFmt } -func NewVisualization() lib.DebuggerVisualization { +type OutputFmt int + +const ( + OutputFmtURL OutputFmt = iota + OutputFmtRaw +) + +func NewVisualization(fmt OutputFmt) lib.DebuggerVisualization { diagram := sequence.NewDiagram() diagram.Config.SetMessageAlign("left") diagram.Config.SetNoteAlign("left") @@ -29,11 +41,34 @@ func NewVisualization() lib.DebuggerVisualization { Actors: make(map[string]string), ActiveActors: make(map[string]*sequence.Actor), Diagram: diagram, + Format: fmt, } } func (v *visualization) ToString() string { - return v.Diagram.String() + diagramStr := v.Diagram.String() + switch v.Format { + case v.Format: + // Compress with zlib and base64 encode + var buf bytes.Buffer + w := zlib.NewWriter(&buf) + _, err := w.Write([]byte(diagramStr)) + if err != nil { + return "failed to write to zlib writer: " + err.Error() + } + err = w.Close() + if err != nil { + return "failed to close zlib writer: " + err.Error() + } + zlibEncodedDiagram := base64.StdEncoding.EncodeToString(buf.Bytes()) + + mermaidURL := "https://www.mermaidchart.com/play#pako:" + url.PathEscape(zlibEncodedDiagram) + return mermaidURL + case OutputFmtRaw: + return diagramStr + default: + return "unknown format" + } } func (v *visualization) NewActor(address string, contractType deployment.ContractType, name string) { From e7b4b7c49edbbfffbfec27574055372f825d54f8 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 10:52:53 -0300 Subject: [PATCH 20/45] feat: expose generate cmd --- cmd/explorer/main.go | 112 +---------------------------- pkg/ton/debug/explorer/explorer.go | 111 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 111 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 050222a5e..f715cf54e 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -1,123 +1,13 @@ package main import ( - "context" - "encoding/hex" - "errors" "fmt" "os" - "strings" - - "github.com/spf13/cobra" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) -var ( - destAddressStr string - txHashStr string - net string - verbose bool - pageSize uint32 - maxPages uint32 - visualization string - format string -) - -var rootCmd = &cobra.Command{ - Use: "explorer
| ", - Short: "TON blockchain explorer and trace analyzer", - Long: `A command-line tool for exploring TON blockchain transactions and analyzing traces. -This tool helps debug and understand transaction flows on the TON network. - -Usage: - explorer
- Analyze transaction with address and hash - explorer - Analyze transaction from URL - -Arguments: - address Destination address in base64 - tx-hash Transaction hash in hex - url tonscan TX URL`, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 && len(args) != 2 { - return errors.New("requires 1 argument (URL) or 2 arguments (
)") - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - var txHash, address, parsedNet string - - urlOrTx := args[0] - var parseURLErr error - txHash, address, parsedNet, parseURLErr = explorer.ParseURL(urlOrTx) - if parseURLErr == nil { - if cmd.Root().Flags().Changed("net") { - return errors.New("cannot specify network flag when using URL") - } - net = parsedNet - } else { - // Not a URL, treat as tx-hash - if len(urlOrTx) != 64 && (len(urlOrTx) != 66 || !strings.HasPrefix(urlOrTx, "0x")) { - return fmt.Errorf("failed to parse URL: %w", parseURLErr) - } - - _, err := hex.DecodeString(strings.TrimPrefix(urlOrTx, "0x")) - if err != nil { - return fmt.Errorf("invalid transaction hash or url: %w", err) - } - txHash = urlOrTx - } - - if len(args) == 2 { - address = args[1] - } - - ctx := context.Background() - client, parseURLErr := explorer.Connect(net, verbose, pageSize, maxPages) - if parseURLErr != nil { - return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) - } - explorerFormat, err := parseFormat(visualization, format) - if err != nil { - return fmt.Errorf("failed to parse format: %w", err) - } - parseURLErr = client.PrintTrace(ctx, txHash, address, explorerFormat) - if parseURLErr != nil { - return fmt.Errorf("failed to execute trace: %w", parseURLErr) - } - return nil - }, -} - -func parseFormat(visualization string, format string) (explorer.Format, error) { - switch visualization { - case "tree": - if format != "" { - return explorer.Format(0), fmt.Errorf("format option is not applicable for tree visualization") - } - return explorer.FormatTree, nil - case "sequence": - switch format { - case "", "url": - return explorer.FormatSequenceURL, nil - case "raw": - return explorer.FormatSequenceRaw, nil - } - return explorer.Format(0), fmt.Errorf("invalid sequence format: %s", format) - } - return explorer.Format(0), fmt.Errorf("invalid visualization format: %s", format) -} - -func init() { - rootCmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (optional if provided as argument)") - rootCmd.Flags().StringVarP(&visualization, "visualization", "V", "sequence", "Visualization format (sequence or tree)") - rootCmd.Flags().StringVarP(&format, "format", "f", "", "Sequence visualization format (url or raw) (only for sequence visualization)") - rootCmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") - rootCmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") - rootCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") - rootCmd.Flags().Uint32VarP(&pageSize, "page-size", "s", 10, "Number of blocks to fetch per page") - rootCmd.Flags().Uint32VarP(&maxPages, "max-pages", "p", 10, "Maximum number of pages to fetch") -} +var rootCmd = explorer.GenerateExplorerCmd() func main() { if err := rootCmd.Execute(); err != nil { diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index fbb62080b..ceb615287 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -8,9 +8,11 @@ import ( "fmt" "net/http" "net/url" + "strings" "time" "github.com/Masterminds/semver/v3" + "github.com/spf13/cobra" "github.com/xssnick/tonutils-go/address" "github.com/xssnick/tonutils-go/liteclient" "github.com/xssnick/tonutils-go/tlb" @@ -24,6 +26,115 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) +func GenerateExplorerCmd() *cobra.Command { + + var ( + destAddressStr string + txHashStr string + net string + verbose bool + pageSize uint32 + maxPages uint32 + visualization string + format string + ) + + cmd := &cobra.Command{ + Use: "explorer
| ", + Short: "TON blockchain explorer and trace analyzer", + Long: `A command-line tool for exploring TON blockchain transactions and analyzing traces. +This tool helps debug and understand transaction flows on the TON network. + +Usage: + explorer
- Analyze transaction with address and hash + explorer - Analyze transaction from URL + +Arguments: + address Destination address in base64 + tx-hash Transaction hash in hex + url tonscan TX URL`, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 && len(args) != 2 { + return errors.New("requires 1 argument (URL) or 2 arguments (
)") + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + var txHash, address, parsedNet string + + urlOrTx := args[0] + var parseURLErr error + txHash, address, parsedNet, parseURLErr = ParseURL(urlOrTx) + if parseURLErr == nil { + if cmd.Root().Flags().Changed("net") { + return errors.New("cannot specify network flag when using URL") + } + net = parsedNet + } else { + // Not a URL, treat as tx-hash + if len(urlOrTx) != 64 && (len(urlOrTx) != 66 || !strings.HasPrefix(urlOrTx, "0x")) { + return fmt.Errorf("failed to parse URL: %w", parseURLErr) + } + + _, err := hex.DecodeString(strings.TrimPrefix(urlOrTx, "0x")) + if err != nil { + return fmt.Errorf("invalid transaction hash or url: %w", err) + } + txHash = urlOrTx + } + + if len(args) == 2 { + address = args[1] + } + + ctx := context.Background() + client, parseURLErr := Connect(net, verbose, pageSize, maxPages) + if parseURLErr != nil { + return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) + } + explorerFormat, err := parseFormat(visualization, format) + if err != nil { + return fmt.Errorf("failed to parse format: %w", err) + } + parseURLErr = client.PrintTrace(ctx, txHash, address, explorerFormat) + if parseURLErr != nil { + return fmt.Errorf("failed to execute trace: %w", parseURLErr) + } + return nil + }, + } + + cmd.Flags().StringVarP(&destAddressStr, "address", "a", "", "Destination address in base64 (optional if provided as argument)") + cmd.Flags().StringVarP(&visualization, "visualization", "V", "sequence", "Visualization format (sequence or tree)") + cmd.Flags().StringVarP(&format, "format", "f", "", "Sequence visualization format (url or raw) (only for sequence visualization)") + cmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") + cmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") + cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") + cmd.Flags().Uint32VarP(&pageSize, "page-size", "s", 10, "Number of blocks to fetch per page") + cmd.Flags().Uint32VarP(&maxPages, "max-pages", "p", 10, "Maximum number of pages to fetch") + + return cmd +} + +func parseFormat(visualization string, format string) (Format, error) { + switch visualization { + case "tree": + if format != "" { + return Format(0), fmt.Errorf("format option is not applicable for tree visualization") + } + return FormatTree, nil + case "sequence": + switch format { + case "", "url": + return FormatSequenceURL, nil + case "raw": + return FormatSequenceRaw, nil + } + return Format(0), fmt.Errorf("invalid sequence format: %s", format) + } + return Format(0), fmt.Errorf("invalid visualization format: %s", format) +} + // Connect establishes a connection to the specified TON network and returns an // explorer instance for tracing transactions. // From c31306aac440ed96aa011e00296a50acddf1aac2 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 18:34:14 -0300 Subject: [PATCH 21/45] feat: admint actor map in command --- cmd/explorer/main.go | 3 ++- pkg/ton/debug/explorer/explorer.go | 17 ++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index f715cf54e..7e3421600 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -4,10 +4,11 @@ import ( "fmt" "os" + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) -var rootCmd = explorer.GenerateExplorerCmd() +var rootCmd = explorer.GenerateExplorerCmd(map[string]deployment.TypeAndVersion{}) func main() { if err := rootCmd.Execute(); err != nil { diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index ceb615287..b66e75da0 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -26,7 +26,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) -func GenerateExplorerCmd() *cobra.Command { +func GenerateExplorerCmd(contracts map[string]deployment.TypeAndVersion) *cobra.Command { var ( destAddressStr string @@ -88,17 +88,17 @@ Arguments: } ctx := context.Background() - client, parseURLErr := Connect(net, verbose, pageSize, maxPages) - if parseURLErr != nil { - return fmt.Errorf("failed to initialize explorer: %w", parseURLErr) + client, err := Connect(net, verbose, pageSize, maxPages) + if err != nil { + return fmt.Errorf("failed to initialize explorer: %w", err) } explorerFormat, err := parseFormat(visualization, format) if err != nil { return fmt.Errorf("failed to parse format: %w", err) } - parseURLErr = client.PrintTrace(ctx, txHash, address, explorerFormat) - if parseURLErr != nil { - return fmt.Errorf("failed to execute trace: %w", parseURLErr) + err = client.PrintTrace(ctx, txHash, address, explorerFormat, contracts) + if err != nil { + return fmt.Errorf("failed to execute trace: %w", err) } return nil }, @@ -182,7 +182,7 @@ const ( // - ctx: The context for managing request deadlines and cancellation. // - txHashStr: The transaction hash in hexadecimal format. // - srcAddresstr: The source address of the transaction in string format. -func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, format Format) error { +func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, format Format, knownActors map[string]deployment.TypeAndVersion) error { var senderAddr *address.Address var err error if srcAddresstr == "" { @@ -225,7 +225,6 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr if err != nil { return fmt.Errorf("failed to wait for trace: %w", err) } - knownActors := map[string]deployment.TypeAndVersion{} // TODO fill from cld address book fmt.Println("querying actors") err = c.queryActors(ctx, &recvMsg, knownActors) From 1677c00670c32d31a1f6611436d5404e1ac1d790 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 18:57:37 -0300 Subject: [PATCH 22/45] test --- cmd/explorer/main.go | 4 +++- go.mod | 1 + go.sum | 2 ++ pkg/ton/debug/explorer/explorer.go | 23 +++++++++---------- .../sequence/sequence_diagram.go | 3 +++ 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index 7e3421600..fa7468b22 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -4,11 +4,13 @@ import ( "fmt" "os" + "github.com/smartcontractkit/wsrpc/logger" + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) -var rootCmd = explorer.GenerateExplorerCmd(map[string]deployment.TypeAndVersion{}) +var rootCmd = explorer.GenerateExplorerCmd(logger.DefaultLogger, map[string]deployment.TypeAndVersion{}) func main() { if err := rootCmd.Execute(); err != nil { diff --git a/go.mod b/go.mod index 9ee6b5830..af195f2a3 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d + github.com/smartcontractkit/wsrpc v0.8.4 github.com/spf13/cobra v1.10.1 github.com/stretchr/testify v1.11.1 github.com/xssnick/tonutils-go v1.14.1 diff --git a/go.sum b/go.sum index c6c0a2b19..54a4a51cd 100644 --- a/go.sum +++ b/go.sum @@ -613,6 +613,8 @@ github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d h1:/0/80Ic github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d/go.mod h1:Acy3BTBxou83ooMESLO90s8PKSu7RvLCzwSTbxxfOK0= github.com/smartcontractkit/mcms v0.25.0 h1:GTkG6jQ2CYoVQFKkRQnA42IvUrR4gObeHqwrQNRhmGM= github.com/smartcontractkit/mcms v0.25.0/go.mod h1:7v5DNfWqIS81nISbuFBrlV1QHZfD+pFQzjsxqqhcK9o= +github.com/smartcontractkit/wsrpc v0.8.4 h1:pgNfTzq2tr3gs2ztP3x12+sUckyIo4Pms04508U5544= +github.com/smartcontractkit/wsrpc v0.8.4/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index b66e75da0..dfec3669f 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -18,6 +18,8 @@ import ( "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/ton" + "github.com/smartcontractkit/wsrpc/logger" + "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" @@ -26,7 +28,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) -func GenerateExplorerCmd(contracts map[string]deployment.TypeAndVersion) *cobra.Command { +func GenerateExplorerCmd(lggr logger.Logger, contracts map[string]deployment.TypeAndVersion) *cobra.Command { var ( destAddressStr string @@ -158,6 +160,7 @@ func Connect(net string, verbose bool, pageSize uint32, maxPages uint32) (*clien } type client struct { + lggr logger.Logger connection *ton.APIClient net string verbose bool @@ -186,16 +189,12 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr var senderAddr *address.Address var err error if srcAddresstr == "" { - if c.verbose { - fmt.Println("source address not provided, attempting to fetch from toncenter by hash...") - } + c.lggr.Debug("source address not provided, attempting to fetch from toncenter by hash...") senderAddr, err = c.GetSenderAddressFromTxHash(ctx, txHashStr) if err != nil { return fmt.Errorf("failed to get sender address from tx hash: %w", err) } - if c.verbose { - fmt.Println("source address found:", senderAddr.String()) - } + c.lggr.Debug("source address found:", senderAddr.String()) } else { senderAddr, err = address.ParseAddr(srcAddresstr) if err != nil { @@ -212,27 +211,27 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr return err } - fmt.Println("tx found in lt:", tx.LT) + c.lggr.Info("tx found in lt:", tx.LT) recvMsg, err := tracetracking.MapToReceivedMessage(tx) if err != nil { return fmt.Errorf("failed to map transaction to received message: %w", err) } - fmt.Println("waiting for full trace...") + c.lggr.Info("waiting for full trace...") err = recvMsg.WaitForTrace(c.connection) if err != nil { return fmt.Errorf("failed to wait for trace: %w", err) } - fmt.Println("querying actors") + c.lggr.Info("querying actors") err = c.queryActors(ctx, &recvMsg, knownActors) if err != nil { return fmt.Errorf("failed to query actors: %w", err) } - fmt.Println("full trace received:") + c.lggr.Info("full trace received:") var debugger debug.DebuggerEnvironment switch format { @@ -245,7 +244,7 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr default: return errors.New("unknown format") } - fmt.Println(debugger.DumpReceived(&recvMsg, c.verbose)) + c.lggr.Info(debugger.DumpReceived(&recvMsg, c.verbose)) return nil } diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index f7b03e18a..5b74cc4df 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -72,6 +72,7 @@ func (v *visualization) ToString() string { } func (v *visualization) NewActor(address string, contractType deployment.ContractType, name string) { + fmt.Println("Registering actor:", address, contractType, name) if _, exists := v.Actors[address]; !exists { if name != "" { v.Actors[address] = name @@ -140,6 +141,8 @@ func (v *visualization) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib. func (v *visualization) describeAddr(addr *address.Address) string { addrStr := addr.String() + fmt.Println("looking for ", addrStr) + fmt.Println("in actors:", v.Actors) if name, exists := v.Actors[addrStr]; exists { return name } From 743921099f61cdde9788fbad3b00da544d598985 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 19:04:57 -0300 Subject: [PATCH 23/45] fix: missing lggr --- pkg/ton/debug/explorer/explorer.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index dfec3669f..a88b43d05 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -90,7 +90,7 @@ Arguments: } ctx := context.Background() - client, err := Connect(net, verbose, pageSize, maxPages) + client, err := Connect(lggr, net, verbose, pageSize, maxPages) if err != nil { return fmt.Errorf("failed to initialize explorer: %w", err) } @@ -145,12 +145,13 @@ func parseFormat(visualization string, format string) (Format, error) { // - verbose: Whether to enable verbose output. // - pageSize: The number of transactions to fetch per page. // - maxPages: The maximum number of pages to fetch. -func Connect(net string, verbose bool, pageSize uint32, maxPages uint32) (*client, error) { +func Connect(lggr logger.Logger, net string, verbose bool, pageSize uint32, maxPages uint32) (*client, error) { apiClient, err := connect(context.Background(), net) if err != nil { return nil, fmt.Errorf("failed to connect to network: %w", err) } return &client{ + lggr: lggr, connection: apiClient, net: net, verbose: verbose, From 5bf3b79f90bc0881eae3dd5225521ddeee7059d9 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 19:22:02 -0300 Subject: [PATCH 24/45] debug --- pkg/ton/debug/explorer/explorer.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index a88b43d05..5ae9268a8 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -303,13 +303,19 @@ func (c *client) queryOutgoingMessages(ctx context.Context, block *ton.BlockIDEx } func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDExt, addr *address.Address, knownActors map[string]deployment.TypeAndVersion, visited map[string]bool) error { + c.lggr.Debug("queryActorIfNotVisited", addr.String()) + c.lggr.Debug("visited:", visited) + c.lggr.Debug("knownActors:", knownActors) if visited[addr.String()] { + c.lggr.Debug("already visited", addr.String()) return nil } if _, known := knownActors[addr.String()]; known { visited[addr.String()] = true + c.lggr.Debug("actor found in knownActors", addr.String()) return nil } + c.lggr.Debug("actor not known") var typeVersion common.TypeAndVersion result, err := c.connection.RunGetMethod(ctx, block, addr, "typeAndVersion") defer func() { From 43bbf0f6c9e8ce36b96331984419209bc246a9ed Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 19:35:09 -0300 Subject: [PATCH 25/45] debug --- pkg/ton/debug/explorer/explorer.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 5ae9268a8..896f4c123 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -226,11 +226,13 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr return fmt.Errorf("failed to wait for trace: %w", err) } + c.lggr.Debug("actors before query:\n", knownActors) c.lggr.Info("querying actors") err = c.queryActors(ctx, &recvMsg, knownActors) if err != nil { return fmt.Errorf("failed to query actors: %w", err) } + c.lggr.Debug("actors after query:\n", knownActors) c.lggr.Info("full trace received:") From 2cd3a43b632612e665b4f86d1fbb8acb360b70ea Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 19:43:45 -0300 Subject: [PATCH 26/45] debug --- pkg/ton/debug/visualizations/sequence/sequence_diagram.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 5b74cc4df..173d0dcf5 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -115,6 +115,7 @@ func (v *visualization) actorFromAddr(addr *address.Address) *sequence.Actor { name := v.describeAddr(addr) id := strings.ReplaceAll(addr.StringRaw(), ":", "_") if actor, ok = v.ActiveActors[id]; !ok { + fmt.Println("adding active actor: ", id, "\n", name, "\n=====") actor = v.Diagram.AddActor(id, name, sequence.ActorParticipant) v.ActiveActors[id] = actor } From f3c72341f7f6466f32a7bb2d2af86a7f47a2fedc Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Fri, 10 Oct 2025 20:04:56 -0300 Subject: [PATCH 27/45] fix: format output --- pkg/ton/debug/explorer/explorer.go | 1 - pkg/ton/debug/visualizations/sequence/sequence_diagram.go | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 896f4c123..189ecfa4f 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -344,7 +344,6 @@ func (c *client) tryMatchByCodeHash(ctx context.Context, block *ton.BlockIDExt, } code := account.Code.ToBOC() codeHex := hex.EncodeToString(code) - // fmt.Println("querying actor by code hash", addr.String(), codeHex) switch codeHex { case "b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03": // https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/main/build/HighloadWalletV3.compiled.json knownActors[addr.String()] = deployment.TypeAndVersion{ diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 173d0dcf5..0dbd6662e 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -48,7 +48,7 @@ func NewVisualization(fmt OutputFmt) lib.DebuggerVisualization { func (v *visualization) ToString() string { diagramStr := v.Diagram.String() switch v.Format { - case v.Format: + case OutputFmtURL: // Compress with zlib and base64 encode var buf bytes.Buffer w := zlib.NewWriter(&buf) @@ -72,7 +72,6 @@ func (v *visualization) ToString() string { } func (v *visualization) NewActor(address string, contractType deployment.ContractType, name string) { - fmt.Println("Registering actor:", address, contractType, name) if _, exists := v.Actors[address]; !exists { if name != "" { v.Actors[address] = name @@ -115,7 +114,6 @@ func (v *visualization) actorFromAddr(addr *address.Address) *sequence.Actor { name := v.describeAddr(addr) id := strings.ReplaceAll(addr.StringRaw(), ":", "_") if actor, ok = v.ActiveActors[id]; !ok { - fmt.Println("adding active actor: ", id, "\n", name, "\n=====") actor = v.Diagram.AddActor(id, name, sequence.ActorParticipant) v.ActiveActors[id] = actor } @@ -142,8 +140,6 @@ func (v *visualization) DescribeReceivedMessage(m *tt.ReceivedMessage, info lib. func (v *visualization) describeAddr(addr *address.Address) string { addrStr := addr.String() - fmt.Println("looking for ", addrStr) - fmt.Println("in actors:", v.Actors) if name, exists := v.Actors[addrStr]; exists { return name } From 34f7d9c06cef5bb68524ee04070d9ccc2eccd7d0 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 12:00:19 -0300 Subject: [PATCH 28/45] fix: nix hash --- cmd/chainlink-ton/lock.nix | 2 +- go.sum | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index 3579ceb2c..77ad0e9dc 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `nix-lock-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-EviBTKmwemqtxJdgB9KE8i+WqSsKZUERz7UF2pvcS5g="; + chainlink-ton = "sha256-3p3kZFPhp3CfaB4T2UIMln+YhrOLNTvnhjWVu1ZOrWY="; } diff --git a/go.sum b/go.sum index 54a4a51cd..b78fba368 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,7 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= From 7be59f3c5470069b4a90c11df03c7d69548f5c5d Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 15:20:52 -0300 Subject: [PATCH 29/45] fix: url encoding --- .../sequence/sequence_diagram.go | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go index 0dbd6662e..3be9adb8a 100644 --- a/pkg/ton/debug/visualizations/sequence/sequence_diagram.go +++ b/pkg/ton/debug/visualizations/sequence/sequence_diagram.go @@ -4,8 +4,8 @@ import ( "bytes" "compress/zlib" "encoding/base64" + "encoding/json" "fmt" - "net/url" "strings" "github.com/xssnick/tonutils-go/address" @@ -49,10 +49,20 @@ func (v *visualization) ToString() string { diagramStr := v.Diagram.String() switch v.Format { case OutputFmtURL: + type objectFormat struct { + Code string `json:"code"` + } + object := objectFormat{ + Code: diagramStr, + } + jsonObject, err := json.Marshal(object) + if err != nil { + return "failed to marshal diagram to JSON: " + err.Error() + } // Compress with zlib and base64 encode - var buf bytes.Buffer - w := zlib.NewWriter(&buf) - _, err := w.Write([]byte(diagramStr)) + buf := bytes.NewBuffer([]byte{}) + w := zlib.NewWriter(buf) + _, err = w.Write(jsonObject) if err != nil { return "failed to write to zlib writer: " + err.Error() } @@ -60,9 +70,9 @@ func (v *visualization) ToString() string { if err != nil { return "failed to close zlib writer: " + err.Error() } - zlibEncodedDiagram := base64.StdEncoding.EncodeToString(buf.Bytes()) + zlibEncodedDiagram := base64.URLEncoding.EncodeToString(buf.Bytes()) - mermaidURL := "https://www.mermaidchart.com/play#pako:" + url.PathEscape(zlibEncodedDiagram) + mermaidURL := "https://www.mermaidchart.com/play#pako:" + zlibEncodedDiagram return mermaidURL case OutputFmtRaw: return diagramStr From 5e38d594c3bd9fcf095a4640661a6c8e95950698 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 15:23:03 -0300 Subject: [PATCH 30/45] feat: mylocalton port scan --- cmd/explorer/main.go | 2 +- deployment/ccip/cs_test_helpers.go | 3 + go.mod | 35 ++++++ go.sum | 30 ++++- pkg/ton/debug/explorer/explorer.go | 171 ++++++++++++++++++++++++++--- 5 files changed, 222 insertions(+), 19 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index fa7468b22..f5735298d 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -10,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) -var rootCmd = explorer.GenerateExplorerCmd(logger.DefaultLogger, map[string]deployment.TypeAndVersion{}) +var rootCmd = explorer.GenerateExplorerCmd(logger.DefaultLogger, map[string]deployment.TypeAndVersion{}, nil) func main() { if err := rootCmd.Execute(); err != nil { diff --git a/deployment/ccip/cs_test_helpers.go b/deployment/ccip/cs_test_helpers.go index c0c5a09c1..443fab9ce 100644 --- a/deployment/ccip/cs_test_helpers.go +++ b/deployment/ccip/cs_test_helpers.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" "testing" + "time" "github.com/smartcontractkit/chainlink-ton/deployment/ccip/sequence" "github.com/smartcontractkit/chainlink-ton/deployment/state" @@ -272,6 +273,8 @@ func SendTonRequest( return 0, nil, fmt.Errorf("failed to wait for trace: %w", err) } + time.Sleep(24 * time.Hour) // Wait for the message to be fully processed + event, err := waitForReceivedMsgFlatten(e, clientConn, receivedMsg) if err != nil { return 0, nil, fmt.Errorf("failed to get CCIPMessageSent from flattening received messages: %w", err) diff --git a/go.mod b/go.mod index af195f2a3..e00c38d56 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250930202440-88c08e65d960 github.com/smartcontractkit/chainlink-common v0.9.6-0.20251003171904-99a82a53b142 github.com/smartcontractkit/chainlink-deployments-framework v0.52.0 + github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.30 github.com/smartcontractkit/libocr v0.0.0-20250905115425-2785a5cee79d github.com/smartcontractkit/wsrpc v0.8.4 github.com/spf13/cobra v1.10.1 @@ -26,7 +27,9 @@ require ( ) require ( + dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/XSAM/otelsql v0.37.0 // indirect @@ -43,22 +46,34 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudevents/sdk-go/binding/format/protobuf/v2 v2.16.1 // indirect github.com/cloudevents/sdk-go/v2 v2.16.1 // indirect github.com/coder/websocket v1.8.13 // indirect github.com/consensys/gnark-crypto v0.18.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v1.0.0-rc.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v28.3.3+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/ebitengine/purego v0.8.4 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fbsobreira/gotron-sdk v0.0.0-20250403083053-2943ce8c759b // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect @@ -71,7 +86,9 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/go-resty/resty/v2 v2.16.3 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect @@ -105,29 +122,45 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect + github.com/magiconair/properties v1.8.10 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.1.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // 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 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.2.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.23.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/samber/lo v1.49.1 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v4 v4.25.5 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chainlink-aptos v0.0.0-20250905094443-ac02b032b32b // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a // indirect github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a // indirect @@ -145,6 +178,7 @@ require ( github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/supranational/blst v0.3.14 // indirect + github.com/testcontainers/testcontainers-go v0.38.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -159,6 +193,7 @@ require ( go.mongodb.org/mongo-driver v1.17.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect diff --git a/go.sum b/go.sum index b78fba368..e8b304a2b 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= @@ -74,7 +76,6 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= @@ -118,6 +119,7 @@ github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsW github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= @@ -129,6 +131,8 @@ github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cucumber/gherkin/go/v26 v26.2.0 h1:EgIjePLWiPeslwIWmNQ3XHcypPsWAHoMCz/YEBKP4GI= github.com/cucumber/gherkin/go/v26 v26.2.0/go.mod h1:t2GAPnB8maCT4lkHL99BDCVNzCh1d7dBhCLt150Nr/0= github.com/cucumber/godog v0.15.0 h1:51AL8lBXF3f0cyA5CV4TnJFCTHpgiy+1x1Hb3TtZUmo= @@ -231,6 +235,7 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -396,6 +401,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I= github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -440,12 +446,15 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= @@ -453,8 +462,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY= @@ -467,6 +476,8 @@ github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= @@ -550,10 +561,12 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= @@ -683,6 +696,7 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xssnick/tonutils-go v1.14.1 h1:zV/iVYl/h3hArS+tPsd9XrSFfGert3r21caMltPSeHg= github.com/xssnick/tonutils-go v1.14.1/go.mod h1:68xwWjpoGGqiTbLJ0gT63sKu1Z1moCnDLLzA+DKanIg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -791,6 +805,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -806,6 +821,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -824,6 +840,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -851,6 +868,7 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -859,15 +877,19 @@ golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= @@ -906,6 +928,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 189ecfa4f..8e0aceb27 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -8,6 +8,8 @@ import ( "fmt" "net/http" "net/url" + "os/exec" + "strconv" "strings" "time" @@ -28,7 +30,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) -func GenerateExplorerCmd(lggr logger.Logger, contracts map[string]deployment.TypeAndVersion) *cobra.Command { +func GenerateExplorerCmd(lggr logger.Logger, contracts map[string]deployment.TypeAndVersion, client *ton.APIClient) *cobra.Command { var ( destAddressStr string @@ -62,6 +64,9 @@ Arguments: return nil }, RunE: func(cmd *cobra.Command, args []string) error { + if client != nil && cmd.Flags().Changed("net") { + return errors.New("cannot specify network flag when using existing client") + } var txHash, address, parsedNet string urlOrTx := args[0] @@ -90,7 +95,7 @@ Arguments: } ctx := context.Background() - client, err := Connect(lggr, net, verbose, pageSize, maxPages) + client, err := Connect(lggr, client, net, verbose, pageSize, maxPages) if err != nil { return fmt.Errorf("failed to initialize explorer: %w", err) } @@ -137,6 +142,98 @@ func parseFormat(visualization string, format string) (Format, error) { return Format(0), fmt.Errorf("invalid visualization format: %s", format) } +// ContainerInspect represents the structure returned by docker inspect +type ContainerInspect struct { + ID string `json:"Id"` + State struct { + Running bool `json:"Running"` + } `json:"State"` + Config struct { + Image string `json:"Image"` + } `json:"Config"` + NetworkSettings struct { + Ports map[string][]struct { + HostIP string `json:"HostIp"` + HostPort string `json:"HostPort"` + } `json:"Ports"` + } `json:"NetworkSettings"` +} + +// findMylocaltonContainer finds a running mylocalton container and returns its ID +func findMylocaltonContainer(ctx context.Context) (string, error) { + cmd := exec.CommandContext(ctx, "docker", "ps", "--format", "{{.ID}}\t{{.Image}}", "--filter", "status=running") + output, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to list docker containers: %w", err) + } + + lines := strings.Split(strings.TrimSpace(string(output)), "\n") + for _, line := range lines { + if line == "" { + continue + } + parts := strings.Split(line, "\t") + if len(parts) != 2 { + continue + } + containerID := parts[0] + image := parts[1] + + // Look for mylocalton containers, but exclude explorer + if strings.Contains(image, "mylocalton-docker") && !strings.Contains(image, "mylocalton-docker-explorer") { + return containerID, nil + } + } + + return "", errors.New("no running mylocalton container found") +} + +// inspectContainer runs docker inspect on the given container ID +func inspectContainer(ctx context.Context, containerID string) (*ContainerInspect, error) { + cmd := exec.CommandContext(ctx, "docker", "inspect", containerID) + output, err := cmd.CombinedOutput() + if err != nil { + if strings.Contains(string(output), "No such object") || strings.Contains(string(output), "No such container") { + return nil, fmt.Errorf("container %s does not exist", containerID) + } + return nil, fmt.Errorf("docker inspect failed: %w\nOutput: %s", err, string(output)) + } + + var inspects []ContainerInspect + if err := json.Unmarshal(output, &inspects); err != nil { + return nil, fmt.Errorf("failed to parse docker inspect output: %w", err) + } + + if len(inspects) == 0 { + return nil, fmt.Errorf("container %s not found", containerID) + } + + inspect := &inspects[0] + + if !inspect.State.Running { + return nil, fmt.Errorf("container %s exists but is not running", containerID) + } + + return inspect, nil +} + +// getPortMapping extracts the host port that maps to a given container port +func getPortMapping(inspect *ContainerInspect, containerPort string) (string, error) { + portKey := containerPort + "/tcp" + ports, exists := inspect.NetworkSettings.Ports[portKey] + if !exists || len(ports) == 0 { + return "", fmt.Errorf("no port mapping found for container port %s", containerPort) + } + + // Return the first host port mapping + hostPort := ports[0].HostPort + if hostPort == "" { + return "", fmt.Errorf("empty host port mapping for container port %s", containerPort) + } + + return hostPort, nil +} + // Connect establishes a connection to the specified TON network and returns an // explorer instance for tracing transactions. // @@ -145,10 +242,13 @@ func parseFormat(visualization string, format string) (Format, error) { // - verbose: Whether to enable verbose output. // - pageSize: The number of transactions to fetch per page. // - maxPages: The maximum number of pages to fetch. -func Connect(lggr logger.Logger, net string, verbose bool, pageSize uint32, maxPages uint32) (*client, error) { - apiClient, err := connect(context.Background(), net) - if err != nil { - return nil, fmt.Errorf("failed to connect to network: %w", err) +func Connect(lggr logger.Logger, apiClient *ton.APIClient, net string, verbose bool, pageSize uint32, maxPages uint32) (*client, error) { + if apiClient == nil { + var err error + apiClient, err = connect(context.Background(), net) + if err != nil { + return nil, fmt.Errorf("failed to connect to network: %w", err) + } } return &client{ lggr: lggr, @@ -464,19 +564,60 @@ func equalHash(a, b []byte) bool { } func connect(ctx context.Context, net string) (*ton.APIClient, error) { - configURL := net + pool := liteclient.NewConnectionPool() switch net { case "mainnet": - configURL = "https://ton-blockchain.github.io/global.config.json" + configURL := "https://ton-blockchain.github.io/global.config.json" + err := pool.AddConnectionsFromConfigUrl(ctx, configURL) + if err != nil { + return nil, fmt.Errorf("failed to add connections from config url: %w", err) + } case "testnet": - configURL = "https://ton.org/testnet-global.config.json" + configURL := "https://ton.org/testnet-global.config.json" + err := pool.AddConnectionsFromConfigUrl(ctx, configURL) + if err != nil { + return nil, fmt.Errorf("failed to add connections from config url: %w", err) + } case "mylocalton": - configURL = "http://127.0.0.1:8000/localhost.global.config.json" - } - pool := liteclient.NewConnectionPool() - err := pool.AddConnectionsFromConfigUrl(ctx, configURL) - if err != nil { - return nil, fmt.Errorf("failed to add connections from config url: %w", err) + // Find running mylocalton container + containerID, err := findMylocaltonContainer(ctx) + if err != nil { + return nil, fmt.Errorf("failed to find mylocalton container: %w", err) + } + + // Inspect the container to get port mappings + inspect, err := inspectContainer(ctx, containerID) + if err != nil { + return nil, fmt.Errorf("failed to inspect container %s: %w", containerID, err) + } + + // Get the external port mapping for internal port 8000 (config server) + configPort, err := getPortMapping(inspect, "8000") + if err != nil { + return nil, fmt.Errorf("failed to get port mapping for config server: %w", err) + } + + // Fetch the config from the mapped port + configURL := fmt.Sprintf("http://127.0.0.1:%s/localhost.global.config.json", configPort) + config, err := liteclient.GetConfigFromUrl(ctx, configURL) + if err != nil { + return nil, fmt.Errorf("failed to get config from url: %w", err) + } + + // Get the liteserver port mapping (typically port 46995 internally) + liteserverConfig := config.Liteservers[0] + liteserverPort := strconv.Itoa(int(liteserverConfig.Port)) + externalLiteserverPort, err := getPortMapping(inspect, liteserverPort) + if err != nil { + return nil, fmt.Errorf("failed to get port mapping for liteserver: %w", err) + } + + // Connect to the liteserver using the external port + connectionString := fmt.Sprintf("127.0.0.1:%s", externalLiteserverPort) + err = pool.AddConnection(ctx, connectionString, liteserverConfig.ID.Key) + if err != nil { + return nil, fmt.Errorf("failed to add localton connection: %w", err) + } } return ton.NewAPIClient(pool, ton.ProofCheckPolicyFast), nil } From d51b3f892f7a6524286d2d6d22fecf68430f58cd Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 16:22:51 -0300 Subject: [PATCH 31/45] doc: usage and development guies --- deployment/ccip/cs_test_helpers.go | 3 - docs/.misc/dev-guides/explorer/development.md | 35 ++++++++ docs/.misc/dev-guides/explorer/usage.md | 84 +++++++++++++++++++ pkg/ton/debug/explorer/explorer.go | 8 +- pkg/ton/debug/lib/lib.go | 8 ++ 5 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 docs/.misc/dev-guides/explorer/development.md create mode 100644 docs/.misc/dev-guides/explorer/usage.md diff --git a/deployment/ccip/cs_test_helpers.go b/deployment/ccip/cs_test_helpers.go index 443fab9ce..c0c5a09c1 100644 --- a/deployment/ccip/cs_test_helpers.go +++ b/deployment/ccip/cs_test_helpers.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" "testing" - "time" "github.com/smartcontractkit/chainlink-ton/deployment/ccip/sequence" "github.com/smartcontractkit/chainlink-ton/deployment/state" @@ -273,8 +272,6 @@ func SendTonRequest( return 0, nil, fmt.Errorf("failed to wait for trace: %w", err) } - time.Sleep(24 * time.Hour) // Wait for the message to be fully processed - event, err := waitForReceivedMsgFlatten(e, clientConn, receivedMsg) if err != nil { return 0, nil, fmt.Errorf("failed to get CCIPMessageSent from flattening received messages: %w", err) diff --git a/docs/.misc/dev-guides/explorer/development.md b/docs/.misc/dev-guides/explorer/development.md new file mode 100644 index 000000000..24403fd7a --- /dev/null +++ b/docs/.misc/dev-guides/explorer/development.md @@ -0,0 +1,35 @@ +# TON Explorer Development Guide + +For adding support to more contracts, you need to register your decoder in [`defaultDecoders`](../../../../pkg/ton/debug/pretty_print.go). Decoders implement [`ContractDecoder`](../../../../pkg/ton/debug/lib/lib.go) interface: + +```go +type ContractDecoder interface { + ContractType() cldf.ContractType + InternalMessageInfo(body *cell.Cell) (MessageInfo, error) + ExternalMessageInfo(body *cell.Cell) (MessageInfo, error) + EventInfo(dstAddr *address.Address, msg *cell.Cell) (MessageInfo, error) + ExitCodeInfo(exitCode tvm.ExitCode) (string, error) +} + +// Describes a decoded message or event. +// +// - Name is a short name of the message/event type. +// - Body carries the contents of the message/event in both compact and detailed forms. +type MessageInfo interface { + Name() string + Body() BodyInfo +} + +// BodyInfo describes the contents of a message or event. +// +// - Compact is a single-line representation. +// - Describe is a pretty-printed, multi-line representation. +type BodyInfo interface { + Compact() string + Describe() string +} +``` + +Your decoder should go in `pkg/ton/debug/decoders/` package. If it is a ccip contract, then in `pkg/ton/debug/decoders/ccip`. E.g. `pkg/ton/debug/decoders/ccip/feequoter/feequoter.go`. + +I suggest not placing any business logic in the decoder. Instead, create a separate package for that, e.g. `pkg/ccip/bindings/feequoter/codec.go` and use it from the decoder. diff --git a/docs/.misc/dev-guides/explorer/usage.md b/docs/.misc/dev-guides/explorer/usage.md new file mode 100644 index 000000000..d7fe63070 --- /dev/null +++ b/docs/.misc/dev-guides/explorer/usage.md @@ -0,0 +1,84 @@ +# TON Explorer Usage Guide + +Command-line tool for analyzing TON blockchain transactions and traces. + +## Usage + +Three ways to run: + +1. **URL**: `./explorer ` +2. **Hash + Address**: `./explorer
` +3. **Hash only**: `./explorer ` (testnet/mainnet only) + +## Build + +```bash +cd cmd/explorer +go build +``` + +## Examples + +```bash +# URL (recommended) +./explorer https://testnet.tonscan.org/tx/ + +# Hash + address +./explorer
+ +# Hash only (auto-resolves address) +./explorer +``` + +## Networks + +Choose the network with `-n`/`--net` flag: + +- `--net testnet` (default) +- `--net mainnet` +- `--net mylocalton` (auto-discovers Docker containers) +- `--net http://custom-domain/global.config.json` + +## Output Formats + +**Sequence diagram** + +Display message flow as a sequence diagram in [Mermaid](https://www.mermaidchart.com/) format + +Available options: + +- `--visualization sequence --format url` (default): URL to [Mermaid Playground Editor](https://mermaid.play/) with preloaded diagram +- `--visualization sequence --format raw`: Raw Mermaid syntax + +**Tree view** + +Display message trace as a tree structure with `--visualization tree`. + +## Options + +```bash +--verbose # Show debugging information +--page-size 10 --max-pages 10 # Control transaction search pagination +``` + +## Environment injection + +The same cli is exposed in [chainlink-deployments's repo](https://github.com/smartcontractkit/chainlink-deployments/branch/tree/main/domains/ccip/cmd) which injects contract metadata from the DataStore. + +## Debugging Functionality + +### Humman-readable addresses + +The explorer will try to match contract addresses to known contracts. It will first look into the injected contracts map, and then fallback to calling the `typeAndVersion` getter on the contract. If none of these methods work, the explorer will try to match the contract to known types with its code hash. + +### Payload decoding + +The explorer will try to decode message payloads for known contracts. It currently supports: + +- Jetton wallet and minter +- Router +- OnRamp +- FeeQuoter +- CcipSendExecutor + +Read [TON Explorer Development Guide](./development.md) to learn how to add support for more contracts. diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 8e0aceb27..56b33b290 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -548,7 +548,7 @@ func (c *client) findTx(ctx context.Context, api *ton.APIClient, srcAddr *addres maxLT = last.PrevTxLT maxHash = last.PrevTxHash } - return nil, errors.New("transaction not found") + return nil, errors.New("transaction not found in searched range. Try increasing --page-size and --max-pages") } func equalHash(a, b []byte) bool { @@ -618,6 +618,12 @@ func connect(ctx context.Context, net string) (*ton.APIClient, error) { if err != nil { return nil, fmt.Errorf("failed to add localton connection: %w", err) } + default: + configURL := net + err := pool.AddConnectionsFromConfigUrl(ctx, configURL) + if err != nil { + return nil, fmt.Errorf("failed to add connections from config url: %w", err) + } } return ton.NewAPIClient(pool, ton.ProofCheckPolicyFast), nil } diff --git a/pkg/ton/debug/lib/lib.go b/pkg/ton/debug/lib/lib.go index 12403b070..1fed88729 100644 --- a/pkg/ton/debug/lib/lib.go +++ b/pkg/ton/debug/lib/lib.go @@ -16,11 +16,19 @@ type TxInfo struct { ExitCode string } +// Describes a decoded message or event. +// +// - Name is a short name of the message/event type. +// - Body carries the contents of the message/event in both compact and detailed forms. type MessageInfo interface { Name() string Body() BodyInfo } +// BodyInfo describes the contents of a message or event. +// +// - Compact is a single-line representation. +// - Describe is a pretty-printed, multi-line representation. type BodyInfo interface { Compact() string Describe() string From dcf41e0b72b0cb39c8091ea978b77415365a03e6 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 16:26:52 -0300 Subject: [PATCH 32/45] doc:development guies --- docs/.misc/dev-guides/explorer/development.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/.misc/dev-guides/explorer/development.md b/docs/.misc/dev-guides/explorer/development.md index 24403fd7a..cbc527282 100644 --- a/docs/.misc/dev-guides/explorer/development.md +++ b/docs/.misc/dev-guides/explorer/development.md @@ -33,3 +33,5 @@ type BodyInfo interface { Your decoder should go in `pkg/ton/debug/decoders/` package. If it is a ccip contract, then in `pkg/ton/debug/decoders/ccip`. E.g. `pkg/ton/debug/decoders/ccip/feequoter/feequoter.go`. I suggest not placing any business logic in the decoder. Instead, create a separate package for that, e.g. `pkg/ccip/bindings/feequoter/codec.go` and use it from the decoder. + +When trying to parse a message, your decoder should return `lib.UnknownMessageError{}` if the opcode doesn't match. As we are rellying on unique opcodes, if the opcode matches, you can assume the message is for your contract, and return a different error if the message is malformed. \ No newline at end of file From b474d02418c0806116b21b0a1ab8e9e9db366175 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 16:30:42 -0300 Subject: [PATCH 33/45] fix: bump nix hash --- cmd/chainlink-ton/lock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index 77ad0e9dc..670a98f17 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `nix-lock-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-3p3kZFPhp3CfaB4T2UIMln+YhrOLNTvnhjWVu1ZOrWY="; + chainlink-ton = "sha256-GZGXWJMIHXYXPELCJVhy6XgYqKzKMN3ntLiGyUAbU3M="; } From 25043dcab520d1c3bdc4d6d6ee3b4d84f9b7d7f7 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 16:34:41 -0300 Subject: [PATCH 34/45] fix: golint --- cmd/explorer/main.go | 1 + pkg/ton/debug/explorer/explorer.go | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index f5735298d..f78c345e9 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -7,6 +7,7 @@ import ( "github.com/smartcontractkit/wsrpc/logger" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 56b33b290..5f48ccfde 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -31,7 +31,6 @@ import ( ) func GenerateExplorerCmd(lggr logger.Logger, contracts map[string]deployment.TypeAndVersion, client *ton.APIClient) *cobra.Command { - var ( destAddressStr string txHashStr string @@ -127,7 +126,7 @@ func parseFormat(visualization string, format string) (Format, error) { switch visualization { case "tree": if format != "" { - return Format(0), fmt.Errorf("format option is not applicable for tree visualization") + return Format(0), errors.New("format option is not applicable for tree visualization") } return FormatTree, nil case "sequence": @@ -604,16 +603,16 @@ func connect(ctx context.Context, net string) (*ton.APIClient, error) { return nil, fmt.Errorf("failed to get config from url: %w", err) } - // Get the liteserver port mapping (typically port 46995 internally) + // Get the liteserver port mapping liteserverConfig := config.Liteservers[0] - liteserverPort := strconv.Itoa(int(liteserverConfig.Port)) + liteserverPort := strconv.Itoa(liteserverConfig.Port) externalLiteserverPort, err := getPortMapping(inspect, liteserverPort) if err != nil { return nil, fmt.Errorf("failed to get port mapping for liteserver: %w", err) } // Connect to the liteserver using the external port - connectionString := fmt.Sprintf("127.0.0.1:%s", externalLiteserverPort) + connectionString := "127.0.0.1:" + externalLiteserverPort err = pool.AddConnection(ctx, connectionString, liteserverConfig.ID.Key) if err != nil { return nil, fmt.Errorf("failed to add localton connection: %w", err) From 53fda9a8f40e02439a47128e53b7cdf2be0a4592 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 17:32:03 -0300 Subject: [PATCH 35/45] fix: typos --- docs/.misc/dev-guides/explorer/development.md | 2 +- docs/.misc/dev-guides/explorer/usage.md | 4 ++-- pkg/ton/debug/explorer/explorer.go | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/.misc/dev-guides/explorer/development.md b/docs/.misc/dev-guides/explorer/development.md index cbc527282..695d93e68 100644 --- a/docs/.misc/dev-guides/explorer/development.md +++ b/docs/.misc/dev-guides/explorer/development.md @@ -34,4 +34,4 @@ Your decoder should go in `pkg/ton/debug/decoders/` package. If it is a I suggest not placing any business logic in the decoder. Instead, create a separate package for that, e.g. `pkg/ccip/bindings/feequoter/codec.go` and use it from the decoder. -When trying to parse a message, your decoder should return `lib.UnknownMessageError{}` if the opcode doesn't match. As we are rellying on unique opcodes, if the opcode matches, you can assume the message is for your contract, and return a different error if the message is malformed. \ No newline at end of file +When trying to parse a message, your decoder should return `lib.UnknownMessageError{}` if the opcode doesn't match. As we are relying on unique opcodes, if the opcode matches, you can assume the message is for your contract, and return a different error if the message is malformed. diff --git a/docs/.misc/dev-guides/explorer/usage.md b/docs/.misc/dev-guides/explorer/usage.md index d7fe63070..d9eb0c56c 100644 --- a/docs/.misc/dev-guides/explorer/usage.md +++ b/docs/.misc/dev-guides/explorer/usage.md @@ -63,11 +63,11 @@ Display message trace as a tree structure with `--visualization tree`. ## Environment injection -The same cli is exposed in [chainlink-deployments's repo](https://github.com/smartcontractkit/chainlink-deployments/branch/tree/main/domains/ccip/cmd) which injects contract metadata from the DataStore. +The same cli is exposed in [chainlink-deployments's repo](https://github.com/smartcontractkit/chainlink-deployments/tree/main/domains/ccip/cmd) which injects contract metadata from the DataStore. ## Debugging Functionality -### Humman-readable addresses +### Human-readable addresses The explorer will try to match contract addresses to known contracts. It will first look into the injected contracts map, and then fallback to calling the `typeAndVersion` getter on the contract. If none of these methods work, the explorer will try to match the contract to known types with its code hash. diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 5f48ccfde..44e91ca71 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -284,11 +284,11 @@ const ( // Parameters: // - ctx: The context for managing request deadlines and cancellation. // - txHashStr: The transaction hash in hexadecimal format. -// - srcAddresstr: The source address of the transaction in string format. -func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr string, format Format, knownActors map[string]deployment.TypeAndVersion) error { +// - srcAddrStr: The source address of the transaction in string format. +func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddrStr string, format Format, knownActors map[string]deployment.TypeAndVersion) error { var senderAddr *address.Address var err error - if srcAddresstr == "" { + if srcAddrStr == "" { c.lggr.Debug("source address not provided, attempting to fetch from toncenter by hash...") senderAddr, err = c.GetSenderAddressFromTxHash(ctx, txHashStr) if err != nil { @@ -296,7 +296,7 @@ func (c *client) PrintTrace(ctx context.Context, txHashStr string, srcAddresstr } c.lggr.Debug("source address found:", senderAddr.String()) } else { - senderAddr, err = address.ParseAddr(srcAddresstr) + senderAddr, err = address.ParseAddr(srcAddrStr) if err != nil { return fmt.Errorf("failed to parse transaction address: %w", err) } From c02d0506229dca1e7b69c5ba1b0ab2e96b46d7e8 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Mon, 13 Oct 2025 17:44:34 -0300 Subject: [PATCH 36/45] feat: mylocalton explorer url support --- docs/.misc/dev-guides/explorer/usage.md | 5 +++-- pkg/ton/debug/explorer/utils.go | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/.misc/dev-guides/explorer/usage.md b/docs/.misc/dev-guides/explorer/usage.md index d9eb0c56c..b9472fd7e 100644 --- a/docs/.misc/dev-guides/explorer/usage.md +++ b/docs/.misc/dev-guides/explorer/usage.md @@ -22,12 +22,13 @@ go build ```bash # URL (recommended) ./explorer https://testnet.tonscan.org/tx/ +./explorer http://localhost:8080/transaction?account=&hash= # Hash + address -./explorer
+./explorer
[--net testnet|mainnet|mylocalton|http://custom-domain/global.config.json] # Hash only (auto-resolves address) -./explorer +./explorer [--net testnet|mainnet|mylocalton|http://custom-domain/global.config.json] ``` ## Networks diff --git a/pkg/ton/debug/explorer/utils.go b/pkg/ton/debug/explorer/utils.go index 16aaba063..94546c822 100644 --- a/pkg/ton/debug/explorer/utils.go +++ b/pkg/ton/debug/explorer/utils.go @@ -8,7 +8,7 @@ import ( ) // ParseURL extracts transaction hash and network from tonscan URL -// Supports tonscan.org URL formats +// Supports tonscan.org and mylocalton explorer URL formats func ParseURL(urlStr string) (txHash, address, network string, err error) { u, err := url.Parse(urlStr) if err != nil { @@ -16,11 +16,13 @@ func ParseURL(urlStr string) (txHash, address, network string, err error) { } // Determine network from subdomain (tonscan.org format) - network = "mainnet" // default + network = "testnet" // default if strings.Contains(u.Host, "testnet.tonscan.org") { network = "testnet" } else if strings.Contains(u.Host, "tonscan.org") { network = "mainnet" + } else if strings.Contains(u.Host, "localhost") { + network = "mylocalton" } // Handle tonscan.org transaction URLs: /tx/{hash} @@ -30,6 +32,16 @@ func ParseURL(urlStr string) (txHash, address, network string, err error) { txHash = pathParts[1] return txHash, address, network, nil } + } else if strings.Contains(u.Host, "localhost") { + // Handle mylocalton transaction URLs: /transaction?hash={hash}&account={address} + if u.Path == "/transaction" { + query := u.Query() + txHash = query.Get("hash") + address = query.Get("account") + if txHash != "" { + return txHash, address, network, nil + } + } } return "", "", "", errors.New("unsupported URL format") From b505cd3825b2471319c17703295d2d5cf54ab518 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 14:52:18 -0300 Subject: [PATCH 37/45] feat: dash padding only for sequence diagram --- pkg/ton/debug/lib/lib.go | 2 +- .../visualizations/sequence/sanitizer.go | 17 ++- .../visualizations/sequence/sanitizer_test.go | 137 ++++++++++++++++++ 3 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 pkg/ton/debug/visualizations/sequence/sanitizer_test.go diff --git a/pkg/ton/debug/lib/lib.go b/pkg/ton/debug/lib/lib.go index 1fed88729..9db4ba0f7 100644 --- a/pkg/ton/debug/lib/lib.go +++ b/pkg/ton/debug/lib/lib.go @@ -53,7 +53,7 @@ func NewMessageInfo[T any](name string, msg T) (MessageInfo, error) { if err != nil { return nil, err } - long, err := json.MarshalIndent(msg, "", "__") + long, err := json.MarshalIndent(msg, "", " ") if err != nil { return nil, err } diff --git a/pkg/ton/debug/visualizations/sequence/sanitizer.go b/pkg/ton/debug/visualizations/sequence/sanitizer.go index 0ec332712..c7bfcf1eb 100644 --- a/pkg/ton/debug/visualizations/sequence/sanitizer.go +++ b/pkg/ton/debug/visualizations/sequence/sanitizer.go @@ -6,9 +6,18 @@ import ( ) func sanitizeString(s string) string { + description := "" + for i, line := range strings.Split(s, "\n") { + if i > 0 { + description += "
" + } + withoutPadding := strings.TrimLeft(line, " ") + paddingLen := len(line) - len(withoutPadding) + newPadding := strings.Repeat("_", paddingLen) + description += newPadding + withoutPadding + } var wrapWidth = 80 - description := wrap(s, wrapWidth) - description = strings.ReplaceAll(description, "\n", "
") + description = wrap(description, wrapWidth) description = strings.ReplaceAll(description, "\"", "'") return description } @@ -21,7 +30,7 @@ func wrap(s string, width int) string { } var out []string - paras := strings.Split(s, "\n") + paras := strings.Split(s, "
") for i := range paras { p := paras[i] @@ -82,7 +91,7 @@ func wrap(s string, width int) string { } // Join lines, but keep single trailing newline behavior similar to input - return strings.Join(out, "\n") + return strings.Join(out, "
") } // takeRunes returns the first n runes of s. diff --git a/pkg/ton/debug/visualizations/sequence/sanitizer_test.go b/pkg/ton/debug/visualizations/sequence/sanitizer_test.go new file mode 100644 index 000000000..ff8159ccf --- /dev/null +++ b/pkg/ton/debug/visualizations/sequence/sanitizer_test.go @@ -0,0 +1,137 @@ +package sequence + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSanitizeString(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "empty string", + input: "", + expected: "", + }, + { + name: "simple string without quotes or padding", + input: "hello world", + expected: "hello world", + }, + { + name: "string with double quotes", + input: `this is a "quoted" string`, + expected: "this is a 'quoted' string", + }, + { + name: "string with multiple quotes", + input: `"hello" and "world" with "quotes"`, + expected: "'hello' and 'world' with 'quotes'", + }, + { + name: "string with padding spaces", + input: " hello world", + expected: "__hello world", + }, + { + name: "string with varying padding", + input: " indented line\n less indented\nno indent", + expected: "____indented line
__less indented
no indent", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := sanitizeString(tt.input) + assert.Equalf(t, tt.expected, result, "Failed test: %s", tt.name) + }) + } +} + +func TestWrap(t *testing.T) { + tests := []struct { + name string + input string + width int + expected string + }{ + { + name: "empty string", + input: "", + width: 10, + expected: "", + }, + { + name: "width zero or negative", + input: "hello world", + width: 0, + expected: "hello world", + }, + { + name: "short text within width", + input: "hello", + width: 10, + expected: "hello", + }, + { + name: "text exactly at width", + input: "hello world", + width: 11, + expected: "hello world", + }, + { + name: "simple wrapping", + input: "hello world test", + width: 10, + expected: "hello
world test", + }, + { + name: "word longer than width", + input: strings.Repeat("a", 25), + width: 10, + expected: strings.Repeat("a", 10) + "
" + strings.Repeat("a", 10) + "
" + strings.Repeat("a", 5), + }, + { + name: "mixed short and long words", + input: "hello " + strings.Repeat("b", 14) + " world", + width: 10, + expected: "hello
" + strings.Repeat("b", 10) + "
" + strings.Repeat("b", 4) + " world", + }, + { + name: "preserve blank lines", + input: "line one
line three", + width: 20, + expected: "line one
line three", + }, + { + name: "multiple consecutive blank lines", + input: "line one
line four", + width: 20, + expected: "line one
line four", + }, + { + name: "blank lines with wrapping", + input: "this is a long line that needs wrapping
this is another long line that also needs wrapping", + width: 20, + expected: "this is a long line
that needs wrapping
this is another long
line that also needs
wrapping", + }, + { + name: "single character width", + input: "hello", + width: 1, + expected: "h
e
l
l
o", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := wrap(tt.input, tt.width) + assert.Equalf(t, tt.expected, result, "Failed test: %s", tt.name) + }) + } +} From 0c52c350aaf4be0d10b176e0365b9e0cc07f21da Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 16:22:27 -0300 Subject: [PATCH 38/45] fix: golint --- pkg/ton/debug/explorer/utils.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/ton/debug/explorer/utils.go b/pkg/ton/debug/explorer/utils.go index 94546c822..2fd6449a7 100644 --- a/pkg/ton/debug/explorer/utils.go +++ b/pkg/ton/debug/explorer/utils.go @@ -17,11 +17,12 @@ func ParseURL(urlStr string) (txHash, address, network string, err error) { // Determine network from subdomain (tonscan.org format) network = "testnet" // default - if strings.Contains(u.Host, "testnet.tonscan.org") { + switch { + case strings.Contains(u.Host, "testnet.tonscan.org"): network = "testnet" - } else if strings.Contains(u.Host, "tonscan.org") { + case strings.Contains(u.Host, "tonscan.org"): network = "mainnet" - } else if strings.Contains(u.Host, "localhost") { + case strings.Contains(u.Host, "localhost"): network = "mylocalton" } From bc8e48f9d632bcec252ead01ab205224a0fd378d Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 18:53:00 -0300 Subject: [PATCH 39/45] fix: explorer --- cmd/explorer/main.go | 4 +--- pkg/ton/debug/explorer/explorer.go | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/cmd/explorer/main.go b/cmd/explorer/main.go index f78c345e9..11a933b88 100644 --- a/cmd/explorer/main.go +++ b/cmd/explorer/main.go @@ -4,14 +4,12 @@ import ( "fmt" "os" - "github.com/smartcontractkit/wsrpc/logger" - "github.com/smartcontractkit/chainlink-deployments-framework/deployment" "github.com/smartcontractkit/chainlink-ton/pkg/ton/debug/explorer" ) -var rootCmd = explorer.GenerateExplorerCmd(logger.DefaultLogger, map[string]deployment.TypeAndVersion{}, nil) +var rootCmd = explorer.GenerateExplorerCmd(nil, map[string]deployment.TypeAndVersion{}, nil) func main() { if err := rootCmd.Execute(); err != nil { diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 44e91ca71..0d2e47b02 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -19,8 +19,9 @@ import ( "github.com/xssnick/tonutils-go/liteclient" "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/ton" + "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/wsrpc/logger" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -30,7 +31,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tracetracking" ) -func GenerateExplorerCmd(lggr logger.Logger, contracts map[string]deployment.TypeAndVersion, client *ton.APIClient) *cobra.Command { +func GenerateExplorerCmd(lggr *logger.Logger, contracts map[string]deployment.TypeAndVersion, client *ton.APIClient) *cobra.Command { var ( destAddressStr string txHashStr string @@ -63,6 +64,18 @@ Arguments: return nil }, RunE: func(cmd *cobra.Command, args []string) error { + var err error + var log logger.Logger + if lggr == nil { + config := logger.Config{} + if verbose { + config.Level = zapcore.DebugLevel + } + log, err = config.New() + if err != nil { + return fmt.Errorf("failed to create logger: %w", err) + } + } if client != nil && cmd.Flags().Changed("net") { return errors.New("cannot specify network flag when using existing client") } @@ -94,7 +107,7 @@ Arguments: } ctx := context.Background() - client, err := Connect(lggr, client, net, verbose, pageSize, maxPages) + client, err := Connect(log, client, net, verbose, pageSize, maxPages) if err != nil { return fmt.Errorf("failed to initialize explorer: %w", err) } @@ -115,7 +128,9 @@ Arguments: cmd.Flags().StringVarP(&format, "format", "f", "", "Sequence visualization format (url or raw) (only for sequence visualization)") cmd.Flags().StringVarP(&txHashStr, "tx", "t", "", "Transaction hash in hex (optional if provided as argument)") cmd.Flags().StringVarP(&net, "net", "n", "testnet", "TON network (mainnet, testnet, mylocalton, or http://domain/x.global.config.json)") - cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") + if lggr == nil { + cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Shows full body of unmatched messages") + } cmd.Flags().Uint32VarP(&pageSize, "page-size", "s", 10, "Number of blocks to fetch per page") cmd.Flags().Uint32VarP(&maxPages, "max-pages", "p", 10, "Maximum number of pages to fetch") From d0a03dddaec43ba7998447c9f004557b34df67a6 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 18:57:30 -0300 Subject: [PATCH 40/45] fix: explorer --- pkg/ton/debug/explorer/explorer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 0d2e47b02..58ac20534 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -66,7 +66,9 @@ Arguments: RunE: func(cmd *cobra.Command, args []string) error { var err error var log logger.Logger - if lggr == nil { + if lggr != nil { + log = *lggr + } else { config := logger.Config{} if verbose { config.Level = zapcore.DebugLevel From 45145f85a50432cd278d91fc3f7088fcba5d2a00 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 19:27:26 -0300 Subject: [PATCH 41/45] chore: remove codec from this pr --- pkg/bindings/jetton/common.go | 21 ----- pkg/bindings/jetton/minter/codec.go | 88 ------------------- pkg/bindings/jetton/minter/minter.go | 49 +++++++++++ pkg/bindings/jetton/wallet/codec.go | 84 ------------------ pkg/bindings/jetton/wallet/wallet.go | 45 ++++++++++ .../ccipsendexecutor/ccipsendexecutor.go | 12 +++ pkg/ccip/bindings/ccipsendexecutor/codec.go | 37 -------- pkg/ccip/bindings/feequoter/codec.go | 41 --------- pkg/ccip/bindings/onramp/codec.go | 43 --------- pkg/ccip/bindings/router/codec.go | 40 --------- pkg/ccip/bindings/router/router.go | 11 +++ pkg/ton/codec/builder.go | 31 ------- .../ccip/ccipsendexecutor/ccipsendexecutor.go | 4 +- .../decoders/ccip/feequoter/feequoter.go | 19 ++-- pkg/ton/debug/decoders/ccip/onramp/onramp.go | 22 +++-- pkg/ton/debug/decoders/ccip/router/router.go | 7 +- pkg/ton/debug/decoders/jetton/common.go | 4 +- .../decoders/jetton/minter/jetton_minter.go | 9 +- .../decoders/jetton/wallet/jetton_wallet.go | 6 +- 19 files changed, 166 insertions(+), 407 deletions(-) delete mode 100644 pkg/bindings/jetton/minter/codec.go delete mode 100644 pkg/bindings/jetton/wallet/codec.go delete mode 100644 pkg/ccip/bindings/ccipsendexecutor/codec.go delete mode 100644 pkg/ccip/bindings/feequoter/codec.go delete mode 100644 pkg/ccip/bindings/onramp/codec.go delete mode 100644 pkg/ccip/bindings/router/codec.go delete mode 100644 pkg/ton/codec/builder.go diff --git a/pkg/bindings/jetton/common.go b/pkg/bindings/jetton/common.go index e47975b5c..c2e7c169d 100644 --- a/pkg/bindings/jetton/common.go +++ b/pkg/bindings/jetton/common.go @@ -3,7 +3,6 @@ package jetton import ( "github.com/xssnick/tonutils-go/tlb" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" ) @@ -19,26 +18,6 @@ const ( ErrorWrongWorkchain tvm.ExitCode = tvm.ExitCode(333) ) -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - TopUp: codec.TLBCodec[TopUpMessage](), - }, - }, -} - -type inMessageBuilder struct { - TopUp codec.CellCodec[TopUpMessage] -} - -type messageBuilder struct { - In inMessageBuilder -} - -type builder struct { - Messages messageBuilder -} - // For funding the contract with TON type TopUpMessage struct { _ tlb.Magic `tlb:"#d372158c"` //nolint:revive // (opcode) should stay uninitialized diff --git a/pkg/bindings/jetton/minter/codec.go b/pkg/bindings/jetton/minter/codec.go deleted file mode 100644 index 3cbc5887d..000000000 --- a/pkg/bindings/jetton/minter/codec.go +++ /dev/null @@ -1,88 +0,0 @@ -package minter - -import ( - "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" - - "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" -) - -// JettonMinter opcodes -const ( - OpcodeMinterMint = 0x642b7d07 - OpcodeMinterChangeAdmin = 0x6501f354 - OpcodeMinterClaimAdmin = 0xfb88e119 - OpcodeMinterDropAdmin = 0x7431f221 - OpcodeMinterBurnNotification = 0x7bdd97de - OpcodeMinterChangeMetadataURL = 0xcb862902 - OpcodeWalletBurnNotification = 0x7bdd97de -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - Mint: codec.TLBCodec[MintMessage](), - ChangeAdmin: codec.TLBCodec[ChangeAdminMessage](), - ClaimAdmin: codec.TLBCodec[ClaimAdminMessage](), - DropAdmin: codec.TLBCodec[DropAdminMessage](), - ChangeContent: codec.TLBCodec[ChangeContentMessage](), - Upgrade: codec.TLBCodec[UpgradeMessage](), - }, - }, -} - -type inMessageBuilder struct { - Mint codec.CellCodec[MintMessage] - ChangeAdmin codec.CellCodec[ChangeAdminMessage] - ClaimAdmin codec.CellCodec[ClaimAdminMessage] - DropAdmin codec.CellCodec[DropAdminMessage] - ChangeContent codec.CellCodec[ChangeContentMessage] - Upgrade codec.CellCodec[UpgradeMessage] -} - -type messageBuilder struct { - In inMessageBuilder -} - -type builder struct { - Messages messageBuilder -} - -type MintMessage struct { - _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Destination *address.Address `tlb:"addr"` - TonAmount tlb.Coins `tlb:"."` - MasterMsg wallet.InternalTransferMessage `tlb:"^"` -} - -type ChangeAdminMessage struct { - _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewAdmin *address.Address `tlb:"addr"` -} - -type ClaimAdminMessage struct { - _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type DropAdminMessage struct { - _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type ChangeContentMessage struct { - _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Content *cell.Cell `tlb:"^"` -} - -type UpgradeMessage struct { - _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewData *cell.Cell `tlb:"^"` - NewCode *cell.Cell `tlb:"^"` -} diff --git a/pkg/bindings/jetton/minter/minter.go b/pkg/bindings/jetton/minter/minter.go index d24f9b330..977d03ac8 100644 --- a/pkg/bindings/jetton/minter/minter.go +++ b/pkg/bindings/jetton/minter/minter.go @@ -10,6 +10,7 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) @@ -30,3 +31,51 @@ func Code() (*cell.Cell, error) { } return compiledContract, nil } + +// JettonMinter opcodes +const ( + OpcodeMinterMint = 0x642b7d07 + OpcodeMinterChangeAdmin = 0x6501f354 + OpcodeMinterClaimAdmin = 0xfb88e119 + OpcodeMinterDropAdmin = 0x7431f221 + OpcodeMinterBurnNotification = 0x7bdd97de + OpcodeMinterChangeMetadataURL = 0xcb862902 + OpcodeWalletBurnNotification = 0x7bdd97de +) + +type MintMessage struct { + _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Destination *address.Address `tlb:"addr"` + TonAmount tlb.Coins `tlb:"."` + MasterMsg wallet.InternalTransferMessage `tlb:"^"` +} + +type ChangeAdminMessage struct { + _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewAdmin *address.Address `tlb:"addr"` +} + +type ClaimAdminMessage struct { + _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type DropAdminMessage struct { + _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type ChangeContentMessage struct { + _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Content *cell.Cell `tlb:"^"` +} + +type UpgradeMessage struct { + _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewData *cell.Cell `tlb:"^"` + NewCode *cell.Cell `tlb:"^"` +} diff --git a/pkg/bindings/jetton/wallet/codec.go b/pkg/bindings/jetton/wallet/codec.go deleted file mode 100644 index 22617b986..000000000 --- a/pkg/bindings/jetton/wallet/codec.go +++ /dev/null @@ -1,84 +0,0 @@ -package wallet - -import ( - "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" - - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -// JettonWallet opcodes -const ( - OpcodeWalletTransfer = 0x0f8a7ea5 - OpcodeWalletTransferNotification = 0x7362d09c - OpcodeWalletInternalTransfer = 0x178d4519 - OpcodeWalletExcesses = 0xd53276db - OpcodeWalletBurn = 0x595f07bc -) - -const ( - BalanceError tvm.ExitCode = tvm.ExitCode(47) - NotEnoughGas tvm.ExitCode = tvm.ExitCode(48) - InvalidMessage tvm.ExitCode = tvm.ExitCode(49) -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - AskToTransfer: codec.TLBCodec[AskToTransfer](), - InternalTransfer: codec.TLBCodec[InternalTransferMessage](), - }, - Out: outMessageBuilder{ - TransferNotification: codec.TLBCodec[TransferNotification](), - }, - }, -} - -type inMessageBuilder struct { - AskToTransfer codec.CellCodec[AskToTransfer] - InternalTransfer codec.CellCodec[InternalTransferMessage] -} - -type outMessageBuilder struct { - TransferNotification codec.CellCodec[TransferNotification] -} - -type messageBuilder struct { - In inMessageBuilder - Out outMessageBuilder -} - -type builder struct { - Messages messageBuilder -} - -type AskToTransfer struct { - _ tlb.Magic `tlb:"#0f8a7ea5"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"."` - Destination *address.Address `tlb:"addr"` - ResponseDestination *address.Address `tlb:"addr"` - CustomPayload *cell.Cell `tlb:"either . ^"` - ForwardTonAmount tlb.Coins `tlb:"."` - ForwardPayload *cell.Cell `tlb:"either . ^"` -} - -type InternalTransferMessage struct { - _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"."` - From *address.Address `tlb:"addr"` - ResponseAddress *address.Address `tlb:"addr"` - ForwardTonAmount tlb.Coins `tlb:"."` - ForwardPayload *cell.Cell `tlb:"either . ^"` -} - -type TransferNotification struct { - _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"^"` - Sender *address.Address `tlb:"addr"` - ForwardPayload *cell.Cell `tlb:"maybe ^"` -} diff --git a/pkg/bindings/jetton/wallet/wallet.go b/pkg/bindings/jetton/wallet/wallet.go index a614afdeb..792239762 100644 --- a/pkg/bindings/jetton/wallet/wallet.go +++ b/pkg/bindings/jetton/wallet/wallet.go @@ -9,9 +9,54 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) +// JettonWallet opcodes +const ( + OpcodeWalletTransfer = 0x0f8a7ea5 + OpcodeWalletTransferNotification = 0x7362d09c + OpcodeWalletInternalTransfer = 0x178d4519 + OpcodeWalletExcesses = 0xd53276db + OpcodeWalletBurn = 0x595f07bc +) + +const ( + BalanceError tvm.ExitCode = tvm.ExitCode(47) + NotEnoughGas tvm.ExitCode = tvm.ExitCode(48) + InvalidMessage tvm.ExitCode = tvm.ExitCode(49) +) + +type AskToTransfer struct { + _ tlb.Magic `tlb:"#0f8a7ea5"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + Destination *address.Address `tlb:"addr"` + ResponseDestination *address.Address `tlb:"addr"` + CustomPayload *cell.Cell `tlb:"either . ^"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type InternalTransferMessage struct { + _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + From *address.Address `tlb:"addr"` + ResponseAddress *address.Address `tlb:"addr"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type TransferNotification struct { + _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"^"` + Sender *address.Address `tlb:"addr"` + ForwardPayload *cell.Cell `tlb:"maybe ^"` +} + var WalletContractPath = path.Join(jetton.PathToContracts, "JettonWallet.compiled.json") type Provider struct { diff --git a/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go index 224ab21ea..9cdb0bc75 100644 --- a/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go +++ b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go @@ -9,6 +9,18 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// CCIPSend Executor opcodes +const ( + OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') +) + +// CCIPSend Executor exit codes +const ( + ErrorStateNotExpected tvm.ExitCode = tvm.ExitCode(500) + ErrorUnauthorized tvm.ExitCode = tvm.ExitCode(265) // ERROR_UNAUTHORIZED from contract ) // CCIPSendExecutor_Execute message structure diff --git a/pkg/ccip/bindings/ccipsendexecutor/codec.go b/pkg/ccip/bindings/ccipsendexecutor/codec.go deleted file mode 100644 index fe0c92468..000000000 --- a/pkg/ccip/bindings/ccipsendexecutor/codec.go +++ /dev/null @@ -1,37 +0,0 @@ -package ccipsendexecutor - -import ( - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -// CCIPSend Executor opcodes -const ( - OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') -) - -// CCIPSend Executor exit codes -const ( - ErrorStateNotExpected tvm.ExitCode = tvm.ExitCode(500) - ErrorUnauthorized tvm.ExitCode = tvm.ExitCode(265) // ERROR_UNAUTHORIZED from contract -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - Execute: codec.TLBCodec[Execute](), - }, - }, -} - -type inMessageBuilder struct { - Execute codec.CellCodec[Execute] -} - -type messageBuilder struct { - In inMessageBuilder -} - -type builder struct { - Messages messageBuilder -} diff --git a/pkg/ccip/bindings/feequoter/codec.go b/pkg/ccip/bindings/feequoter/codec.go deleted file mode 100644 index 922013d06..000000000 --- a/pkg/ccip/bindings/feequoter/codec.go +++ /dev/null @@ -1,41 +0,0 @@ -package feequoter - -import ( - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - UpdatePrices: codec.TLBCodec[UpdatePrices](), - UpdateFeeTokens: codec.TLBCodec[UpdateFeeTokens](), - UpdateTokenTransferFeeConfigs: codec.TLBCodec[UpdateTokenTransferFeeConfigs](), - UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigs](), - GetValidatedFee: codec.TLBCodec[GetValidatedFee](), - }, - Out: outMessageBuilder{ - MessageValidated: codec.TLBCodec[MessageValidated](), - }, - }, -} - -type inMessageBuilder struct { - UpdatePrices codec.CellCodec[UpdatePrices] - UpdateFeeTokens codec.CellCodec[UpdateFeeTokens] - UpdateTokenTransferFeeConfigs codec.CellCodec[UpdateTokenTransferFeeConfigs] - UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigs] - GetValidatedFee codec.CellCodec[GetValidatedFee] -} - -type outMessageBuilder struct { - MessageValidated codec.CellCodec[MessageValidated] -} - -type messageBuilder struct { - In inMessageBuilder - Out outMessageBuilder -} - -type builder struct { - Messages messageBuilder -} diff --git a/pkg/ccip/bindings/onramp/codec.go b/pkg/ccip/bindings/onramp/codec.go deleted file mode 100644 index f2f1581c7..000000000 --- a/pkg/ccip/bindings/onramp/codec.go +++ /dev/null @@ -1,43 +0,0 @@ -package onramp - -import ( - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - OnRampSend: codec.TLBCodec[Send](), - WithdrawJettons: codec.TLBCodec[WithdrawJettons](), - ExecutorFinishedSuccessfully: codec.TLBCodec[ExecutorFinishedSuccessfully](), - SetDynamicConfig: codec.TLBCodec[SetDynamicConfigMessage](), - UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigsMessage](), - UpdateAllowlists: codec.TLBCodec[UpdateAllowlistsMessage](), - }, - }, - Events: eventBuilder{ - CCIPMessageSent: codec.TLBCodec[CCIPMessageSent](), - }, -} - -type eventBuilder struct { - CCIPMessageSent codec.CellCodec[CCIPMessageSent] -} - -type inMessageBuilder struct { - OnRampSend codec.CellCodec[Send] - WithdrawJettons codec.CellCodec[WithdrawJettons] - ExecutorFinishedSuccessfully codec.CellCodec[ExecutorFinishedSuccessfully] - SetDynamicConfig codec.CellCodec[SetDynamicConfigMessage] - UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigsMessage] - UpdateAllowlists codec.CellCodec[UpdateAllowlistsMessage] -} - -type messageBuilder struct { - In inMessageBuilder -} - -type builder struct { - Messages messageBuilder - Events eventBuilder -} diff --git a/pkg/ccip/bindings/router/codec.go b/pkg/ccip/bindings/router/codec.go deleted file mode 100644 index cab33f868..000000000 --- a/pkg/ccip/bindings/router/codec.go +++ /dev/null @@ -1,40 +0,0 @@ -package router - -import ( - "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -// Router opcodes -const ( - OpcodeSetRamps = 0x10000001 - OpcodeCCIPSend = 0x00000001 -) - -// Router exit codes -const ( - ErrorDestChainNotEnabled tvm.ExitCode = tvm.ExitCode(0x1001) - ErrorUnknownMessage tvm.ExitCode = tvm.ExitCode(0x1002) -) - -var Builder = builder{ - Messages: messageBuilder{ - In: inMessageBuilder{ - SetRamps: codec.TLBCodec[SetRamps](), - CCIPSend: codec.TLBCodec[CCIPSend](), - }, - }, -} - -type inMessageBuilder struct { - SetRamps codec.CellCodec[SetRamps] - CCIPSend codec.CellCodec[CCIPSend] -} - -type messageBuilder struct { - In inMessageBuilder -} - -type builder struct { - Messages messageBuilder -} diff --git a/pkg/ccip/bindings/router/router.go b/pkg/ccip/bindings/router/router.go index fc887792a..3df467e96 100644 --- a/pkg/ccip/bindings/router/router.go +++ b/pkg/ccip/bindings/router/router.go @@ -8,6 +8,17 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +const ( + OpcodeSetRamps = 0x10000001 + OpcodeCCIPSend = 0x00000001 +) + +const ( + ErrorDestChainNotEnabled tvm.ExitCode = tvm.ExitCode(0x1001) + ErrorUnknownMessage tvm.ExitCode = tvm.ExitCode(0x1002) ) type Storage struct { diff --git a/pkg/ton/codec/builder.go b/pkg/ton/codec/builder.go deleted file mode 100644 index 03241e809..000000000 --- a/pkg/ton/codec/builder.go +++ /dev/null @@ -1,31 +0,0 @@ -package codec - -import ( - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" -) - -// CellCodec is an interface for encoding and decoding data of type T to and from TON Cells. -type CellCodec[T any] interface { - Encode(data T) (*cell.Builder, error) - Decode(src *cell.Slice) (T, error) -} - -// TLBCodec returns a CellCodec implementation that uses struct tlb tags for encoding and decoding. -// It wraps the `tlb.ToCell` and `tlb.LoadFromCell` functions from the tonutils-go/tlb package. -func TLBCodec[T any]() CellCodec[T] { - return &tlbCodec[T]{} -} - -type tlbCodec[T any] struct{} - -func (c *tlbCodec[T]) Encode(data T) (*cell.Builder, error) { - cell, err := tlb.ToCell(data) - return cell.ToBuilder(), err -} - -func (c *tlbCodec[T]) Decode(src *cell.Slice) (T, error) { - var data T - err := tlb.LoadFromCell(&data, src) - return data, err -} diff --git a/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go index 85be1c7c3..7163fc224 100644 --- a/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go +++ b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go @@ -2,6 +2,7 @@ package ccipsendexecutor import ( "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -46,7 +47,8 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { return nil, err } if opCode == ccipsendexecutor.OpcodeCCIPSendExecutorExecute { - execute, err := ccipsendexecutor.Builder.Messages.In.Execute.Decode(r) + var execute ccipsendexecutor.Execute + err := tlb.LoadFromCell(&execute, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go index 7b2560d1d..b044627fa 100644 --- a/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go +++ b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go @@ -2,6 +2,7 @@ package feequoter import ( "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -46,37 +47,43 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case feequoter.OpcodeUpdatePrices: - updatePrices, err := feequoter.Builder.Messages.In.UpdatePrices.Decode(r) + var updatePrices feequoter.UpdatePrices + err := tlb.LoadFromCell(&updatePrices, r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdatePrices", updatePrices) case feequoter.OpcodeUpdateFeeTokens: - updateFeeTokens, err := feequoter.Builder.Messages.In.UpdateFeeTokens.Decode(r) + var updateFeeTokens feequoter.UpdateFeeTokens + err := tlb.LoadFromCell(&updateFeeTokens, r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateFeeTokens", updateFeeTokens) case feequoter.OpcodeUpdateTokenTransferFeeConfigs: - updateConfigs, err := feequoter.Builder.Messages.In.UpdateTokenTransferFeeConfigs.Decode(r) + var updateConfigs feequoter.UpdateTokenTransferFeeConfigs + err := tlb.LoadFromCell(&updateConfigs, r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateTokenTransferFeeConfigs", updateConfigs) case feequoter.OpcodeUpdateDestChainConfigs: - updateDestConfigs, err := feequoter.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) + var updateDestConfigs feequoter.UpdateDestChainConfigs + err := tlb.LoadFromCell(&updateDestConfigs, r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestConfigs) case feequoter.OpcodeFeeQuoterGetValidatedFee: - getValidatedFee, err := feequoter.Builder.Messages.In.GetValidatedFee.Decode(r) + var getValidatedFee feequoter.GetValidatedFee + err := tlb.LoadFromCell(&getValidatedFee, r) if err != nil { return nil, err } return lib.NewMessageInfo("GetValidatedFee", getValidatedFee) case feequoter.OpcodeFeeQuoterMessageValidated: - messageValidated, err := feequoter.Builder.Messages.Out.MessageValidated.Decode(r) + var messageValidated feequoter.MessageValidated + err := tlb.LoadFromCell(&messageValidated, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/onramp/onramp.go b/pkg/ton/debug/decoders/ccip/onramp/onramp.go index 43fd99978..7cd6107fc 100644 --- a/pkg/ton/debug/decoders/ccip/onramp/onramp.go +++ b/pkg/ton/debug/decoders/ccip/onramp/onramp.go @@ -2,6 +2,7 @@ package onramp import ( "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -35,7 +36,8 @@ func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.Messa return nil, &lib.UnknownMessageError{} } if topic == onramp.TopicCCIPMessageSent { - ccipMessageSent, err := onramp.Builder.Events.CCIPMessageSent.Decode(msg.BeginParse()) + var ccipMessageSent onramp.CCIPMessageSent + err := tlb.LoadFromCell(&ccipMessageSent, msg.BeginParse()) if err != nil { return nil, err } @@ -62,37 +64,43 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case onramp.OpcodeOnRampSend: - onRampSend, err := onramp.Builder.Messages.In.OnRampSend.Decode(r) + var onRampSend onramp.Send + err := tlb.LoadFromCell(&onRampSend, r) if err != nil { return nil, err } return lib.NewMessageInfo("OnRampSend", onRampSend) case onramp.OpcodeOnRampWithdrawJettons: - withdrawJettons, err := onramp.Builder.Messages.In.WithdrawJettons.Decode(r) + var withdrawJettons onramp.WithdrawJettons + err := tlb.LoadFromCell(&withdrawJettons, r) if err != nil { return nil, err } return lib.NewMessageInfo("WithdrawJettons", withdrawJettons) case onramp.OpcodeOnRampExecutorFinishedSuccessfully: - executorFinished, err := onramp.Builder.Messages.In.ExecutorFinishedSuccessfully.Decode(r) + var executorFinished onramp.ExecutorFinishedSuccessfully + err := tlb.LoadFromCell(&executorFinished, r) if err != nil { return nil, err } return lib.NewMessageInfo("ExecutorFinishedSuccessfully", executorFinished) case onramp.OpcodeSetDynamicConfig: - setDynamicConfig, err := onramp.Builder.Messages.In.SetDynamicConfig.Decode(r) + var setDynamicConfig onramp.SetDynamicConfigMessage + err := tlb.LoadFromCell(&setDynamicConfig, r) if err != nil { return nil, err } return lib.NewMessageInfo("SetDynamicConfig", setDynamicConfig) case onramp.OpcodeUpdateDestChainConfigs: - updateDestChainConfigs, err := onramp.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) + var updateDestChainConfigs onramp.UpdateDestChainConfigsMessage + err := tlb.LoadFromCell(&updateDestChainConfigs, r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestChainConfigs) case onramp.OpcodeUpdateAllowlists: - updateAllowlists, err := onramp.Builder.Messages.In.UpdateAllowlists.Decode(r) + var updateAllowlists onramp.UpdateAllowlistsMessage + err := tlb.LoadFromCell(&updateAllowlists, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/router/router.go b/pkg/ton/debug/decoders/ccip/router/router.go index 281bc8338..a634751ef 100644 --- a/pkg/ton/debug/decoders/ccip/router/router.go +++ b/pkg/ton/debug/decoders/ccip/router/router.go @@ -2,6 +2,7 @@ package router import ( "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -47,13 +48,15 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case router.OpcodeSetRamps: - setRamps, err := router.Builder.Messages.In.SetRamps.Decode(r) + var setRamps router.SetRamps + err := tlb.LoadFromCell(&setRamps, r) if err != nil { return nil, err } return lib.NewMessageInfo("SetRamps", setRamps) case router.OpcodeCCIPSend: - ccipSend, err := router.Builder.Messages.In.CCIPSend.Decode(r) + var ccipSend router.CCIPSend + err := tlb.LoadFromCell(&ccipSend, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/common.go b/pkg/ton/debug/decoders/jetton/common.go index f68d5c787..c26c97ae2 100644 --- a/pkg/ton/debug/decoders/jetton/common.go +++ b/pkg/ton/debug/decoders/jetton/common.go @@ -1,6 +1,7 @@ package jetton import ( + "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" @@ -27,7 +28,8 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { return nil, err } if opCode == jetton.OpcodeTopUp { - topUp, err := jetton.Builder.Messages.In.TopUp.Decode(r) + var topUp jetton.TopUpMessage + err := tlb.LoadFromCell(&topUp, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go index b5242019e..63fb04ddf 100644 --- a/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go +++ b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go @@ -52,7 +52,8 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case minter.OpcodeMinterMint: - mint, err := minter.Builder.Messages.In.Mint.Decode(r) + var mint minter.MintMessage + err := tlb.LoadFromCell(&mint, r) if err != nil { return nil, err } @@ -71,13 +72,15 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { MasterMsg: wallet.InternalTransferDescription(mint.MasterMsg, payloadInfo), }) case minter.OpcodeMinterChangeAdmin: - changeAdmin, err := minter.Builder.Messages.In.ChangeAdmin.Decode(r) + var changeAdmin minter.ChangeAdminMessage + err := tlb.LoadFromCell(&changeAdmin, r) if err != nil { return nil, err } return lib.NewMessageInfo("ChangeAdmin", changeAdmin) case minter.OpcodeMinterClaimAdmin: - changeContent, err := minter.Builder.Messages.In.ClaimAdmin.Decode(r) + var changeContent minter.ClaimAdminMessage + err := tlb.LoadFromCell(&changeContent, r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go index 912728fbb..06859b3b1 100644 --- a/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go +++ b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go @@ -51,7 +51,8 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case wallet.OpcodeWalletTransfer: - askToTransfer, err := wallet.Builder.Messages.In.AskToTransfer.Decode(r) + var askToTransfer wallet.AskToTransfer + err := tlb.LoadFromCell(&askToTransfer, r) if err != nil { return nil, err } @@ -72,7 +73,8 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { }) } case wallet.OpcodeWalletInternalTransfer: - internalTransfer, err := wallet.Builder.Messages.In.InternalTransfer.Decode(r) + var internalTransfer wallet.InternalTransferMessage + err := tlb.LoadFromCell(&internalTransfer, r) if err != nil { return nil, err } From 7fb341a5c8e797f8b9c688262379ef47b6271579 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 19:31:02 -0300 Subject: [PATCH 42/45] fix: rm panic --- pkg/ton/debug/decoders/ccip/ccipcommon/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ton/debug/decoders/ccip/ccipcommon/common.go b/pkg/ton/debug/decoders/ccip/ccipcommon/common.go index f43458673..a02297b21 100644 --- a/pkg/ton/debug/decoders/ccip/ccipcommon/common.go +++ b/pkg/ton/debug/decoders/ccip/ccipcommon/common.go @@ -14,7 +14,7 @@ type decoder struct { // EventInfo implements lib.ContractDecoder. func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.MessageInfo, error) { - panic("unimplemented") + return nil, &lib.UnknownMessageError{} } // ExitCodeInfo implements lib.ContractDecoder. From 9c41962d4045bc758c87b2e08df6033d471dbd0e Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 19:31:46 -0300 Subject: [PATCH 43/45] fix: rm commented code --- pkg/ton/debug/pretty_print.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pkg/ton/debug/pretty_print.go b/pkg/ton/debug/pretty_print.go index 5c392742d..75d56ddd6 100644 --- a/pkg/ton/debug/pretty_print.go +++ b/pkg/ton/debug/pretty_print.go @@ -24,14 +24,6 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" ) -// func NewDebuggerFromEnv(env cldf.Environment, writer lib.DebuggerWriter) Debugger { -// return Debugger{ -// ExistingAddresses: env.GetAddressBook(), -// Contracts: make(map[*cldf.ContractType]lib.ContractDecoder), -// Writer: writer, -// } -// } - type DebuggerEnvironment struct { existingAddresses map[string]cldf.TypeAndVersion contracts map[cldf.ContractType]lib.ContractDecoder From 7bf0bb440f316c38fee31630a6a2e77b303a5d70 Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 19:39:50 -0300 Subject: [PATCH 44/45] chore: codehash matching not working properly --- pkg/ton/debug/explorer/explorer.go | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/pkg/ton/debug/explorer/explorer.go b/pkg/ton/debug/explorer/explorer.go index 58ac20534..2f6974324 100644 --- a/pkg/ton/debug/explorer/explorer.go +++ b/pkg/ton/debug/explorer/explorer.go @@ -438,9 +438,6 @@ func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDE result, err := c.connection.RunGetMethod(ctx, block, addr, "typeAndVersion") defer func() { }() - if err != nil { - return c.tryMatchByCodeHash(ctx, block, addr, knownActors) - } if err = typeVersion.FromResult(result); err != nil { return fmt.Errorf("failed to parse typeAndVersion: %w", err) } @@ -453,31 +450,6 @@ func (c *client) queryActorIfNotVisited(ctx context.Context, block *ton.BlockIDE return nil } -func (c *client) tryMatchByCodeHash(ctx context.Context, block *ton.BlockIDExt, addr *address.Address, knownActors map[string]deployment.TypeAndVersion) error { - account, err := c.connection.GetAccount(ctx, block, addr) - if err != nil { - return fmt.Errorf("get account: %w", err) - } - code := account.Code.ToBOC() - codeHex := hex.EncodeToString(code) - switch codeHex { - case "b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03": // https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/main/build/HighloadWalletV3.compiled.json - knownActors[addr.String()] = deployment.TypeAndVersion{ - Version: *semver.MustParse("3.2.0"), - Type: deployment.ContractType("org.ton.Wallet"), - } - return nil - case "b5ee9c7241021401000281000114ff00f4a413f4bcf2c80b01020120020d020148030402dcd020d749c120915b8f6320d70b1f2082106578746ebd21821073696e74bdb0925f03e082106578746eba8eb48020d72101d074d721fa4030fa44f828fa443058bd915be0ed44d0810141d721f4058307f40e6fa1319130e18040d721707fdb3ce03120d749810280b99130e070e2100f020120050c020120060902016e07080019adce76a2684020eb90eb85ffc00019af1df6a2684010eb90eb858fc00201480a0b0017b325fb51341c75c875c2c7e00011b262fb513435c280200019be5f0f6a2684080a0eb90fa02c0102f20e011e20d70b1f82107369676ebaf2e08a7f0f01e68ef0eda2edfb218308d722028308d723208020d721d31fd31fd31fed44d0d200d31f20d31fd3ffd70a000af90140ccf9109a28945f0adb31e1f2c087df02b35007b0f2d0845125baf2e0855036baf2e086f823bbf2d0882292f800de01a47fc8ca00cb1f01cf16c9ed542092f80fde70db3cd81003f6eda2edfb02f404216e926c218e4c0221d73930709421c700b38e2d01d72820761e436c20d749c008f2e09320d74ac002f2e09320d71d06c712c2005230b0f2d089d74cd7393001a4e86c128407bbf2e093d74ac000f2e093ed55e2d20001c000915be0ebd72c08142091709601d72c081c12e25210b1e30f20d74a111213009601fa4001fa44f828fa443058baf2e091ed44d0810141d718f405049d7fc8ca0040048307f453f2e08b8e14038307f45bf2e08c22d70a00216e01b3b0f2d090e2c85003cf1612f400c9ed54007230d72c08248e2d21f2e092d200ed44d0d2005113baf2d08f54503091319c01810140d721d70a00f2e08ee2c8ca0058cf16c9ed5493f2c08de20010935bdb31e1d74cd0b4d6c35e": // https://github.com/ton-blockchain/wallet-contract-v5/blob/main/build/wallet_v5.compiled.json - knownActors[addr.String()] = deployment.TypeAndVersion{ - Version: *semver.MustParse("3.1.0"), - Type: deployment.ContractType("org.ton.Wallet"), - } - return nil - // TODO add missing wallets - } - return nil -} - func (c *client) GetSenderAddressFromTxHash(ctx context.Context, txHashStr string) (*address.Address, error) { // fetch from https://testnet.toncenter.com/api/v3/transactions?hash=txHashStr var baseURL string From 1e33b098b45ac16d6e27754a6ebd644dddda227f Mon Sep 17 00:00:00 2001 From: Patricio Tourne Passarino Date: Tue, 14 Oct 2025 19:28:32 -0300 Subject: [PATCH 45/45] feat: codec interface --- pkg/bindings/jetton/common.go | 21 +++++ pkg/bindings/jetton/minter/codec.go | 88 +++++++++++++++++++ pkg/bindings/jetton/minter/minter.go | 49 ----------- pkg/bindings/jetton/wallet/codec.go | 84 ++++++++++++++++++ pkg/bindings/jetton/wallet/wallet.go | 45 ---------- .../ccipsendexecutor/ccipsendexecutor.go | 12 --- pkg/ccip/bindings/ccipsendexecutor/codec.go | 37 ++++++++ pkg/ccip/bindings/feequoter/codec.go | 41 +++++++++ pkg/ccip/bindings/onramp/codec.go | 43 +++++++++ pkg/ccip/bindings/router/codec.go | 40 +++++++++ pkg/ccip/bindings/router/router.go | 11 --- pkg/ton/codec/builder.go | 31 +++++++ .../ccip/ccipsendexecutor/ccipsendexecutor.go | 4 +- .../decoders/ccip/feequoter/feequoter.go | 19 ++-- pkg/ton/debug/decoders/ccip/onramp/onramp.go | 22 ++--- pkg/ton/debug/decoders/ccip/router/router.go | 7 +- pkg/ton/debug/decoders/jetton/common.go | 4 +- .../decoders/jetton/minter/jetton_minter.go | 9 +- .../decoders/jetton/wallet/jetton_wallet.go | 6 +- 19 files changed, 407 insertions(+), 166 deletions(-) create mode 100644 pkg/bindings/jetton/minter/codec.go create mode 100644 pkg/bindings/jetton/wallet/codec.go create mode 100644 pkg/ccip/bindings/ccipsendexecutor/codec.go create mode 100644 pkg/ccip/bindings/feequoter/codec.go create mode 100644 pkg/ccip/bindings/onramp/codec.go create mode 100644 pkg/ccip/bindings/router/codec.go create mode 100644 pkg/ton/codec/builder.go diff --git a/pkg/bindings/jetton/common.go b/pkg/bindings/jetton/common.go index c2e7c169d..e47975b5c 100644 --- a/pkg/bindings/jetton/common.go +++ b/pkg/bindings/jetton/common.go @@ -3,6 +3,7 @@ package jetton import ( "github.com/xssnick/tonutils-go/tlb" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" ) @@ -18,6 +19,26 @@ const ( ErrorWrongWorkchain tvm.ExitCode = tvm.ExitCode(333) ) +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + TopUp: codec.TLBCodec[TopUpMessage](), + }, + }, +} + +type inMessageBuilder struct { + TopUp codec.CellCodec[TopUpMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + // For funding the contract with TON type TopUpMessage struct { _ tlb.Magic `tlb:"#d372158c"` //nolint:revive // (opcode) should stay uninitialized diff --git a/pkg/bindings/jetton/minter/codec.go b/pkg/bindings/jetton/minter/codec.go new file mode 100644 index 000000000..3cbc5887d --- /dev/null +++ b/pkg/bindings/jetton/minter/codec.go @@ -0,0 +1,88 @@ +package minter + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +// JettonMinter opcodes +const ( + OpcodeMinterMint = 0x642b7d07 + OpcodeMinterChangeAdmin = 0x6501f354 + OpcodeMinterClaimAdmin = 0xfb88e119 + OpcodeMinterDropAdmin = 0x7431f221 + OpcodeMinterBurnNotification = 0x7bdd97de + OpcodeMinterChangeMetadataURL = 0xcb862902 + OpcodeWalletBurnNotification = 0x7bdd97de +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + Mint: codec.TLBCodec[MintMessage](), + ChangeAdmin: codec.TLBCodec[ChangeAdminMessage](), + ClaimAdmin: codec.TLBCodec[ClaimAdminMessage](), + DropAdmin: codec.TLBCodec[DropAdminMessage](), + ChangeContent: codec.TLBCodec[ChangeContentMessage](), + Upgrade: codec.TLBCodec[UpgradeMessage](), + }, + }, +} + +type inMessageBuilder struct { + Mint codec.CellCodec[MintMessage] + ChangeAdmin codec.CellCodec[ChangeAdminMessage] + ClaimAdmin codec.CellCodec[ClaimAdminMessage] + DropAdmin codec.CellCodec[DropAdminMessage] + ChangeContent codec.CellCodec[ChangeContentMessage] + Upgrade codec.CellCodec[UpgradeMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + +type MintMessage struct { + _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Destination *address.Address `tlb:"addr"` + TonAmount tlb.Coins `tlb:"."` + MasterMsg wallet.InternalTransferMessage `tlb:"^"` +} + +type ChangeAdminMessage struct { + _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewAdmin *address.Address `tlb:"addr"` +} + +type ClaimAdminMessage struct { + _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type DropAdminMessage struct { + _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` +} + +type ChangeContentMessage struct { + _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Content *cell.Cell `tlb:"^"` +} + +type UpgradeMessage struct { + _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + NewData *cell.Cell `tlb:"^"` + NewCode *cell.Cell `tlb:"^"` +} diff --git a/pkg/bindings/jetton/minter/minter.go b/pkg/bindings/jetton/minter/minter.go index 977d03ac8..d24f9b330 100644 --- a/pkg/bindings/jetton/minter/minter.go +++ b/pkg/bindings/jetton/minter/minter.go @@ -10,7 +10,6 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" - "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton/wallet" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) @@ -31,51 +30,3 @@ func Code() (*cell.Cell, error) { } return compiledContract, nil } - -// JettonMinter opcodes -const ( - OpcodeMinterMint = 0x642b7d07 - OpcodeMinterChangeAdmin = 0x6501f354 - OpcodeMinterClaimAdmin = 0xfb88e119 - OpcodeMinterDropAdmin = 0x7431f221 - OpcodeMinterBurnNotification = 0x7bdd97de - OpcodeMinterChangeMetadataURL = 0xcb862902 - OpcodeWalletBurnNotification = 0x7bdd97de -) - -type MintMessage struct { - _ tlb.Magic `tlb:"#642b7d07"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Destination *address.Address `tlb:"addr"` - TonAmount tlb.Coins `tlb:"."` - MasterMsg wallet.InternalTransferMessage `tlb:"^"` -} - -type ChangeAdminMessage struct { - _ tlb.Magic `tlb:"#6501f354"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewAdmin *address.Address `tlb:"addr"` -} - -type ClaimAdminMessage struct { - _ tlb.Magic `tlb:"#fb88e119"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type DropAdminMessage struct { - _ tlb.Magic `tlb:"#7431f221"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - -type ChangeContentMessage struct { - _ tlb.Magic `tlb:"#cb862902"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Content *cell.Cell `tlb:"^"` -} - -type UpgradeMessage struct { - _ tlb.Magic `tlb:"#2508d66a"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - NewData *cell.Cell `tlb:"^"` - NewCode *cell.Cell `tlb:"^"` -} diff --git a/pkg/bindings/jetton/wallet/codec.go b/pkg/bindings/jetton/wallet/codec.go new file mode 100644 index 000000000..22617b986 --- /dev/null +++ b/pkg/bindings/jetton/wallet/codec.go @@ -0,0 +1,84 @@ +package wallet + +import ( + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// JettonWallet opcodes +const ( + OpcodeWalletTransfer = 0x0f8a7ea5 + OpcodeWalletTransferNotification = 0x7362d09c + OpcodeWalletInternalTransfer = 0x178d4519 + OpcodeWalletExcesses = 0xd53276db + OpcodeWalletBurn = 0x595f07bc +) + +const ( + BalanceError tvm.ExitCode = tvm.ExitCode(47) + NotEnoughGas tvm.ExitCode = tvm.ExitCode(48) + InvalidMessage tvm.ExitCode = tvm.ExitCode(49) +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + AskToTransfer: codec.TLBCodec[AskToTransfer](), + InternalTransfer: codec.TLBCodec[InternalTransferMessage](), + }, + Out: outMessageBuilder{ + TransferNotification: codec.TLBCodec[TransferNotification](), + }, + }, +} + +type inMessageBuilder struct { + AskToTransfer codec.CellCodec[AskToTransfer] + InternalTransfer codec.CellCodec[InternalTransferMessage] +} + +type outMessageBuilder struct { + TransferNotification codec.CellCodec[TransferNotification] +} + +type messageBuilder struct { + In inMessageBuilder + Out outMessageBuilder +} + +type builder struct { + Messages messageBuilder +} + +type AskToTransfer struct { + _ tlb.Magic `tlb:"#0f8a7ea5"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + Destination *address.Address `tlb:"addr"` + ResponseDestination *address.Address `tlb:"addr"` + CustomPayload *cell.Cell `tlb:"either . ^"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type InternalTransferMessage struct { + _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"."` + From *address.Address `tlb:"addr"` + ResponseAddress *address.Address `tlb:"addr"` + ForwardTonAmount tlb.Coins `tlb:"."` + ForwardPayload *cell.Cell `tlb:"either . ^"` +} + +type TransferNotification struct { + _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag + QueryID uint64 `tlb:"## 64"` + Amount tlb.Coins `tlb:"^"` + Sender *address.Address `tlb:"addr"` + ForwardPayload *cell.Cell `tlb:"maybe ^"` +} diff --git a/pkg/bindings/jetton/wallet/wallet.go b/pkg/bindings/jetton/wallet/wallet.go index 792239762..a614afdeb 100644 --- a/pkg/bindings/jetton/wallet/wallet.go +++ b/pkg/bindings/jetton/wallet/wallet.go @@ -9,54 +9,9 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" "github.com/smartcontractkit/chainlink-ton/pkg/ton/wrappers" ) -// JettonWallet opcodes -const ( - OpcodeWalletTransfer = 0x0f8a7ea5 - OpcodeWalletTransferNotification = 0x7362d09c - OpcodeWalletInternalTransfer = 0x178d4519 - OpcodeWalletExcesses = 0xd53276db - OpcodeWalletBurn = 0x595f07bc -) - -const ( - BalanceError tvm.ExitCode = tvm.ExitCode(47) - NotEnoughGas tvm.ExitCode = tvm.ExitCode(48) - InvalidMessage tvm.ExitCode = tvm.ExitCode(49) -) - -type AskToTransfer struct { - _ tlb.Magic `tlb:"#0f8a7ea5"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"."` - Destination *address.Address `tlb:"addr"` - ResponseDestination *address.Address `tlb:"addr"` - CustomPayload *cell.Cell `tlb:"either . ^"` - ForwardTonAmount tlb.Coins `tlb:"."` - ForwardPayload *cell.Cell `tlb:"either . ^"` -} - -type InternalTransferMessage struct { - _ tlb.Magic `tlb:"#178d4519"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"."` - From *address.Address `tlb:"addr"` - ResponseAddress *address.Address `tlb:"addr"` - ForwardTonAmount tlb.Coins `tlb:"."` - ForwardPayload *cell.Cell `tlb:"either . ^"` -} - -type TransferNotification struct { - _ tlb.Magic `tlb:"#7362d09c"` //nolint:revive // Ignore opcode tag - QueryID uint64 `tlb:"## 64"` - Amount tlb.Coins `tlb:"^"` - Sender *address.Address `tlb:"addr"` - ForwardPayload *cell.Cell `tlb:"maybe ^"` -} - var WalletContractPath = path.Join(jetton.PathToContracts, "JettonWallet.compiled.json") type Provider struct { diff --git a/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go index 9cdb0bc75..224ab21ea 100644 --- a/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go +++ b/pkg/ccip/bindings/ccipsendexecutor/ccipsendexecutor.go @@ -9,18 +9,6 @@ import ( "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/onramp" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -// CCIPSend Executor opcodes -const ( - OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') -) - -// CCIPSend Executor exit codes -const ( - ErrorStateNotExpected tvm.ExitCode = tvm.ExitCode(500) - ErrorUnauthorized tvm.ExitCode = tvm.ExitCode(265) // ERROR_UNAUTHORIZED from contract ) // CCIPSendExecutor_Execute message structure diff --git a/pkg/ccip/bindings/ccipsendexecutor/codec.go b/pkg/ccip/bindings/ccipsendexecutor/codec.go new file mode 100644 index 000000000..fe0c92468 --- /dev/null +++ b/pkg/ccip/bindings/ccipsendexecutor/codec.go @@ -0,0 +1,37 @@ +package ccipsendexecutor + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// CCIPSend Executor opcodes +const ( + OpcodeCCIPSendExecutorExecute = 0xAF3C62B3 // crc32('CCIPSendExecutor_Execute') +) + +// CCIPSend Executor exit codes +const ( + ErrorStateNotExpected tvm.ExitCode = tvm.ExitCode(500) + ErrorUnauthorized tvm.ExitCode = tvm.ExitCode(265) // ERROR_UNAUTHORIZED from contract +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + Execute: codec.TLBCodec[Execute](), + }, + }, +} + +type inMessageBuilder struct { + Execute codec.CellCodec[Execute] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/feequoter/codec.go b/pkg/ccip/bindings/feequoter/codec.go new file mode 100644 index 000000000..922013d06 --- /dev/null +++ b/pkg/ccip/bindings/feequoter/codec.go @@ -0,0 +1,41 @@ +package feequoter + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + UpdatePrices: codec.TLBCodec[UpdatePrices](), + UpdateFeeTokens: codec.TLBCodec[UpdateFeeTokens](), + UpdateTokenTransferFeeConfigs: codec.TLBCodec[UpdateTokenTransferFeeConfigs](), + UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigs](), + GetValidatedFee: codec.TLBCodec[GetValidatedFee](), + }, + Out: outMessageBuilder{ + MessageValidated: codec.TLBCodec[MessageValidated](), + }, + }, +} + +type inMessageBuilder struct { + UpdatePrices codec.CellCodec[UpdatePrices] + UpdateFeeTokens codec.CellCodec[UpdateFeeTokens] + UpdateTokenTransferFeeConfigs codec.CellCodec[UpdateTokenTransferFeeConfigs] + UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigs] + GetValidatedFee codec.CellCodec[GetValidatedFee] +} + +type outMessageBuilder struct { + MessageValidated codec.CellCodec[MessageValidated] +} + +type messageBuilder struct { + In inMessageBuilder + Out outMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/onramp/codec.go b/pkg/ccip/bindings/onramp/codec.go new file mode 100644 index 000000000..f2f1581c7 --- /dev/null +++ b/pkg/ccip/bindings/onramp/codec.go @@ -0,0 +1,43 @@ +package onramp + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + OnRampSend: codec.TLBCodec[Send](), + WithdrawJettons: codec.TLBCodec[WithdrawJettons](), + ExecutorFinishedSuccessfully: codec.TLBCodec[ExecutorFinishedSuccessfully](), + SetDynamicConfig: codec.TLBCodec[SetDynamicConfigMessage](), + UpdateDestChainConfigs: codec.TLBCodec[UpdateDestChainConfigsMessage](), + UpdateAllowlists: codec.TLBCodec[UpdateAllowlistsMessage](), + }, + }, + Events: eventBuilder{ + CCIPMessageSent: codec.TLBCodec[CCIPMessageSent](), + }, +} + +type eventBuilder struct { + CCIPMessageSent codec.CellCodec[CCIPMessageSent] +} + +type inMessageBuilder struct { + OnRampSend codec.CellCodec[Send] + WithdrawJettons codec.CellCodec[WithdrawJettons] + ExecutorFinishedSuccessfully codec.CellCodec[ExecutorFinishedSuccessfully] + SetDynamicConfig codec.CellCodec[SetDynamicConfigMessage] + UpdateDestChainConfigs codec.CellCodec[UpdateDestChainConfigsMessage] + UpdateAllowlists codec.CellCodec[UpdateAllowlistsMessage] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder + Events eventBuilder +} diff --git a/pkg/ccip/bindings/router/codec.go b/pkg/ccip/bindings/router/codec.go new file mode 100644 index 000000000..cab33f868 --- /dev/null +++ b/pkg/ccip/bindings/router/codec.go @@ -0,0 +1,40 @@ +package router + +import ( + "github.com/smartcontractkit/chainlink-ton/pkg/ton/codec" + "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" +) + +// Router opcodes +const ( + OpcodeSetRamps = 0x10000001 + OpcodeCCIPSend = 0x00000001 +) + +// Router exit codes +const ( + ErrorDestChainNotEnabled tvm.ExitCode = tvm.ExitCode(0x1001) + ErrorUnknownMessage tvm.ExitCode = tvm.ExitCode(0x1002) +) + +var Builder = builder{ + Messages: messageBuilder{ + In: inMessageBuilder{ + SetRamps: codec.TLBCodec[SetRamps](), + CCIPSend: codec.TLBCodec[CCIPSend](), + }, + }, +} + +type inMessageBuilder struct { + SetRamps codec.CellCodec[SetRamps] + CCIPSend codec.CellCodec[CCIPSend] +} + +type messageBuilder struct { + In inMessageBuilder +} + +type builder struct { + Messages messageBuilder +} diff --git a/pkg/ccip/bindings/router/router.go b/pkg/ccip/bindings/router/router.go index 3df467e96..fc887792a 100644 --- a/pkg/ccip/bindings/router/router.go +++ b/pkg/ccip/bindings/router/router.go @@ -8,17 +8,6 @@ import ( "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/ccip/bindings/common" - "github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm" -) - -const ( - OpcodeSetRamps = 0x10000001 - OpcodeCCIPSend = 0x00000001 -) - -const ( - ErrorDestChainNotEnabled tvm.ExitCode = tvm.ExitCode(0x1001) - ErrorUnknownMessage tvm.ExitCode = tvm.ExitCode(0x1002) ) type Storage struct { diff --git a/pkg/ton/codec/builder.go b/pkg/ton/codec/builder.go new file mode 100644 index 000000000..03241e809 --- /dev/null +++ b/pkg/ton/codec/builder.go @@ -0,0 +1,31 @@ +package codec + +import ( + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +// CellCodec is an interface for encoding and decoding data of type T to and from TON Cells. +type CellCodec[T any] interface { + Encode(data T) (*cell.Builder, error) + Decode(src *cell.Slice) (T, error) +} + +// TLBCodec returns a CellCodec implementation that uses struct tlb tags for encoding and decoding. +// It wraps the `tlb.ToCell` and `tlb.LoadFromCell` functions from the tonutils-go/tlb package. +func TLBCodec[T any]() CellCodec[T] { + return &tlbCodec[T]{} +} + +type tlbCodec[T any] struct{} + +func (c *tlbCodec[T]) Encode(data T) (*cell.Builder, error) { + cell, err := tlb.ToCell(data) + return cell.ToBuilder(), err +} + +func (c *tlbCodec[T]) Decode(src *cell.Slice) (T, error) { + var data T + err := tlb.LoadFromCell(&data, src) + return data, err +} diff --git a/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go index 7163fc224..85be1c7c3 100644 --- a/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go +++ b/pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go @@ -2,7 +2,6 @@ package ccipsendexecutor import ( "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -47,8 +46,7 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { return nil, err } if opCode == ccipsendexecutor.OpcodeCCIPSendExecutorExecute { - var execute ccipsendexecutor.Execute - err := tlb.LoadFromCell(&execute, r) + execute, err := ccipsendexecutor.Builder.Messages.In.Execute.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go index b044627fa..7b2560d1d 100644 --- a/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go +++ b/pkg/ton/debug/decoders/ccip/feequoter/feequoter.go @@ -2,7 +2,6 @@ package feequoter import ( "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -47,43 +46,37 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case feequoter.OpcodeUpdatePrices: - var updatePrices feequoter.UpdatePrices - err := tlb.LoadFromCell(&updatePrices, r) + updatePrices, err := feequoter.Builder.Messages.In.UpdatePrices.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdatePrices", updatePrices) case feequoter.OpcodeUpdateFeeTokens: - var updateFeeTokens feequoter.UpdateFeeTokens - err := tlb.LoadFromCell(&updateFeeTokens, r) + updateFeeTokens, err := feequoter.Builder.Messages.In.UpdateFeeTokens.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateFeeTokens", updateFeeTokens) case feequoter.OpcodeUpdateTokenTransferFeeConfigs: - var updateConfigs feequoter.UpdateTokenTransferFeeConfigs - err := tlb.LoadFromCell(&updateConfigs, r) + updateConfigs, err := feequoter.Builder.Messages.In.UpdateTokenTransferFeeConfigs.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateTokenTransferFeeConfigs", updateConfigs) case feequoter.OpcodeUpdateDestChainConfigs: - var updateDestConfigs feequoter.UpdateDestChainConfigs - err := tlb.LoadFromCell(&updateDestConfigs, r) + updateDestConfigs, err := feequoter.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestConfigs) case feequoter.OpcodeFeeQuoterGetValidatedFee: - var getValidatedFee feequoter.GetValidatedFee - err := tlb.LoadFromCell(&getValidatedFee, r) + getValidatedFee, err := feequoter.Builder.Messages.In.GetValidatedFee.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("GetValidatedFee", getValidatedFee) case feequoter.OpcodeFeeQuoterMessageValidated: - var messageValidated feequoter.MessageValidated - err := tlb.LoadFromCell(&messageValidated, r) + messageValidated, err := feequoter.Builder.Messages.Out.MessageValidated.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/onramp/onramp.go b/pkg/ton/debug/decoders/ccip/onramp/onramp.go index 7cd6107fc..43fd99978 100644 --- a/pkg/ton/debug/decoders/ccip/onramp/onramp.go +++ b/pkg/ton/debug/decoders/ccip/onramp/onramp.go @@ -2,7 +2,6 @@ package onramp import ( "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -36,8 +35,7 @@ func (d *decoder) EventInfo(dstAddr *address.Address, msg *cell.Cell) (lib.Messa return nil, &lib.UnknownMessageError{} } if topic == onramp.TopicCCIPMessageSent { - var ccipMessageSent onramp.CCIPMessageSent - err := tlb.LoadFromCell(&ccipMessageSent, msg.BeginParse()) + ccipMessageSent, err := onramp.Builder.Events.CCIPMessageSent.Decode(msg.BeginParse()) if err != nil { return nil, err } @@ -64,43 +62,37 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case onramp.OpcodeOnRampSend: - var onRampSend onramp.Send - err := tlb.LoadFromCell(&onRampSend, r) + onRampSend, err := onramp.Builder.Messages.In.OnRampSend.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("OnRampSend", onRampSend) case onramp.OpcodeOnRampWithdrawJettons: - var withdrawJettons onramp.WithdrawJettons - err := tlb.LoadFromCell(&withdrawJettons, r) + withdrawJettons, err := onramp.Builder.Messages.In.WithdrawJettons.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("WithdrawJettons", withdrawJettons) case onramp.OpcodeOnRampExecutorFinishedSuccessfully: - var executorFinished onramp.ExecutorFinishedSuccessfully - err := tlb.LoadFromCell(&executorFinished, r) + executorFinished, err := onramp.Builder.Messages.In.ExecutorFinishedSuccessfully.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("ExecutorFinishedSuccessfully", executorFinished) case onramp.OpcodeSetDynamicConfig: - var setDynamicConfig onramp.SetDynamicConfigMessage - err := tlb.LoadFromCell(&setDynamicConfig, r) + setDynamicConfig, err := onramp.Builder.Messages.In.SetDynamicConfig.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("SetDynamicConfig", setDynamicConfig) case onramp.OpcodeUpdateDestChainConfigs: - var updateDestChainConfigs onramp.UpdateDestChainConfigsMessage - err := tlb.LoadFromCell(&updateDestChainConfigs, r) + updateDestChainConfigs, err := onramp.Builder.Messages.In.UpdateDestChainConfigs.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestChainConfigs) case onramp.OpcodeUpdateAllowlists: - var updateAllowlists onramp.UpdateAllowlistsMessage - err := tlb.LoadFromCell(&updateAllowlists, r) + updateAllowlists, err := onramp.Builder.Messages.In.UpdateAllowlists.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/ccip/router/router.go b/pkg/ton/debug/decoders/ccip/router/router.go index a634751ef..281bc8338 100644 --- a/pkg/ton/debug/decoders/ccip/router/router.go +++ b/pkg/ton/debug/decoders/ccip/router/router.go @@ -2,7 +2,6 @@ package router import ( "github.com/xssnick/tonutils-go/address" - "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment" @@ -48,15 +47,13 @@ func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case router.OpcodeSetRamps: - var setRamps router.SetRamps - err := tlb.LoadFromCell(&setRamps, r) + setRamps, err := router.Builder.Messages.In.SetRamps.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("SetRamps", setRamps) case router.OpcodeCCIPSend: - var ccipSend router.CCIPSend - err := tlb.LoadFromCell(&ccipSend, r) + ccipSend, err := router.Builder.Messages.In.CCIPSend.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/common.go b/pkg/ton/debug/decoders/jetton/common.go index c26c97ae2..f68d5c787 100644 --- a/pkg/ton/debug/decoders/jetton/common.go +++ b/pkg/ton/debug/decoders/jetton/common.go @@ -1,7 +1,6 @@ package jetton import ( - "github.com/xssnick/tonutils-go/tlb" "github.com/xssnick/tonutils-go/tvm/cell" "github.com/smartcontractkit/chainlink-ton/pkg/bindings/jetton" @@ -28,8 +27,7 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { return nil, err } if opCode == jetton.OpcodeTopUp { - var topUp jetton.TopUpMessage - err := tlb.LoadFromCell(&topUp, r) + topUp, err := jetton.Builder.Messages.In.TopUp.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go index 63fb04ddf..b5242019e 100644 --- a/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go +++ b/pkg/ton/debug/decoders/jetton/minter/jetton_minter.go @@ -52,8 +52,7 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case minter.OpcodeMinterMint: - var mint minter.MintMessage - err := tlb.LoadFromCell(&mint, r) + mint, err := minter.Builder.Messages.In.Mint.Decode(r) if err != nil { return nil, err } @@ -72,15 +71,13 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { MasterMsg: wallet.InternalTransferDescription(mint.MasterMsg, payloadInfo), }) case minter.OpcodeMinterChangeAdmin: - var changeAdmin minter.ChangeAdminMessage - err := tlb.LoadFromCell(&changeAdmin, r) + changeAdmin, err := minter.Builder.Messages.In.ChangeAdmin.Decode(r) if err != nil { return nil, err } return lib.NewMessageInfo("ChangeAdmin", changeAdmin) case minter.OpcodeMinterClaimAdmin: - var changeContent minter.ClaimAdminMessage - err := tlb.LoadFromCell(&changeContent, r) + changeContent, err := minter.Builder.Messages.In.ClaimAdmin.Decode(r) if err != nil { return nil, err } diff --git a/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go index 06859b3b1..912728fbb 100644 --- a/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go +++ b/pkg/ton/debug/decoders/jetton/wallet/jetton_wallet.go @@ -51,8 +51,7 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { } switch opCode { case wallet.OpcodeWalletTransfer: - var askToTransfer wallet.AskToTransfer - err := tlb.LoadFromCell(&askToTransfer, r) + askToTransfer, err := wallet.Builder.Messages.In.AskToTransfer.Decode(r) if err != nil { return nil, err } @@ -73,8 +72,7 @@ func (j *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) { }) } case wallet.OpcodeWalletInternalTransfer: - var internalTransfer wallet.InternalTransferMessage - err := tlb.LoadFromCell(&internalTransfer, r) + internalTransfer, err := wallet.Builder.Messages.In.InternalTransfer.Decode(r) if err != nil { return nil, err }