@@ -2,14 +2,14 @@ package ton
22
33import (
44 "context"
5- "errors"
65 "fmt"
76 "math/big"
87
98 "github.com/xssnick/tonutils-go/address"
109 "github.com/xssnick/tonutils-go/ton"
1110 "github.com/xssnick/tonutils-go/tvm/cell"
1211
12+ "github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock"
1313 "github.com/smartcontractkit/mcms/sdk"
1414)
1515
@@ -50,24 +50,87 @@ func (i timelockInspector) GetMinDelay(ctx context.Context, _address string) (ui
5050 return rs .LoadUInt (64 )
5151}
5252
53+ // GetAdmins returns the list of addresses with the admin role
54+ func (i timelockInspector ) GetAdmins (ctx context.Context , address string ) ([]string , error ) {
55+ return i .getRoleMembers (ctx , address , [32 ]byte (timelock .RoleAdmin .Bytes ()))
56+ }
57+
5358// GetProposers returns the list of addresses with the proposer role
5459func (i timelockInspector ) GetProposers (ctx context.Context , address string ) ([]string , error ) {
55- return nil , errors . New ( "unimplemented" )
60+ return i . getRoleMembers ( ctx , address , [ 32 ] byte ( timelock . RoleProposer . Bytes ()) )
5661}
5762
5863// GetExecutors returns the list of addresses with the executor role
5964func (i timelockInspector ) GetExecutors (ctx context.Context , address string ) ([]string , error ) {
60- return nil , errors . New ( "unimplemented" )
65+ return i . getRoleMembers ( ctx , address , [ 32 ] byte ( timelock . RoleExecutor . Bytes ()) )
6166}
6267
6368// GetBypassers returns the list of addresses with the bypasser role
6469func (i timelockInspector ) GetBypassers (ctx context.Context , address string ) ([]string , error ) {
65- return nil , errors . New ( "unimplemented" )
70+ return i . getRoleMembers ( ctx , address , [ 32 ] byte ( timelock . RoleBaypasser . Bytes ()) )
6671}
6772
6873// GetCancellers returns the list of addresses with the canceller role
6974func (i timelockInspector ) GetCancellers (ctx context.Context , address string ) ([]string , error ) {
70- return nil , errors .New ("unimplemented" )
75+ return i .getRoleMembers (ctx , address , [32 ]byte (timelock .RoleCanceller .Bytes ()))
76+ }
77+
78+ // GetOracles returns the list of addresses with the oracle role
79+ func (i timelockInspector ) GetOracles (ctx context.Context , address string ) ([]string , error ) {
80+ return i .getRoleMembers (ctx , address , [32 ]byte (timelock .RoleOracle .Bytes ()))
81+ }
82+
83+ // getRoleMembers returns the list of addresses with the given role
84+ func (i timelockInspector ) getRoleMembers (ctx context.Context , _address string , role [32 ]byte ) ([]string , error ) {
85+ // Map to Ton Address type (timelock.address)
86+ addr , err := address .ParseAddr (_address )
87+ if err != nil {
88+ return nil , fmt .Errorf ("invalid timelock address: %w" , err )
89+ }
90+
91+ // TODO: mv and import from github.com/smartcontractkit/chainlink-ton/bindings/mcms/timelock
92+ block , err := i .client .CurrentMasterchainInfo (ctx )
93+ if err != nil {
94+ return nil , fmt .Errorf ("failed to get current masterchain info: %w" , err )
95+ }
96+
97+ _role , err := mapRoleParam (role )
98+ if err != nil {
99+ return nil , fmt .Errorf ("failed to map opID param: %w" , err )
100+ }
101+
102+ r , err := i .client .RunGetMethod (ctx , block , addr , "getRoleMemberCount" , _role )
103+ if err != nil {
104+ return nil , fmt .Errorf ("error getting getRoleMemberCount: %w" , err )
105+ }
106+
107+ count , err := r .Int (0 )
108+ if err != nil {
109+ return nil , fmt .Errorf ("error decoding getRoleMemberCount result: %w" , err )
110+ }
111+
112+ // For each address index in the roles count, get the address
113+ addresses := make ([]string , 0 , count .Uint64 ())
114+ for j := range count .Uint64 () {
115+ rAddr , err := i .client .RunGetMethod (ctx , block , addr , "getRoleMember" , _role , uint32 (j ))
116+ if err != nil {
117+ return nil , fmt .Errorf ("error getting getRoleMember: %w" , err )
118+ }
119+
120+ sAddr , err := rAddr .Slice (0 )
121+ if err != nil {
122+ return nil , fmt .Errorf ("error decoding getRoleMember result: %w" , err )
123+ }
124+
125+ addr , err := sAddr .LoadAddr ()
126+ if err != nil {
127+ return nil , fmt .Errorf ("error decoding getRoleMember result slice: %w" , err )
128+ }
129+
130+ addresses = append (addresses , addr .String ())
131+ }
132+
133+ return addresses , nil
71134}
72135
73136func (i timelockInspector ) IsOperation (ctx context.Context , _address string , opID [32 ]byte ) (bool , error ) {
@@ -203,3 +266,13 @@ func mapOpIDParam(opID [32]byte) (*cell.Slice, error) {
203266
204267 return b .EndCell ().BeginParse (), nil
205268}
269+
270+ // Help function to map (encode) role param to cell.Slice
271+ func mapRoleParam (role [32 ]byte ) (* cell.Slice , error ) {
272+ b := cell .BeginCell ()
273+ if err := b .StoreBigUInt (new (big.Int ).SetBytes (role [:]), 256 ); err != nil {
274+ return nil , fmt .Errorf ("failed to store domain separator: %w" , err )
275+ }
276+
277+ return b .EndCell ().BeginParse (), nil
278+ }
0 commit comments