github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/nns/contract.go (about)

     1  // Package nns provide RPC wrappers for the non-native NNS contract.
     2  // This is Neo N3 NNS contract wrapper, the source code of the contract can be found here:
     3  // https://github.com/neo-project/non-native-contracts/blob/8d72b92e5e5705d763232bcc24784ced0fb8fc87/src/NameService/NameService.cs
     4  package nns
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  	"unicode/utf8"
    11  
    12  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    13  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    14  	"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep11"
    15  	"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
    16  	"github.com/nspcc-dev/neo-go/pkg/smartcontract"
    17  	"github.com/nspcc-dev/neo-go/pkg/util"
    18  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    19  )
    20  
    21  // MaxNameLength is the max length of domain name.
    22  const MaxNameLength = 255
    23  
    24  // SetAdminEvent represents "SetAdmin" event emitted by the contract.
    25  type SetAdminEvent struct {
    26  	Name     string
    27  	OldAdmin util.Uint160
    28  	NewAdmin util.Uint160
    29  }
    30  
    31  // RenewEvent represents "Renew" event emitted by the contract.
    32  type RenewEvent struct {
    33  	Name          string
    34  	OldExpiration *big.Int
    35  	NewExpiration *big.Int
    36  }
    37  
    38  // Invoker is used by ContractReader to call various safe methods.
    39  type Invoker interface {
    40  	nep11.Invoker
    41  }
    42  
    43  // Actor is used by Contract to call state-changing methods.
    44  type Actor interface {
    45  	Invoker
    46  	nep11.Actor
    47  
    48  	MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error)
    49  	MakeRun(script []byte) (*transaction.Transaction, error)
    50  	MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error)
    51  	MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error)
    52  	SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error)
    53  	SendRun(script []byte) (util.Uint256, uint32, error)
    54  }
    55  
    56  // ContractReader implements safe contract methods.
    57  type ContractReader struct {
    58  	nep11.NonDivisibleReader
    59  
    60  	invoker Invoker
    61  	hash    util.Uint160
    62  }
    63  
    64  // Contract provides full NeoNameService interface, both safe and state-changing methods.
    65  type Contract struct {
    66  	ContractReader
    67  	nep11.BaseWriter
    68  
    69  	actor Actor
    70  	hash  util.Uint160
    71  }
    72  
    73  // NewReader creates an instance of ContractReader using provided contract hash and the given Invoker.
    74  func NewReader(invoker Invoker, hash util.Uint160) *ContractReader {
    75  	return &ContractReader{*nep11.NewNonDivisibleReader(invoker, hash), invoker, hash}
    76  }
    77  
    78  // New creates an instance of Contract using provided contract hash and the given Actor.
    79  func New(actor Actor, hash util.Uint160) *Contract {
    80  	var nep11ndt = nep11.NewNonDivisible(actor, hash)
    81  	return &Contract{ContractReader{nep11ndt.NonDivisibleReader, actor, hash}, nep11ndt.BaseWriter, actor, hash}
    82  }
    83  
    84  // Roots invokes `roots` method of contract.
    85  func (c *ContractReader) Roots() (*RootIterator, error) {
    86  	sess, iter, err := unwrap.SessionIterator(c.invoker.Call(c.hash, "roots"))
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return &RootIterator{
    92  		client:   c.invoker,
    93  		iterator: iter,
    94  		session:  sess,
    95  	}, nil
    96  }
    97  
    98  // RootsExpanded is similar to Roots (uses the same contract
    99  // method), but can be useful if the server used doesn't support sessions and
   100  // doesn't expand iterators. It creates a script that will get the specified
   101  // number of result items from the iterator right in the VM and return them to
   102  // you. It's only limited by VM stack and GAS available for RPC invocations.
   103  func (c *ContractReader) RootsExpanded(_numOfIteratorItems int) ([]string, error) {
   104  	arr, err := unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "roots", _numOfIteratorItems))
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	return itemsToRoots(arr)
   110  }
   111  
   112  // GetPrice invokes `getPrice` method of contract.
   113  func (c *ContractReader) GetPrice(length uint8) (*big.Int, error) {
   114  	return unwrap.BigInt(c.invoker.Call(c.hash, "getPrice", length))
   115  }
   116  
   117  // IsAvailable invokes `isAvailable` method of contract.
   118  func (c *ContractReader) IsAvailable(name string) (bool, error) {
   119  	return unwrap.Bool(c.invoker.Call(c.hash, "isAvailable", name))
   120  }
   121  
   122  // GetRecord invokes `getRecord` method of contract.
   123  func (c *ContractReader) GetRecord(name string, typev RecordType) (string, error) {
   124  	return unwrap.UTF8String(c.invoker.Call(c.hash, "getRecord", name, typev))
   125  }
   126  
   127  // GetAllRecords invokes `getAllRecords` method of contract.
   128  func (c *ContractReader) GetAllRecords(name string) (*RecordIterator, error) {
   129  	sess, iter, err := unwrap.SessionIterator(c.invoker.Call(c.hash, "getAllRecords", name))
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	return &RecordIterator{
   135  		client:   c.invoker,
   136  		iterator: iter,
   137  		session:  sess,
   138  	}, nil
   139  }
   140  
   141  // GetAllRecordsExpanded is similar to GetAllRecords (uses the same contract
   142  // method), but can be useful if the server used doesn't support sessions and
   143  // doesn't expand iterators. It creates a script that will get the specified
   144  // number of result items from the iterator right in the VM and return them to
   145  // you. It's only limited by VM stack and GAS available for RPC invocations.
   146  func (c *ContractReader) GetAllRecordsExpanded(name string, _numOfIteratorItems int) ([]RecordState, error) {
   147  	arr, err := unwrap.Array(c.invoker.CallAndExpandIterator(c.hash, "getAllRecords", _numOfIteratorItems, name))
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	return itemsToRecords(arr)
   152  }
   153  
   154  // Resolve invokes `resolve` method of contract.
   155  func (c *ContractReader) Resolve(name string, typev RecordType) (string, error) {
   156  	return unwrap.UTF8String(c.invoker.Call(c.hash, "resolve", name, int64(typev)))
   157  }
   158  
   159  // Update creates a transaction invoking `update` method of the contract.
   160  // This transaction is signed and immediately sent to the network.
   161  // The values returned are its hash, ValidUntilBlock value and error if any.
   162  func (c *Contract) Update(nef []byte, manifest string) (util.Uint256, uint32, error) {
   163  	return c.actor.SendCall(c.hash, "update", nef, manifest)
   164  }
   165  
   166  // UpdateTransaction creates a transaction invoking `update` method of the contract.
   167  // This transaction is signed, but not sent to the network, instead it's
   168  // returned to the caller.
   169  func (c *Contract) UpdateTransaction(nef []byte, manifest string) (*transaction.Transaction, error) {
   170  	return c.actor.MakeCall(c.hash, "update", nef, manifest)
   171  }
   172  
   173  // UpdateUnsigned creates a transaction invoking `update` method of the contract.
   174  // This transaction is not signed, it's simply returned to the caller.
   175  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   176  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   177  func (c *Contract) UpdateUnsigned(nef []byte, manifest string) (*transaction.Transaction, error) {
   178  	return c.actor.MakeUnsignedCall(c.hash, "update", nil, nef, manifest)
   179  }
   180  
   181  // AddRoot creates a transaction invoking `addRoot` method of the contract.
   182  // This transaction is signed and immediately sent to the network.
   183  // The values returned are its hash, ValidUntilBlock value and error if any.
   184  func (c *Contract) AddRoot(root string) (util.Uint256, uint32, error) {
   185  	return c.actor.SendCall(c.hash, "addRoot", root)
   186  }
   187  
   188  // AddRootTransaction creates a transaction invoking `addRoot` method of the contract.
   189  // This transaction is signed, but not sent to the network, instead it's
   190  // returned to the caller.
   191  func (c *Contract) AddRootTransaction(root string) (*transaction.Transaction, error) {
   192  	return c.actor.MakeCall(c.hash, "addRoot", root)
   193  }
   194  
   195  // AddRootUnsigned creates a transaction invoking `addRoot` method of the contract.
   196  // This transaction is not signed, it's simply returned to the caller.
   197  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   198  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   199  func (c *Contract) AddRootUnsigned(root string) (*transaction.Transaction, error) {
   200  	return c.actor.MakeUnsignedCall(c.hash, "addRoot", nil, root)
   201  }
   202  
   203  // SetPrice creates a transaction invoking `setPrice` method of the contract.
   204  // This transaction is signed and immediately sent to the network.
   205  // The values returned are its hash, ValidUntilBlock value and error if any.
   206  func (c *Contract) SetPrice(priceList []int64) (util.Uint256, uint32, error) {
   207  	anyPriceList := make([]any, len(priceList))
   208  	for i, price := range priceList {
   209  		anyPriceList[i] = price
   210  	}
   211  	return c.actor.SendCall(c.hash, "setPrice", anyPriceList)
   212  }
   213  
   214  // SetPriceTransaction creates a transaction invoking `setPrice` method of the contract.
   215  // This transaction is signed, but not sent to the network, instead it's
   216  // returned to the caller.
   217  func (c *Contract) SetPriceTransaction(priceList []int64) (*transaction.Transaction, error) {
   218  	anyPriceList := make([]any, len(priceList))
   219  	for i, price := range priceList {
   220  		anyPriceList[i] = price
   221  	}
   222  	return c.actor.MakeCall(c.hash, "setPrice", anyPriceList)
   223  }
   224  
   225  // SetPriceUnsigned creates a transaction invoking `setPrice` method of the contract.
   226  // This transaction is not signed, it's simply returned to the caller.
   227  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   228  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   229  func (c *Contract) SetPriceUnsigned(priceList []int64) (*transaction.Transaction, error) {
   230  	anyPriceList := make([]any, len(priceList))
   231  	for i, price := range priceList {
   232  		anyPriceList[i] = price
   233  	}
   234  	return c.actor.MakeUnsignedCall(c.hash, "setPrice", nil, anyPriceList)
   235  }
   236  
   237  func (c *Contract) scriptForRegister(name string, owner util.Uint160) ([]byte, error) {
   238  	return smartcontract.CreateCallWithAssertScript(c.hash, "register", name, owner)
   239  }
   240  
   241  // Register creates a transaction invoking `register` method of the contract.
   242  // This transaction is signed and immediately sent to the network.
   243  // The values returned are its hash, ValidUntilBlock value and error if any.
   244  func (c *Contract) Register(name string, owner util.Uint160) (util.Uint256, uint32, error) {
   245  	script, err := c.scriptForRegister(name, owner)
   246  	if err != nil {
   247  		return util.Uint256{}, 0, err
   248  	}
   249  	return c.actor.SendRun(script)
   250  }
   251  
   252  // RegisterTransaction creates a transaction invoking `register` method of the contract.
   253  // This transaction is signed, but not sent to the network, instead it's
   254  // returned to the caller.
   255  func (c *Contract) RegisterTransaction(name string, owner util.Uint160) (*transaction.Transaction, error) {
   256  	script, err := c.scriptForRegister(name, owner)
   257  	if err != nil {
   258  		return nil, err
   259  	}
   260  	return c.actor.MakeRun(script)
   261  }
   262  
   263  // RegisterUnsigned creates a transaction invoking `register` method of the contract.
   264  // This transaction is not signed, it's simply returned to the caller.
   265  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   266  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   267  func (c *Contract) RegisterUnsigned(name string, owner util.Uint160) (*transaction.Transaction, error) {
   268  	script, err := c.scriptForRegister(name, owner)
   269  	if err != nil {
   270  		return nil, err
   271  	}
   272  	return c.actor.MakeUnsignedRun(script, nil)
   273  }
   274  
   275  // Renew creates a transaction invoking `renew` method of the contract.
   276  // This transaction is signed and immediately sent to the network.
   277  // The values returned are its hash, ValidUntilBlock value and error if any.
   278  func (c *Contract) Renew(name string) (util.Uint256, uint32, error) {
   279  	return c.actor.SendCall(c.hash, "renew", name)
   280  }
   281  
   282  // RenewTransaction creates a transaction invoking `renew` method of the contract.
   283  // This transaction is signed, but not sent to the network, instead it's
   284  // returned to the caller.
   285  func (c *Contract) RenewTransaction(name string) (*transaction.Transaction, error) {
   286  	return c.actor.MakeCall(c.hash, "renew", name)
   287  }
   288  
   289  // RenewUnsigned creates a transaction invoking `renew` method of the contract.
   290  // This transaction is not signed, it's simply returned to the caller.
   291  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   292  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   293  func (c *Contract) RenewUnsigned(name string) (*transaction.Transaction, error) {
   294  	return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name)
   295  }
   296  
   297  // Renew2 creates a transaction invoking `renew` method of the contract.
   298  // This transaction is signed and immediately sent to the network.
   299  // The values returned are its hash, ValidUntilBlock value and error if any.
   300  func (c *Contract) Renew2(name string, years int64) (util.Uint256, uint32, error) {
   301  	return c.actor.SendCall(c.hash, "renew", name, years)
   302  }
   303  
   304  // Renew2Transaction creates a transaction invoking `renew` method of the contract.
   305  // This transaction is signed, but not sent to the network, instead it's
   306  // returned to the caller.
   307  func (c *Contract) Renew2Transaction(name string, years int64) (*transaction.Transaction, error) {
   308  	return c.actor.MakeCall(c.hash, "renew", name, years)
   309  }
   310  
   311  // Renew2Unsigned creates a transaction invoking `renew` method of the contract.
   312  // This transaction is not signed, it's simply returned to the caller.
   313  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   314  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   315  func (c *Contract) Renew2Unsigned(name string, years int64) (*transaction.Transaction, error) {
   316  	return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name, years)
   317  }
   318  
   319  // SetAdmin creates a transaction invoking `setAdmin` method of the contract.
   320  // This transaction is signed and immediately sent to the network.
   321  // The values returned are its hash, ValidUntilBlock value and error if any.
   322  func (c *Contract) SetAdmin(name string, admin util.Uint160) (util.Uint256, uint32, error) {
   323  	return c.actor.SendCall(c.hash, "setAdmin", name, admin)
   324  }
   325  
   326  // SetAdminTransaction creates a transaction invoking `setAdmin` method of the contract.
   327  // This transaction is signed, but not sent to the network, instead it's
   328  // returned to the caller.
   329  func (c *Contract) SetAdminTransaction(name string, admin util.Uint160) (*transaction.Transaction, error) {
   330  	return c.actor.MakeCall(c.hash, "setAdmin", name, admin)
   331  }
   332  
   333  // SetAdminUnsigned creates a transaction invoking `setAdmin` method of the contract.
   334  // This transaction is not signed, it's simply returned to the caller.
   335  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   336  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   337  func (c *Contract) SetAdminUnsigned(name string, admin util.Uint160) (*transaction.Transaction, error) {
   338  	return c.actor.MakeUnsignedCall(c.hash, "setAdmin", nil, name, admin)
   339  }
   340  
   341  // SetRecord creates a transaction invoking `setRecord` method of the contract.
   342  // This transaction is signed and immediately sent to the network.
   343  // The values returned are its hash, ValidUntilBlock value and error if any.
   344  func (c *Contract) SetRecord(name string, typev RecordType, data string) (util.Uint256, uint32, error) {
   345  	return c.actor.SendCall(c.hash, "setRecord", name, typev, data)
   346  }
   347  
   348  // SetRecordTransaction creates a transaction invoking `setRecord` method of the contract.
   349  // This transaction is signed, but not sent to the network, instead it's
   350  // returned to the caller.
   351  func (c *Contract) SetRecordTransaction(name string, typev RecordType, data string) (*transaction.Transaction, error) {
   352  	return c.actor.MakeCall(c.hash, "setRecord", name, typev, data)
   353  }
   354  
   355  // SetRecordUnsigned creates a transaction invoking `setRecord` method of the contract.
   356  // This transaction is not signed, it's simply returned to the caller.
   357  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   358  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   359  func (c *Contract) SetRecordUnsigned(name string, typev RecordType, data string) (*transaction.Transaction, error) {
   360  	return c.actor.MakeUnsignedCall(c.hash, "setRecord", nil, name, typev, data)
   361  }
   362  
   363  // DeleteRecord creates a transaction invoking `deleteRecord` method of the contract.
   364  // This transaction is signed and immediately sent to the network.
   365  // The values returned are its hash, ValidUntilBlock value and error if any.
   366  func (c *Contract) DeleteRecord(name string, typev RecordType) (util.Uint256, uint32, error) {
   367  	return c.actor.SendCall(c.hash, "deleteRecord", name, typev)
   368  }
   369  
   370  // DeleteRecordTransaction creates a transaction invoking `deleteRecord` method of the contract.
   371  // This transaction is signed, but not sent to the network, instead it's
   372  // returned to the caller.
   373  func (c *Contract) DeleteRecordTransaction(name string, typev RecordType) (*transaction.Transaction, error) {
   374  	return c.actor.MakeCall(c.hash, "deleteRecord", name, typev)
   375  }
   376  
   377  // DeleteRecordUnsigned creates a transaction invoking `deleteRecord` method of the contract.
   378  // This transaction is not signed, it's simply returned to the caller.
   379  // Any fields of it that do not affect fees can be changed (ValidUntilBlock,
   380  // Nonce), fee values (NetworkFee, SystemFee) can be increased as well.
   381  func (c *Contract) DeleteRecordUnsigned(name string, typev RecordType) (*transaction.Transaction, error) {
   382  	return c.actor.MakeUnsignedCall(c.hash, "deleteRecord", nil, name, typev)
   383  }
   384  
   385  // SetAdminEventsFromApplicationLog retrieves a set of all emitted events
   386  // with "SetAdmin" name from the provided [result.ApplicationLog].
   387  func SetAdminEventsFromApplicationLog(log *result.ApplicationLog) ([]*SetAdminEvent, error) {
   388  	if log == nil {
   389  		return nil, errors.New("nil application log")
   390  	}
   391  
   392  	var res []*SetAdminEvent
   393  	for i, ex := range log.Executions {
   394  		for j, e := range ex.Events {
   395  			if e.Name != "SetAdmin" {
   396  				continue
   397  			}
   398  			event := new(SetAdminEvent)
   399  			err := event.FromStackItem(e.Item)
   400  			if err != nil {
   401  				return nil, fmt.Errorf("failed to deserialize SetAdminEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
   402  			}
   403  			res = append(res, event)
   404  		}
   405  	}
   406  
   407  	return res, nil
   408  }
   409  
   410  // FromStackItem converts provided [stackitem.Array] to SetAdminEvent or
   411  // returns an error if it's not possible to do to so.
   412  func (e *SetAdminEvent) FromStackItem(item *stackitem.Array) error {
   413  	if item == nil {
   414  		return errors.New("nil item")
   415  	}
   416  	arr, ok := item.Value().([]stackitem.Item)
   417  	if !ok {
   418  		return errors.New("not an array")
   419  	}
   420  	if len(arr) != 3 {
   421  		return errors.New("wrong number of structure elements")
   422  	}
   423  
   424  	var (
   425  		index = -1
   426  		err   error
   427  	)
   428  	index++
   429  	e.Name, err = func(item stackitem.Item) (string, error) {
   430  		b, err := item.TryBytes()
   431  		if err != nil {
   432  			return "", err
   433  		}
   434  		if !utf8.Valid(b) {
   435  			return "", errors.New("not a UTF-8 string")
   436  		}
   437  		return string(b), nil
   438  	}(arr[index])
   439  	if err != nil {
   440  		return fmt.Errorf("field Name: %w", err)
   441  	}
   442  
   443  	index++
   444  	e.OldAdmin, err = func(item stackitem.Item) (util.Uint160, error) {
   445  		b, err := item.TryBytes()
   446  		if err != nil {
   447  			return util.Uint160{}, err
   448  		}
   449  		u, err := util.Uint160DecodeBytesBE(b)
   450  		if err != nil {
   451  			return util.Uint160{}, err
   452  		}
   453  		return u, nil
   454  	}(arr[index])
   455  	if err != nil {
   456  		return fmt.Errorf("field OldAdmin: %w", err)
   457  	}
   458  
   459  	index++
   460  	e.NewAdmin, err = func(item stackitem.Item) (util.Uint160, error) {
   461  		b, err := item.TryBytes()
   462  		if err != nil {
   463  			return util.Uint160{}, err
   464  		}
   465  		u, err := util.Uint160DecodeBytesBE(b)
   466  		if err != nil {
   467  			return util.Uint160{}, err
   468  		}
   469  		return u, nil
   470  	}(arr[index])
   471  	if err != nil {
   472  		return fmt.Errorf("field NewAdmin: %w", err)
   473  	}
   474  
   475  	return nil
   476  }
   477  
   478  // RenewEventsFromApplicationLog retrieves a set of all emitted events
   479  // with "Renew" name from the provided [result.ApplicationLog].
   480  func RenewEventsFromApplicationLog(log *result.ApplicationLog) ([]*RenewEvent, error) {
   481  	if log == nil {
   482  		return nil, errors.New("nil application log")
   483  	}
   484  
   485  	var res []*RenewEvent
   486  	for i, ex := range log.Executions {
   487  		for j, e := range ex.Events {
   488  			if e.Name != "Renew" {
   489  				continue
   490  			}
   491  			event := new(RenewEvent)
   492  			err := event.FromStackItem(e.Item)
   493  			if err != nil {
   494  				return nil, fmt.Errorf("failed to deserialize RenewEvent from stackitem (execution #%d, event #%d): %w", i, j, err)
   495  			}
   496  			res = append(res, event)
   497  		}
   498  	}
   499  
   500  	return res, nil
   501  }
   502  
   503  // FromStackItem converts provided [stackitem.Array] to RenewEvent or
   504  // returns an error if it's not possible to do to so.
   505  func (e *RenewEvent) FromStackItem(item *stackitem.Array) error {
   506  	if item == nil {
   507  		return errors.New("nil item")
   508  	}
   509  	arr, ok := item.Value().([]stackitem.Item)
   510  	if !ok {
   511  		return errors.New("not an array")
   512  	}
   513  	if len(arr) != 3 {
   514  		return errors.New("wrong number of structure elements")
   515  	}
   516  
   517  	var (
   518  		index = -1
   519  		err   error
   520  	)
   521  	index++
   522  	e.Name, err = func(item stackitem.Item) (string, error) {
   523  		b, err := item.TryBytes()
   524  		if err != nil {
   525  			return "", err
   526  		}
   527  		if !utf8.Valid(b) {
   528  			return "", errors.New("not a UTF-8 string")
   529  		}
   530  		return string(b), nil
   531  	}(arr[index])
   532  	if err != nil {
   533  		return fmt.Errorf("field Name: %w", err)
   534  	}
   535  
   536  	index++
   537  	e.OldExpiration, err = arr[index].TryInteger()
   538  	if err != nil {
   539  		return fmt.Errorf("field OldExpiration: %w", err)
   540  	}
   541  
   542  	index++
   543  	e.NewExpiration, err = arr[index].TryInteger()
   544  	if err != nil {
   545  		return fmt.Errorf("field NewExpiration: %w", err)
   546  	}
   547  
   548  	return nil
   549  }