github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/nep11/base_test.go (about) 1 package nep11 2 3 import ( 4 "errors" 5 "math/big" 6 "testing" 7 8 "github.com/google/uuid" 9 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 10 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 11 "github.com/nspcc-dev/neo-go/pkg/util" 12 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 13 "github.com/stretchr/testify/require" 14 ) 15 16 type testAct struct { 17 err error 18 res *result.Invoke 19 tx *transaction.Transaction 20 txh util.Uint256 21 vub uint32 22 } 23 24 func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { 25 return t.res, t.err 26 } 27 func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { 28 return t.tx, t.err 29 } 30 func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) { 31 return t.tx, t.err 32 } 33 func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { 34 return t.txh, t.vub, t.err 35 } 36 func (t *testAct) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { 37 return t.res, t.err 38 } 39 func (t *testAct) TerminateSession(sessionID uuid.UUID) error { 40 return t.err 41 } 42 func (t *testAct) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) { 43 return t.res.Stack, t.err 44 } 45 46 func TestReaderBalanceOf(t *testing.T) { 47 ta := new(testAct) 48 tr := NewBaseReader(ta, util.Uint160{1, 2, 3}) 49 50 ta.err = errors.New("") 51 _, err := tr.BalanceOf(util.Uint160{3, 2, 1}) 52 require.Error(t, err) 53 54 ta.err = nil 55 ta.res = &result.Invoke{ 56 State: "HALT", 57 Stack: []stackitem.Item{ 58 stackitem.Make(100500), 59 }, 60 } 61 bal, err := tr.BalanceOf(util.Uint160{3, 2, 1}) 62 require.NoError(t, err) 63 require.Equal(t, big.NewInt(100500), bal) 64 65 ta.res = &result.Invoke{ 66 State: "HALT", 67 Stack: []stackitem.Item{ 68 stackitem.Make([]stackitem.Item{}), 69 }, 70 } 71 _, err = tr.BalanceOf(util.Uint160{3, 2, 1}) 72 require.Error(t, err) 73 } 74 75 func TestReaderProperties(t *testing.T) { 76 ta := new(testAct) 77 tr := NewBaseReader(ta, util.Uint160{1, 2, 3}) 78 79 ta.err = errors.New("") 80 _, err := tr.Properties([]byte{3, 2, 1}) 81 require.Error(t, err) 82 83 ta.res = &result.Invoke{ 84 State: "HALT", 85 Stack: []stackitem.Item{ 86 stackitem.Make([]stackitem.Item{}), 87 }, 88 } 89 _, err = tr.Properties([]byte{3, 2, 1}) 90 require.Error(t, err) 91 92 ta.err = nil 93 ta.res = &result.Invoke{ 94 State: "HALT", 95 Stack: []stackitem.Item{ 96 stackitem.NewMap(), 97 }, 98 } 99 m, err := tr.Properties([]byte{3, 2, 1}) 100 require.NoError(t, err) 101 require.Equal(t, 0, m.Len()) 102 } 103 104 func TestReaderTokensOfExpanded(t *testing.T) { 105 ta := new(testAct) 106 tr := NewBaseReader(ta, util.Uint160{1, 2, 3}) 107 108 for name, fun := range map[string]func(int) ([][]byte, error){ 109 "Tokens": tr.TokensExpanded, 110 "TokensOf": func(n int) ([][]byte, error) { 111 return tr.TokensOfExpanded(util.Uint160{1, 2, 3}, n) 112 }, 113 } { 114 t.Run(name, func(t *testing.T) { 115 ta.err = errors.New("") 116 _, err := fun(1) 117 require.Error(t, err) 118 119 ta.err = nil 120 ta.res = &result.Invoke{ 121 State: "HALT", 122 Stack: []stackitem.Item{ 123 stackitem.Make(100500), 124 }, 125 } 126 _, err = fun(1) 127 require.Error(t, err) 128 129 ta.res = &result.Invoke{ 130 State: "HALT", 131 Stack: []stackitem.Item{ 132 stackitem.Make([]stackitem.Item{stackitem.Make("one")}), 133 }, 134 } 135 toks, err := fun(1) 136 require.NoError(t, err) 137 require.Equal(t, [][]byte{[]byte("one")}, toks) 138 }) 139 } 140 } 141 142 func TestReaderTokensOf(t *testing.T) { 143 ta := new(testAct) 144 tr := NewBaseReader(ta, util.Uint160{1, 2, 3}) 145 146 for name, fun := range map[string]func() (*TokenIterator, error){ 147 "Tokens": tr.Tokens, 148 "TokensOf": func() (*TokenIterator, error) { 149 return tr.TokensOf(util.Uint160{1, 2, 3}) 150 }, 151 } { 152 t.Run(name, func(t *testing.T) { 153 ta.err = errors.New("") 154 _, err := fun() 155 require.Error(t, err) 156 157 iid := uuid.New() 158 ta.err = nil 159 ta.res = &result.Invoke{ 160 Session: uuid.New(), 161 State: "HALT", 162 Stack: []stackitem.Item{ 163 stackitem.NewInterop(result.Iterator{ 164 ID: &iid, 165 }), 166 }, 167 } 168 iter, err := fun() 169 require.NoError(t, err) 170 171 ta.res = &result.Invoke{ 172 Stack: []stackitem.Item{ 173 stackitem.Make("one"), 174 stackitem.Make([]stackitem.Item{}), 175 }, 176 } 177 _, err = iter.Next(10) 178 require.Error(t, err) 179 180 ta.res = &result.Invoke{ 181 Stack: []stackitem.Item{ 182 stackitem.Make("one"), 183 stackitem.Make("two"), 184 }, 185 } 186 vals, err := iter.Next(10) 187 require.NoError(t, err) 188 require.Equal(t, [][]byte{[]byte("one"), []byte("two")}, vals) 189 190 ta.err = errors.New("") 191 _, err = iter.Next(1) 192 require.Error(t, err) 193 194 err = iter.Terminate() 195 require.Error(t, err) 196 197 // Value-based iterator. 198 ta.err = nil 199 ta.res = &result.Invoke{ 200 State: "HALT", 201 Stack: []stackitem.Item{ 202 stackitem.NewInterop(result.Iterator{ 203 Values: []stackitem.Item{ 204 stackitem.Make("one"), 205 stackitem.Make("two"), 206 }, 207 }), 208 }, 209 } 210 iter, err = fun() 211 require.NoError(t, err) 212 213 ta.err = errors.New("") 214 err = iter.Terminate() 215 require.NoError(t, err) 216 }) 217 } 218 } 219 220 type tData struct { 221 someInt int 222 someString string 223 } 224 225 func (d *tData) ToStackItem() (stackitem.Item, error) { 226 return stackitem.NewStruct([]stackitem.Item{ 227 stackitem.Make(d.someInt), 228 stackitem.Make(d.someString), 229 }), nil 230 } 231 232 func (d *tData) FromStackItem(si stackitem.Item) error { 233 panic("TODO") 234 } 235 236 func TestTokenTransfer(t *testing.T) { 237 ta := new(testAct) 238 tok := NewBase(ta, util.Uint160{1, 2, 3}) 239 240 ta.err = errors.New("") 241 _, _, err := tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, nil) 242 require.Error(t, err) 243 244 ta.err = nil 245 ta.txh = util.Uint256{1, 2, 3} 246 ta.vub = 42 247 h, vub, err := tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, nil) 248 require.NoError(t, err) 249 require.Equal(t, ta.txh, h) 250 require.Equal(t, ta.vub, vub) 251 252 ta.err = nil 253 ta.txh = util.Uint256{1, 2, 3} 254 ta.vub = 42 255 h, vub, err = tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, &tData{ 256 someInt: 5, 257 someString: "ur", 258 }) 259 require.NoError(t, err) 260 require.Equal(t, ta.txh, h) 261 require.Equal(t, ta.vub, vub) 262 263 _, _, err = tok.Transfer(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewPointer(123, []byte{123})) 264 require.Error(t, err) 265 } 266 267 func TestTokenTransferTransaction(t *testing.T) { 268 ta := new(testAct) 269 tok := NewBase(ta, util.Uint160{1, 2, 3}) 270 271 for _, fun := range []func(to util.Uint160, token []byte, data any) (*transaction.Transaction, error){ 272 tok.TransferTransaction, 273 tok.TransferUnsigned, 274 } { 275 ta.err = errors.New("") 276 _, err := fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, nil) 277 require.Error(t, err) 278 279 ta.err = nil 280 ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} 281 tx, err := fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, nil) 282 require.NoError(t, err) 283 require.Equal(t, ta.tx, tx) 284 285 ta.err = nil 286 ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} 287 tx, err = fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, &tData{ 288 someInt: 5, 289 someString: "ur", 290 }) 291 require.NoError(t, err) 292 require.Equal(t, ta.tx, tx) 293 294 _, err = fun(util.Uint160{3, 2, 1}, []byte{3, 2, 1}, stackitem.NewInterop(nil)) 295 require.Error(t, err) 296 } 297 } 298 299 func TestUnwrapKnownProperties(t *testing.T) { 300 _, err := UnwrapKnownProperties(stackitem.NewMap(), errors.New("")) 301 require.Error(t, err) 302 303 m, err := UnwrapKnownProperties(stackitem.NewMap(), nil) 304 require.NoError(t, err) 305 require.NotNil(t, m) 306 require.Equal(t, 0, len(m)) 307 308 m, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{ 309 {Key: stackitem.Make("some"), Value: stackitem.Make("thing")}, 310 }), nil) 311 require.NoError(t, err) 312 require.NotNil(t, m) 313 require.Equal(t, 0, len(m)) 314 315 m, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{ 316 {Key: stackitem.Make([]stackitem.Item{}), Value: stackitem.Make("thing")}, 317 }), nil) 318 require.NoError(t, err) 319 require.NotNil(t, m) 320 require.Equal(t, 0, len(m)) 321 322 _, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{ 323 {Key: stackitem.Make("name"), Value: stackitem.Make([]stackitem.Item{})}, 324 }), nil) 325 require.Error(t, err) 326 327 _, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{ 328 {Key: stackitem.Make("name"), Value: stackitem.Make([]byte{0xff})}, 329 }), nil) 330 require.Error(t, err) 331 332 m, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{ 333 {Key: stackitem.Make("name"), Value: stackitem.Make("thing")}, 334 {Key: stackitem.Make("description"), Value: stackitem.Make("good NFT")}, 335 }), nil) 336 require.NoError(t, err) 337 require.NotNil(t, m) 338 require.Equal(t, 2, len(m)) 339 require.Equal(t, "thing", m["name"]) 340 require.Equal(t, "good NFT", m["description"]) 341 }