package resolver import ( "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // ResolveHash resolves contract hash. func ResolveHash(cli *rpcclient.Client, domain string) (util.Uint160, error) { nnsCs, err := cli.GetContractStateByID(1) if err != nil { return util.Uint160{}, fmt.Errorf("get NNS contract by id: %w", err) } item, err := nnsResolve(invoker.New(cli, nil), nnsCs.Hash, domain) if err != nil { return util.Uint160{}, err } return parseNNSResolveResult(item) } func nnsResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stackitem.Item, error) { return unwrap.Item(inv.Call(nnsHash, "resolve", domain, int64(nns.TXT))) } // parseNNSResolveResult parses the result of resolving NNS record. // It works with multiple formats (corresponding to multiple NNS versions). // If array of hashes is provided, it returns only the first one. func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) { arr, ok := res.Value().([]stackitem.Item) if !ok { arr = []stackitem.Item{res} } if _, ok := res.Value().(stackitem.Null); ok || len(arr) == 0 { return util.Uint160{}, errors.New("NNS record is missing") } for i := range arr { bs, err := arr[i].TryBytes() if err != nil { continue } h, err := address.StringToUint160(string(bs)) if err == nil { return h, nil } h, err = util.Uint160DecodeStringLE(string(bs)) if err == nil { return h, nil } } return util.Uint160{}, errors.New("no valid hashes are found") }