/
token.go
103 lines (88 loc) · 2.34 KB
/
token.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
package core
import (
"context"
"fmt"
"math/big"
"unicode/utf8"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/gelfand/contract-feed/internal/token"
)
// token method IDs
var (
symbolMethodID = common.FromHex("0x95d89b41")
nameMethodID = common.FromHex("0x06fdde03")
)
var big10 = big.NewInt(10)
type Token struct {
Address common.Address
Name string
Symbol string
TotalSupply *big.Int
}
func (t Token) ToMsg() string {
// TODO: make function wrappers for bold text and for hyperlinks.
return fmt.Sprintf("Address: <a href=\"https://etherscan.io/token/%s\"><b>%s</b></a>\n"+
"Name: <b>%s</b>\n"+
"Symbol: <b>%s</b>\n"+
"TotalSupply: <b>%v</b>\n"+
"Twitter: <a href=\"https://twitter.com/search?q=$%s&f=live\"><b>$%s</b></a> <a href=\"https://twitter.com/search?q=%s&f=live\"><b>Address</b></a>",
t.Address.String(), t.Address.String(),
t.Name,
t.Symbol,
t.TotalSupply,
t.Symbol, t.Symbol, t.Address,
)
}
func (c *Coordinator) isToken(ctx context.Context, addr common.Address) bool {
// two checks would be sufficiently enough.
msg := ethereum.CallMsg{
To: &addr,
Data: symbolMethodID,
}
if _, err := c.client.PendingCallContract(ctx, msg); err != nil {
return false
}
msg = ethereum.CallMsg{
To: &addr,
Data: nameMethodID,
}
if _, err := c.client.PendingCallContract(ctx, msg); err != nil {
return false
}
return true
}
// getTokenData retrieves token data by it's address.
func (c *Coordinator) getTokenData(tokenAddr common.Address) (Token, error) {
// I faced it already, but might try without it.
t, err := token.NewTokenCaller(tokenAddr, c.client)
if err != nil {
return Token{}, err
}
name, err := t.Name(&bind.CallOpts{})
if err != nil {
return Token{}, fmt.Errorf("could not retrieve token name: %w", err)
}
if !utf8.ValidString(name) {
name = ""
}
symbol, err := t.Symbol(&bind.CallOpts{})
if err != nil {
return Token{}, fmt.Errorf("could not retrieve token symbol: %w", err)
}
if !utf8.ValidString(symbol) {
symbol = ""
}
var totalSupply *big.Int
totalSupply, err = t.TotalSupply(&bind.CallOpts{})
if err != nil {
totalSupply = big.NewInt(0)
}
return Token{
Address: tokenAddr,
Name: name,
Symbol: symbol,
TotalSupply: totalSupply,
}, nil
}