/
address.go
112 lines (93 loc) · 3.18 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
package models
import (
"database/sql/driver"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"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
}
// 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().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)
}
// Format implements fmt.Formatter
func (a EIP55Address) Format(s fmt.State, c rune) {
fmt.Fprint(s, a.String())
}
// 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.String(), nil
}
// Scan reads the database value and returns an instance.
func (a *EIP55Address) Scan(value interface{}) error {
temp, ok := value.(string)
if !ok {
return fmt.Errorf("Unable to convert %v of %T to EIP55Address", value, value)
}
*a = EIP55Address(temp)
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
}