Skip to content

Commit ddb6854

Browse files
authored
TRON network support (#1568)
TRON network support
1 parent 661546a commit ddb6854

File tree

12 files changed

+245
-5
lines changed

12 files changed

+245
-5
lines changed

.github/workflows/framework-golden-tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ jobs:
3030
config: smoke_aptos.toml
3131
count: 1
3232
timeout: 10m
33+
- name: TestTRONSmoke
34+
config: smoke_tron.toml
35+
count: 1
36+
timeout: 10m
3337
- name: TestSolanaSmoke
3438
config: smoke_solana.toml
3539
count: 1

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
- [Solana](framework/components/blockchains/solana.md)
4040
- [Aptos](framework/components/blockchains/aptos.md)
4141
- [Sui](framework/components/blockchains/sui.md)
42+
- [TRON](framework/components/blockchains/tron.md)
4243
- [Optimism Stack]()
4344
- [Arbitrum Stack]()
4445
- [Chainlink](framework/components/chainlink.md)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# TRON Blockchain Client
2+
3+
## Configuration
4+
```toml
5+
[blockchain_a]
6+
type = "tron"
7+
# image = "tronbox/tre" is default image
8+
```
9+
Default port is `9090`
10+
11+
## Usage
12+
```golang
13+
package examples
14+
15+
import (
16+
"github.com/smartcontractkit/chainlink-testing-framework/framework"
17+
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
18+
"github.com/stretchr/testify/require"
19+
"testing"
20+
)
21+
22+
type CfgTron struct {
23+
BlockchainA *blockchain.Input `toml:"blockchain_a" validate:"required"`
24+
}
25+
26+
func TestTRONSmoke(t *testing.T) {
27+
in, err := framework.Load[CfgTron](t)
28+
require.NoError(t, err)
29+
30+
bc, err := blockchain.NewBlockchainNetwork(in.BlockchainA)
31+
require.NoError(t, err)
32+
33+
// all private keys are funded
34+
_ = blockchain.TRONAccounts.PrivateKeys[0]
35+
36+
t.Run("test something", func(t *testing.T) {
37+
// use internal URL to connect Chainlink nodes
38+
_ = bc.Nodes[0].DockerInternalHTTPUrl
39+
// use host URL to interact
40+
_ = bc.Nodes[0].HostHTTPUrl
41+
42+
// use bc.Nodes[0].HostHTTPUrl + "/wallet" to access full node
43+
// use bc.Nodes[0].HostHTTPUrl + "/walletsolidity" to access Solidity node
44+
})
45+
}
46+
```
47+
48+
## More info
49+
50+
Follow the [guide](https://developers.tron.network/reference/tronbox-quickstart) if you want to work with `TRONBox` environment via JS
51+
52+
## Golang HTTP Client
53+
54+
TRON doesn't have any library to interact with it in `Golang` but we maintain our internal fork [here](https://github.com/smartcontractkit/chainlink-internal-integrations/tree/69e35041cdea0bc38ddf642aa93fd3cc3fb5d0d9/tron/relayer/gotron-sdk)
55+
56+
Check TRON [HTTP API](https://tronprotocol.github.io/documentation-en/api/http/)
57+
58+
Full node is on `:9090/wallet`
59+
```
60+
curl -X POST http://127.0.0.1:9090/wallet/createtransaction -d '{
61+
"owner_address": "TRGhNNfnmgLegT4zHNjEqDSADjgmnHvubJ",
62+
"to_address": "TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW",
63+
"amount": 1000000,
64+
"visible": true
65+
}'
66+
```
67+
68+
Solidity node is on `:9090/walletsolidity`
69+
```
70+
curl -X POST http://127.0.0.1:9090/walletsolidity/getaccount -d '{"address": "41E552F6487585C2B58BC2C9BB4492BC1F17132CD0"}'
71+
```

framework/.changeset/v0.4.5.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Add TRON network support

framework/cmd/observability/compose/docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ services:
1919
- /var/run/docker.sock:/var/run/docker.sock
2020
- ./conf/prometheus.yml:/etc/prometheus/prometheus.yml
2121
ports:
22-
- "9090:9090"
22+
- "9999:9090"
2323
loki:
2424
image: grafana/loki:2.5.0
2525
volumes:

framework/components/blockchain/blockchain.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
// Input is a blockchain network configuration params
99
type Input struct {
1010
// Common EVM fields
11-
Type string `toml:"type" validate:"required,oneof=anvil geth besu solana aptos sui" envconfig:"net_type"`
11+
Type string `toml:"type" validate:"required,oneof=anvil geth besu solana aptos tron sui" envconfig:"net_type"`
1212
Image string `toml:"image"`
1313
PullImage bool `toml:"pull_image"`
1414
Port string `toml:"port"`
@@ -71,6 +71,8 @@ func NewBlockchainNetwork(in *Input) (*Output, error) {
7171
out, err = newAptos(in)
7272
case "sui":
7373
out, err = newSui(in)
74+
case "tron":
75+
out, err = newTron(in)
7476
default:
7577
return nil, fmt.Errorf("blockchain type is not supported or empty, must be 'anvil' or 'geth'")
7678
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package blockchain
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/docker/docker/api/types/container"
8+
"github.com/smartcontractkit/chainlink-testing-framework/framework"
9+
"os"
10+
"time"
11+
12+
"github.com/testcontainers/testcontainers-go"
13+
"github.com/testcontainers/testcontainers-go/wait"
14+
)
15+
16+
type Accounts struct {
17+
HDPath string `json:"hdPath"`
18+
Mnemonic string `json:"mnemonic"`
19+
PrivateKeys []string `json:"privateKeys"`
20+
More []string `json:"more"`
21+
}
22+
23+
var TRONAccounts = Accounts{
24+
HDPath: "m/44'/195'/0'/0/",
25+
Mnemonic: "resemble birth wool happy sun burger fatal trumpet globe purity health ritual",
26+
PrivateKeys: []string{
27+
"932a39242805a1b1095638027f26af9664d1d5bf8ab3b7527ee75e7efb2946dd",
28+
"1c17c9c049d36cde7e5ea99df6c86e0474b04f0e258ab619a1e674f397a17152",
29+
"458130a239671674746582184711a6f8d633355df1a491b9f3b323576134c2e9",
30+
"2676fd1427968e07feaa9aff967d4ba7607c5497c499968c098d0517cd75cfbb",
31+
"d26b24a691ff2b03ee6ab65bf164def216f73574996b9ca6299c43a9a63767ac",
32+
"55df6adf3d081944dbe4688205d94f236fb4427ac44f3a286a96d47db0860667",
33+
"8a9a60ddd722a40753c2a38edd6b6fa38e806d681c9b08a520ba4912e62b6458",
34+
"75eb182fb623acf5e53d9885c4e8578f2530533a96c753481cc4277ecc6022de",
35+
"6c4b22b1d9d68ef7a8ecd151cd4ffdd4ecc2a7b3a3f8a9f9f9bbdbcef6671f10",
36+
"e578d66453cb41b6c923b9caa91c375a0545eeb171ccafc60b46fa834ce5c200",
37+
},
38+
// should not be empty, otherwise TRE will panic
39+
More: []string{},
40+
}
41+
42+
const (
43+
DefaultTronPort = "9090"
44+
)
45+
46+
func defaultTron(in *Input) {
47+
if in.Image == "" {
48+
in.Image = "tronbox/tre"
49+
}
50+
if in.Port == "" {
51+
in.Port = DefaultTronPort
52+
}
53+
}
54+
55+
func newTron(in *Input) (*Output, error) {
56+
defaultTron(in)
57+
ctx := context.Background()
58+
59+
containerName := framework.DefaultTCName("blockchain-node")
60+
bindPort := fmt.Sprintf("%s/tcp", in.Port)
61+
62+
accounts, err := os.CreateTemp("", "accounts.json")
63+
if err != nil {
64+
return nil, err
65+
}
66+
accountsData, err := json.Marshal(TRONAccounts)
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
_, err = accounts.WriteString(string(accountsData))
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
req := testcontainers.ContainerRequest{
77+
AlwaysPullImage: in.PullImage,
78+
Image: in.Image,
79+
Name: containerName,
80+
ExposedPorts: []string{bindPort},
81+
Networks: []string{framework.DefaultNetworkName},
82+
NetworkAliases: map[string][]string{
83+
framework.DefaultNetworkName: {containerName},
84+
},
85+
Labels: framework.DefaultTCLabels(),
86+
HostConfigModifier: func(h *container.HostConfig) {
87+
h.PortBindings = framework.MapTheSamePort(bindPort)
88+
},
89+
WaitingFor: wait.ForLog("Mnemonic").WithPollInterval(200 * time.Millisecond).WithStartupTimeout(1 * time.Minute),
90+
Files: []testcontainers.ContainerFile{
91+
{
92+
HostFilePath: accounts.Name(),
93+
ContainerFilePath: "/config/accounts.json",
94+
FileMode: 0644,
95+
},
96+
},
97+
}
98+
99+
c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
100+
ContainerRequest: req,
101+
Started: true,
102+
})
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
host, err := c.Host(ctx)
108+
if err != nil {
109+
return nil, err
110+
}
111+
112+
return &Output{
113+
UseCache: true,
114+
ChainID: in.ChainID,
115+
Family: "tron",
116+
ContainerName: containerName,
117+
Nodes: []*Node{
118+
{
119+
HostHTTPUrl: fmt.Sprintf("http://%s:%s", host, in.Port),
120+
DockerInternalHTTPUrl: fmt.Sprintf("http://%s:%s", containerName, in.Port),
121+
},
122+
},
123+
}, nil
124+
}

framework/components/blockchain/verify.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import (
66
)
77

88
// VerifyContract wraps the forge verify-contract command.
9-
func VerifyContract(out *Output, address, foundryDir, contractFile, contractName string) error {
9+
func VerifyContract(out *Output, address, foundryDir, contractFile, contractName, compilerVersion string) error {
1010
args := []string{
1111
"verify-contract",
1212
"--rpc-url", out.Nodes[0].HostHTTPUrl,
1313
"--chain-id",
1414
out.ChainID,
15-
"--compiler-version=0.8.24",
15+
fmt.Sprintf("--compiler-version=%s", compilerVersion),
1616
address,
1717
fmt.Sprintf("%s:%s", contractFile, contractName),
1818
"--verifier", "blockscout",

framework/examples/myproject/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ require (
1414
github.com/blocto/solana-go-sdk v1.30.0
1515
github.com/ethereum/go-ethereum v1.14.11
1616
github.com/go-resty/resty/v2 v2.15.3
17-
github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.1
17+
github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.4
1818
github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.10
1919
github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2
2020
github.com/stretchr/testify v1.10.0
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[blockchain_a]
2+
type = "tron"
3+
image = "tronbox/tre"

0 commit comments

Comments
 (0)