/
cns_service.go
162 lines (145 loc) · 5.31 KB
/
cns_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package cns
import (
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/realcoooool/fiscov3-sdk/abi/bind"
"github.com/realcoooool/fiscov3-sdk/client"
"github.com/realcoooool/fiscov3-sdk/core/types"
"github.com/realcoooool/fiscov3-sdk/precompiled"
)
// cns precompiled contract error code
const (
versionLengthOverflow int64 = -51201
addressAndVersionExist int64 = -51200
)
// getErrorMessage returns the message of error code
func getErrorMessage(errorCode int64) string {
var message string
switch errorCode {
case versionLengthOverflow:
message = "version length overflow"
case addressAndVersionExist:
message = "address and version exist"
default:
message = ""
}
return message
}
// errorCodeToError judges whether the error code represents an error
func errorCodeToError(errorCode int64) error {
var errorCodeMessage string
errorCodeMessage = precompiled.GetCommonErrorCodeMessage(errorCode)
if errorCodeMessage != "" {
return fmt.Errorf("error code: %v, error code message: %v", errorCode, errorCodeMessage)
}
errorCodeMessage = getErrorMessage(errorCode)
if errorCodeMessage != "" {
return fmt.Errorf("error code: %v, error code message: %v", errorCode, errorCodeMessage)
}
return nil
}
// Info is used for the CNSService
type Info struct {
Name string `json:"name"`
Version string `json:"version"`
Address string `json:"address"`
Abi string `json:"abi"`
}
// Service is a precompile contract service.
type Service struct {
cns *Cns
cnsAuth *bind.TransactOpts
client *client.Client
}
const maxVersionLength = 40
// contract address
var cnsPrecompileAddress = common.HexToAddress("0x0000000000000000000000000000000000001004")
// NewCnsService returns ptr of Service
func NewCnsService(client *client.Client) (*Service, error) {
instance, err := NewCns(cnsPrecompileAddress, client)
if err != nil {
return nil, fmt.Errorf("construct Service failed: %+v", err)
}
auth := client.GetTransactOpts()
return &Service{cns: instance, cnsAuth: auth, client: client}, nil
}
// SelectByName returns the cns information according to the name string.
func (service *Service) SelectByName(name string) (string, error) {
opts := &bind.CallOpts{From: service.cnsAuth.From}
cnsName, err := service.cns.SelectByName(opts, name)
if err != nil {
return "", fmt.Errorf("service SelectByName failed: %+v", err)
}
return cnsName, nil
}
// SelectByNameAndVersion returns the cns information according to the name string and version string.
func (service *Service) SelectByNameAndVersion(name string, version string) (string, error) {
opts := &bind.CallOpts{From: service.cnsAuth.From}
cnsName, err := service.cns.SelectByNameAndVersion(opts, name, version)
if err != nil {
return "", fmt.Errorf("service SelectByNameAndVersion failed: %+v", err)
}
return cnsName, nil
}
// GetAddressByContractNameAndVersion returns the contract address.
func (service *Service) GetAddressByContractNameAndVersion(contractName, version string) (common.Address, error) {
opts := &bind.CallOpts{From: service.cnsAuth.From}
address, err := service.cns.GetContractAddress(opts, contractName, version)
if err != nil {
return common.Address{}, fmt.Errorf("service GetAddressByContractNameAndVersion failed: %+v", err)
}
return address, nil
}
// RegisterCns registers a contract for its CNS.
func (service *Service) RegisterCns(name string, version string, address common.Address, abi string) (int64, error) {
if len(version) > maxVersionLength {
return precompiled.DefaultErrorCode, fmt.Errorf("version string length exceeds the maximum limit")
}
_, receipt, err := service.cns.Insert(service.cnsAuth, name, version, address.String(), abi)
if err != nil {
return precompiled.DefaultErrorCode, fmt.Errorf("service RegisterCns failed: %+v", err)
}
return parseReturnValue(receipt, "insert")
}
// QueryCnsByName returns the CNS info according to the CNS name
func (service *Service) QueryCnsByName(name string) ([]Info, error) {
cnsInfo, err := service.SelectByName(name)
if err != nil {
return nil, err
}
// json unmarshal
var infos []Info
if err := json.Unmarshal([]byte(cnsInfo), &infos); err != nil {
return nil, fmt.Errorf("unmarshal the Info failed")
}
return infos, nil
}
// QueryCnsByNameAndVersion returns the CNS info according to the name and version
func (service *Service) QueryCnsByNameAndVersion(name string, version string) ([]Info, error) {
cnsInfo, err := service.SelectByNameAndVersion(name, version)
if err != nil {
return nil, err
}
// json unmarshal
var infos []Info
if err := json.Unmarshal([]byte(cnsInfo), &infos); err != nil {
return nil, fmt.Errorf("unmarshal the Info failed")
}
return infos, nil
}
func parseReturnValue(receipt *types.Receipt, name string) (int64, error) {
errorMessage := receipt.GetErrorMessage()
if errorMessage != "" {
return int64(receipt.GetStatus()), fmt.Errorf("receipt.Status err: %v", errorMessage)
}
bigNum, err := precompiled.ParseBigIntFromOutput(receipt)
if err != nil {
return precompiled.DefaultErrorCode, fmt.Errorf("ParseBigIntFromOutput failed, err: %v, txHah: %v", err, receipt.TransactionHash)
}
errorCode, err := precompiled.BigIntToInt64(bigNum)
if err != nil {
return precompiled.DefaultErrorCode, fmt.Errorf("parseReturnValue failed, err: %v, txHah: %v", err, receipt.TransactionHash)
}
return errorCode, errorCodeToError(errorCode)
}