-
Notifications
You must be signed in to change notification settings - Fork 3
Extend cldf timelock converter logic for TON #628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
3261478
ce292f9
76f7941
6b03e06
bb6622b
564f880
fa6aa6c
580e5c7
d139579
e0493eb
8c9b9ff
b703c08
a68db89
d440c1d
060c95e
4a13173
5f800a9
02d0258
588016c
3d3a6ba
95337bb
c434940
781a16b
284e77e
2e6c227
06dd941
4168b5e
120f23b
d58f919
ad23d0e
8dcbd7a
022e0df
075de4e
e5efbd0
b25e6bc
42d488c
ced4bfd
62b9727
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -13,7 +13,6 @@ import ( | |||||
| "github.com/avast/retry-go/v4" | ||||||
| "github.com/testcontainers/testcontainers-go" | ||||||
|
|
||||||
| "github.com/xssnick/tonutils-go/address" | ||||||
| "github.com/xssnick/tonutils-go/tlb" | ||||||
| "github.com/xssnick/tonutils-go/ton" | ||||||
| "github.com/xssnick/tonutils-go/ton/wallet" | ||||||
|
|
@@ -34,6 +33,9 @@ const ( | |||||
|
|
||||||
| // supportedTONImageRepository is the only supported Docker image repository for TON localnet. | ||||||
| supportedTONImageRepository = "ghcr.io/neodix42/mylocalton-docker" | ||||||
|
|
||||||
| // defaultTxTONAmount is the default amount of TON to use for transactions. | ||||||
| defaultTxTONAmount = "0.1" | ||||||
| ) | ||||||
|
|
||||||
| // CTFChainProviderConfig holds the configuration to initialize the CTFChainProvider. | ||||||
|
|
@@ -122,18 +124,15 @@ func (p *CTFChainProvider) Initialize(ctx context.Context) (chain.BlockChain, er | |||||
| return nil, fmt.Errorf("failed to create wallet: %w", err) | ||||||
| } | ||||||
|
|
||||||
| // airdrop the deployer wallet | ||||||
| ferr := fundTonWallets(ctx, nodeClient, []*address.Address{tonWallet.Address()}, []tlb.Coins{tlb.MustFromTON("1000")}) | ||||||
| if ferr != nil { | ||||||
| return nil, fmt.Errorf("failed to fund wallet: %w", ferr) | ||||||
| } | ||||||
|
Comment on lines
-129
to
-133
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Omitting fund logic from network setup makes sense to me(if I am reading it right), but just a reminder that integration tests in core and chainlink-ton are relying on the deployer wallet to fund transmitters:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, think we removed this as we discussed that the integration tests already funded the deployer wallet |
||||||
|
|
||||||
| p.chain = &cldf_ton.Chain{ | ||||||
| ChainMetadata: cldf_ton.ChainMetadata{Selector: p.selector}, | ||||||
| Client: nodeClient, | ||||||
|
huangzhen1997 marked this conversation as resolved.
|
||||||
| Wallet: tonWallet, | ||||||
| WalletAddress: tonWallet.Address(), | ||||||
| WalletAddress: tonWallet.WalletAddress(), | ||||||
|
||||||
| WalletAddress: tonWallet.WalletAddress(), | |
| WalletAddress: tonWallet.Address(), |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import ( | |
| "strings" | ||
|
|
||
| "github.com/xssnick/tonutils-go/liteclient" | ||
| "github.com/xssnick/tonutils-go/tlb" | ||
| tonlib "github.com/xssnick/tonutils-go/ton" | ||
| "github.com/xssnick/tonutils-go/ton/wallet" | ||
|
|
||
|
|
@@ -22,6 +23,8 @@ const ( | |
| WalletVersionV4R2 WalletVersion = "V4R2" | ||
| WalletVersionV5R1 WalletVersion = "V5R1" | ||
| WalletVersionDefault WalletVersion = "" | ||
|
|
||
| defaultAmountTonString = "0.1" // Default amount in TON for transactions | ||
|
huangzhen1997 marked this conversation as resolved.
Outdated
|
||
| ) | ||
|
|
||
| // RPCChainProviderConfig holds the configuration to initialize the RPCChainProvider. | ||
|
|
@@ -173,17 +176,26 @@ func (p *RPCChainProvider) Initialize(ctx context.Context) (chain.BlockChain, er | |
| return nil, err | ||
| } | ||
|
|
||
| p.chain = &ton.Chain{ | ||
| p.chain = buildChain(p.selector, api, tonWallet, p.config.HTTPURL) | ||
|
|
||
| return *p.chain, nil | ||
| } | ||
|
|
||
| // buildChain creates a ton.Chain with the given parameters and default TxOps amount. | ||
| func buildChain(selector uint64, api *tonlib.APIClient, tonWallet *wallet.Wallet, httpURL string) *ton.Chain { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what's the purpose of this method, which just instantiates the type vs just doing it without the method? Then we also have a |
||
| return &ton.Chain{ | ||
| ChainMetadata: ton.ChainMetadata{ | ||
| Selector: p.selector, | ||
| Selector: selector, | ||
| }, | ||
| Client: api, | ||
| Wallet: tonWallet, | ||
| WalletAddress: tonWallet.WalletAddress(), | ||
| URL: p.config.HTTPURL, | ||
| URL: httpURL, | ||
| TxOps: ton.TxOps{ | ||
| Wallet: tonWallet, | ||
| Amount: tlb.MustFromTON(defaultAmountTonString), | ||
| }, | ||
| } | ||
|
|
||
| return *p.chain, nil | ||
| } | ||
|
|
||
| // createLiteclientConnectionPool creates connection pool returning concrete type for production use | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,8 @@ import ( | |||||
|
|
||||||
| "github.com/stretchr/testify/assert" | ||||||
| "github.com/stretchr/testify/require" | ||||||
| "github.com/xssnick/tonutils-go/tlb" | ||||||
| "github.com/xssnick/tonutils-go/ton/wallet" | ||||||
|
huangzhen1997 marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| tonchain "github.com/smartcontractkit/chainlink-deployments-framework/chain/ton" | ||||||
| ) | ||||||
|
|
@@ -89,6 +91,22 @@ func Test_RPCChainProvider_Initialize(t *testing.T) { | |||||
| assert.Equal(t, existingChain.Selector, gotChain.Selector) | ||||||
| } | ||||||
|
|
||||||
| func Test_RPCChainProvider_Initialize_InvalidConfig(t *testing.T) { | ||||||
| t.Parallel() | ||||||
|
|
||||||
| p := &RPCChainProvider{ | ||||||
| selector: 123, | ||||||
| config: RPCChainProviderConfig{ | ||||||
| HTTPURL: "", // invalid - missing URL | ||||||
|
||||||
| HTTPURL: "", // invalid - missing URL | |
| HTTPURL: "", // invalid: empty URL to test validation of missing/empty configuration |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -5,16 +5,25 @@ import ( | |||
| "github.com/xssnick/tonutils-go/ton" | ||||
| "github.com/xssnick/tonutils-go/ton/wallet" | ||||
|
|
||||
| "github.com/xssnick/tonutils-go/tlb" | ||||
|
|
||||
| "github.com/smartcontractkit/chainlink-deployments-framework/chain/internal/common" | ||||
| ) | ||||
|
|
||||
| type ChainMetadata = common.ChainMetadata | ||||
|
|
||||
| // TxOps holds configuration for transaction operations. | ||||
| type TxOps struct { | ||||
| Wallet *wallet.Wallet // Wallet abstraction (signing, sending) | ||||
| Amount tlb.Coins // Default amount for msg transfers | ||||
| } | ||||
|
|
||||
| // Chain represents a TON chain. | ||||
| type Chain struct { | ||||
| ChainMetadata // Contains canonical chain identifier | ||||
| Client *ton.APIClient // APIClient for Lite Server connection | ||||
| Wallet *wallet.Wallet // Wallet abstraction (signing, sending) | ||||
|
||||
| Wallet *wallet.Wallet // Wallet abstraction (signing, sending) |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -28,6 +28,7 @@ import ( | |||||||||
| "github.com/smartcontractkit/mcms/sdk/evm/bindings" | ||||||||||
| "github.com/smartcontractkit/mcms/sdk/solana" | ||||||||||
| "github.com/smartcontractkit/mcms/sdk/sui" | ||||||||||
| "github.com/smartcontractkit/mcms/sdk/ton" | ||||||||||
| "github.com/smartcontractkit/mcms/types" | ||||||||||
| "github.com/spf13/cobra" | ||||||||||
| "github.com/spf13/pflag" | ||||||||||
|
|
@@ -1183,6 +1184,8 @@ func newCfgv2(lggr logger.Logger, cmd *cobra.Command, domain cldf_domain.Domain, | |||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error creating Sui timelock converter: %w", err) | ||||||||||
| } | ||||||||||
| case chainsel.FamilyTon: | ||||||||||
| converter = ton.NewTimelockConverter() | ||||||||||
| default: | ||||||||||
| return nil, fmt.Errorf("unsupported chain family %s", fam) | ||||||||||
| } | ||||||||||
|
|
@@ -1489,18 +1492,18 @@ func getExecutorWithChainOverride(cfg *cfgv2, chainSelector types.ChainSelector) | |||||||||
| if !ok { | ||||||||||
| return nil, fmt.Errorf("invalid encoder type: %T", encoder) | ||||||||||
| } | ||||||||||
| chain := cfg.blockchains.EVMChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.EVMChains()[uint64(chainSelector)] | ||||||||||
|
gustavogama-cll marked this conversation as resolved.
|
||||||||||
|
|
||||||||||
| return evm.NewExecutor(evmEncoder, chain.Client, chain.DeployerKey), nil | ||||||||||
| return evm.NewExecutor(evmEncoder, c.Client, c.DeployerKey), nil | ||||||||||
|
|
||||||||||
| case chainsel.FamilySolana: | ||||||||||
| solanaEncoder, ok := encoder.(*solana.Encoder) | ||||||||||
| if !ok { | ||||||||||
| return nil, fmt.Errorf("invalid encoder type: %T", encoder) | ||||||||||
| } | ||||||||||
| chain := cfg.blockchains.SolanaChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.SolanaChains()[uint64(chainSelector)] | ||||||||||
|
|
||||||||||
| return solana.NewExecutor(solanaEncoder, chain.Client, *chain.DeployerKey), nil | ||||||||||
| return solana.NewExecutor(solanaEncoder, c.Client, *c.DeployerKey), nil | ||||||||||
|
|
||||||||||
| case chainsel.FamilyAptos: | ||||||||||
| encoder, ok := encoder.(*aptos.Encoder) | ||||||||||
|
|
@@ -1511,9 +1514,9 @@ func getExecutorWithChainOverride(cfg *cfgv2, chainSelector types.ChainSelector) | |||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error getting aptos role from proposal: %w", err) | ||||||||||
| } | ||||||||||
| chain := cfg.blockchains.AptosChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.AptosChains()[uint64(chainSelector)] | ||||||||||
|
|
||||||||||
| return aptos.NewExecutor(chain.Client, chain.DeployerSigner, encoder, *role), nil | ||||||||||
| return aptos.NewExecutor(c.Client, c.DeployerSigner, encoder, *role), nil | ||||||||||
|
|
||||||||||
| case chainsel.FamilySui: | ||||||||||
| encoder, ok := encoder.(*sui.Encoder) | ||||||||||
|
|
@@ -1524,10 +1527,18 @@ func getExecutorWithChainOverride(cfg *cfgv2, chainSelector types.ChainSelector) | |||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error getting sui metadata from proposal: %w", err) | ||||||||||
| } | ||||||||||
| chain := cfg.blockchains.SuiChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.SuiChains()[uint64(chainSelector)] | ||||||||||
| entrypointEncoder := suibindings.NewCCIPEntrypointArgEncoder(metadata.RegistryObj, metadata.DeployerStateObj) | ||||||||||
|
|
||||||||||
| return sui.NewExecutor(chain.Client, chain.Signer, encoder, entrypointEncoder, metadata.McmsPackageID, metadata.Role, cfg.timelockProposal.ChainMetadata[chainSelector].MCMAddress, metadata.AccountObj, metadata.RegistryObj, metadata.TimelockObj) | ||||||||||
| return sui.NewExecutor(c.Client, c.Signer, encoder, entrypointEncoder, metadata.McmsPackageID, metadata.Role, cfg.timelockProposal.ChainMetadata[chainSelector].MCMAddress, metadata.AccountObj, metadata.RegistryObj, metadata.TimelockObj) | ||||||||||
| case chainsel.FamilyTon: | ||||||||||
| encoder, ok := encoder.(*ton.Encoder) | ||||||||||
| if !ok { | ||||||||||
| return nil, fmt.Errorf("error getting encoder for chain %d", cfg.chainSelector) | ||||||||||
|
huangzhen1997 marked this conversation as resolved.
Outdated
huangzhen1997 marked this conversation as resolved.
Outdated
gustavogama-cll marked this conversation as resolved.
Outdated
|
||||||||||
| } | ||||||||||
| c := cfg.blockchains.TonChains()[uint64(chainSelector)] | ||||||||||
|
|
||||||||||
| return ton.NewExecutor(encoder, c.Client, c.TxOps.Wallet, c.TxOps.Amount) | ||||||||||
|
huangzhen1997 marked this conversation as resolved.
Outdated
|
||||||||||
| default: | ||||||||||
| return nil, fmt.Errorf("unsupported chain family %s", family) | ||||||||||
| } | ||||||||||
|
|
@@ -1557,26 +1568,29 @@ func getTimelockExecutorWithChainOverride(cfg *cfgv2, chainSelector types.ChainS | |||||||||
| var executor sdk.TimelockExecutor | ||||||||||
| switch family { | ||||||||||
| case chainsel.FamilyEVM: | ||||||||||
| chain := cfg.blockchains.EVMChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.EVMChains()[uint64(chainSelector)] | ||||||||||
|
|
||||||||||
| executor = evm.NewTimelockExecutor(chain.Client, chain.DeployerKey) | ||||||||||
| executor = evm.NewTimelockExecutor(c.Client, c.DeployerKey) | ||||||||||
| case chainsel.FamilySolana: | ||||||||||
| chain := cfg.blockchains.SolanaChains()[uint64(chainSelector)] | ||||||||||
| executor = solana.NewTimelockExecutor(chain.Client, *chain.DeployerKey) | ||||||||||
| c := cfg.blockchains.SolanaChains()[uint64(chainSelector)] | ||||||||||
| executor = solana.NewTimelockExecutor(c.Client, *c.DeployerKey) | ||||||||||
| case chainsel.FamilyAptos: | ||||||||||
| chain := cfg.blockchains.AptosChains()[uint64(chainSelector)] | ||||||||||
| executor = aptos.NewTimelockExecutor(chain.Client, chain.DeployerSigner) | ||||||||||
| c := cfg.blockchains.AptosChains()[uint64(chainSelector)] | ||||||||||
| executor = aptos.NewTimelockExecutor(c.Client, c.DeployerSigner) | ||||||||||
| case chainsel.FamilySui: | ||||||||||
| chain := cfg.blockchains.SuiChains()[uint64(chainSelector)] | ||||||||||
| c := cfg.blockchains.SuiChains()[uint64(chainSelector)] | ||||||||||
|
github-code-quality[bot] marked this conversation as resolved.
Fixed
|
||||||||||
| metadata, err := suiMetadataFromProposal(chainSelector, cfg.timelockProposal) | ||||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error getting sui metadata from proposal: %w", err) | ||||||||||
| } | ||||||||||
| entrypointEncoder := suibindings.NewCCIPEntrypointArgEncoder(metadata.AccountObj, metadata.DeployerStateObj) | ||||||||||
| executor, err = sui.NewTimelockExecutor(chain.Client, chain.Signer, entrypointEncoder, metadata.McmsPackageID, metadata.RegistryObj, metadata.AccountObj) | ||||||||||
| executor, err = sui.NewTimelockExecutor(c.Client, c.Signer, entrypointEncoder, metadata.McmsPackageID, metadata.RegistryObj, metadata.AccountObj) | ||||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error creating sui timelock executor: %w", err) | ||||||||||
| } | ||||||||||
| case chainsel.FamilyTon: | ||||||||||
| c := cfg.blockchains.TonChains()[uint64(chainSelector)] | ||||||||||
| return ton.NewTimelockExecutor(c.Client, c.TxOps.Wallet, c.TxOps.Amount) | ||||||||||
|
huangzhen1997 marked this conversation as resolved.
Outdated
huangzhen1997 marked this conversation as resolved.
Outdated
|
||||||||||
| default: | ||||||||||
| return nil, fmt.Errorf("unsupported chain family %s", family) | ||||||||||
| } | ||||||||||
|
|
@@ -1631,6 +1645,9 @@ var getInspectorFromChainSelector = func(cfg cfgv2) (sdk.Inspector, error) { | |||||||||
| if err != nil { | ||||||||||
| return nil, fmt.Errorf("error creating sui inspector: %w", err) | ||||||||||
| } | ||||||||||
| case chainsel.FamilyTon: | ||||||||||
| chain := cfg.blockchains.TonChains()[cfg.chainSelector] | ||||||||||
| inspector = ton.NewInspector(chain.Client) | ||||||||||
|
huangzhen1997 marked this conversation as resolved.
huangzhen1997 marked this conversation as resolved.
huangzhen1997 marked this conversation as resolved.
Comment on lines
+1619
to
+1620
|
||||||||||
| chain := cfg.blockchains.TonChains()[cfg.chainSelector] | |
| inspector = ton.NewInspector(chain.Client) | |
| c := cfg.blockchains.TonChains()[cfg.chainSelector] | |
| inspector = ton.NewInspector(c.Client) |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TON inspector creation in getInspectorFromChainSelector lacks test coverage. Add test cases to verify the inspector is created correctly for TON chains.
Uh oh!
There was an error while loading. Please reload this page.