-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
address.go
128 lines (107 loc) · 3.68 KB
/
address.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
package models
import (
"database/sql/driver"
"encoding/hex"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/smartcontractkit/chainlink/core/logger"
"github.com/smartcontractkit/chainlink/core/utils"
)
// EIP55Address is a newtype for string which persists an ethereum address in
// its original string representation which includes a leading 0x, and EIP55
// checksum which is represented by the case of digits A-F.
type EIP55Address string
// NewEIP55Address creates an EIP55Address from a string, an error is returned if:
//
// 1) There is no leading 0x
// 2) The length is wrong
// 3) There are any non hexadecimal characters
// 4) The checksum fails
//
func NewEIP55Address(s string) (EIP55Address, error) {
address := common.HexToAddress(s)
if s != address.Hex() {
return EIP55Address(""), fmt.Errorf(`"%s" is not a valid EIP55 formatted address`, s)
}
return EIP55Address(s), nil
}
func EIP55AddressFromAddress(a common.Address) (EIP55Address, error) {
return NewEIP55Address(a.Hex())
}
// Bytes returns the raw bytes
func (a EIP55Address) Bytes() []byte { return a.Address().Bytes() }
// Big returns a big.Int representation
func (a EIP55Address) Big() *big.Int { return a.Address().Hash().Big() }
// Hash returns the Hash
func (a EIP55Address) Hash() common.Hash { return a.Address().Hash() }
// Address returns EIP55Address as a go-ethereum Address type
func (a EIP55Address) Address() common.Address { return common.HexToAddress(a.String()) }
// String implements the stringer interface and is used also by the logger.
func (a EIP55Address) String() string {
return string(a)
}
// Hex is idential to String but makes the API similar to common.Address
func (a EIP55Address) Hex() string {
return a.String()
}
// Format implements fmt.Formatter
func (a EIP55Address) Format(s fmt.State, c rune) {
_, err := fmt.Fprint(s, a.String())
logger.ErrorIf(err, "failed when format EIP55Address to state")
}
// UnmarshalText parses a hash from plain text
func (a *EIP55Address) UnmarshalText(input []byte) error {
var err error
*a, err = NewEIP55Address(string(input))
return err
}
// UnmarshalJSON parses a hash from a JSON string
func (a *EIP55Address) UnmarshalJSON(input []byte) error {
input = utils.RemoveQuotes(input)
return a.UnmarshalText(input)
}
// Value returns this instance serialized for database storage.
func (a EIP55Address) Value() (driver.Value, error) {
return a.Bytes(), nil
}
// Scan reads the database value and returns an instance.
func (a *EIP55Address) Scan(value interface{}) error {
switch v := value.(type) {
case string:
*a = EIP55Address(v)
case []byte:
address := common.HexToAddress("0x" + hex.EncodeToString(v))
*a = EIP55Address(address.Hex())
default:
return fmt.Errorf("unable to convert %v of %T to EIP55Address", value, value)
}
return nil
}
// EIP55AddressCollection is an array of EIP55Addresses.
type EIP55AddressCollection []EIP55Address
// Value returns this instance serialized for database storage.
func (c EIP55AddressCollection) Value() (driver.Value, error) {
// Unable to convert copy-free without unsafe:
// https://stackoverflow.com/a/48554123/639773
converted := make([]string, len(c))
for i, e := range c {
converted[i] = string(e)
}
return strings.Join(converted, ","), nil
}
// Scan reads the database value and returns an instance.
func (c *EIP55AddressCollection) Scan(value interface{}) error {
temp, ok := value.(string)
if !ok {
return fmt.Errorf("unable to convert %v of %T to EIP55AddressCollection", value, value)
}
arr := strings.Split(temp, ",")
collection := make(EIP55AddressCollection, len(arr))
for i, r := range arr {
collection[i] = EIP55Address(r)
}
*c = collection
return nil
}