@@ -4,13 +4,15 @@ import (
4
4
"context"
5
5
"errors"
6
6
"fmt"
7
-
8
7
"github.com/NilFoundation/nil/nil/common"
8
+ "github.com/NilFoundation/nil/nil/internal/config"
9
+ "github.com/NilFoundation/nil/nil/internal/contracts"
9
10
"github.com/NilFoundation/nil/nil/internal/db"
10
11
"github.com/NilFoundation/nil/nil/internal/execution"
11
12
"github.com/NilFoundation/nil/nil/internal/mpt"
12
13
"github.com/NilFoundation/nil/nil/internal/types"
13
14
rawapitypes "github.com/NilFoundation/nil/nil/services/rpc/rawapi/types"
15
+ "math/big"
14
16
)
15
17
16
18
var errBlockNotFound = errors .New ("block not found" )
@@ -75,10 +77,99 @@ func (api *LocalShardApi) GetCode(
75
77
return code , nil
76
78
}
77
79
80
+ type token struct {
81
+ Token types.Address
82
+ Balance * big.Int
83
+ }
84
+
78
85
func (api * LocalShardApi ) GetTokens (
79
86
ctx context.Context ,
80
87
address types.Address ,
81
88
blockReference rawapitypes.BlockReference ,
89
+ ) (map [types.TokenId ]types.Value , error ) {
90
+ abi , err := contracts .GetAbi (contracts .NameTokenManager )
91
+ if err != nil {
92
+ return nil , fmt .Errorf ("cannot get ABI: %w" , err )
93
+ }
94
+
95
+ calldata , err := abi .Pack ("getTokens" , address )
96
+ if err != nil {
97
+ return nil , fmt .Errorf ("cannot pack calldata: %w" , err )
98
+ }
99
+
100
+ tokenManagerAddr := types .ShardAndHexToAddress (address .ShardId (), types .TokenManagerPureAddress )
101
+
102
+ ret , err := api .CallGetter (ctx , tokenManagerAddr , calldata )
103
+ if err != nil {
104
+ return nil , fmt .Errorf ("failed to call getter: %w" , err )
105
+ }
106
+
107
+ var tokens []token
108
+ err = abi .UnpackIntoInterface (& tokens , "getTokens" , ret )
109
+ if err != nil {
110
+ return nil , fmt .Errorf ("failed to unpack response: %w" , err )
111
+ }
112
+
113
+ res := make (map [types.TokenId ]types.Value )
114
+ for t := range tokens {
115
+ res [types .TokenId (tokens [t ].Token )] = types .NewValueFromBigMust (tokens [t ].Balance )
116
+ }
117
+ return res , nil
118
+ }
119
+
120
+ func (api * LocalShardApi ) CallGetter (
121
+ ctx context.Context ,
122
+ address types.Address ,
123
+ calldata []byte ,
124
+ ) ([]byte , error ){
125
+ tx , err := api .db .CreateRoTx (ctx )
126
+ if err != nil {
127
+ return nil , err
128
+ }
129
+ defer tx .Rollback ()
130
+
131
+ block , _ , err := db .ReadLastBlock (tx , address .ShardId ())
132
+ if err != nil {
133
+ return nil , fmt .Errorf ("failed to read last block: %w" , err )
134
+ }
135
+
136
+ cfgAccessor , err := config .NewConfigReader (tx , & block .MainShardHash )
137
+ if err != nil {
138
+ return nil , fmt .Errorf ("failed to create config accessor: %w" , err )
139
+ }
140
+
141
+ es , err := execution .NewExecutionState (tx , address .ShardId (), execution.StateParams {
142
+ Block : block ,
143
+ ConfigAccessor : cfgAccessor ,
144
+ Mode : execution .ModeReadOnly ,
145
+ })
146
+ if err != nil {
147
+ return nil , err
148
+ }
149
+
150
+ extTxn := & types.ExternalTransaction {
151
+ FeeCredit : types .GasToValue (types .DefaultMaxGasInBlock .Uint64 ()),
152
+ MaxFeePerGas : types .MaxFeePerGasDefault ,
153
+ To : address ,
154
+ Data : calldata ,
155
+ }
156
+
157
+ txn := extTxn .ToTransaction ()
158
+
159
+ payer := execution .NewDummyPayer ()
160
+
161
+ es .AddInTransaction (txn )
162
+ res := es .HandleTransaction (ctx , txn , payer )
163
+ if res .Failed () {
164
+ return nil , fmt .Errorf ("transaction failed: %w" , res .GetError ())
165
+ }
166
+ return res .ReturnData , nil
167
+ }
168
+
169
+ func (api * LocalShardApi ) GetTokens1 (
170
+ ctx context.Context ,
171
+ address types.Address ,
172
+ blockReference rawapitypes.BlockReference ,
82
173
) (map [types.TokenId ]types.Value , error ) {
83
174
shardId := address .ShardId ()
84
175
if shardId != api .ShardId {
0 commit comments