-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
181 lines (169 loc) · 5.26 KB
/
main.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package main
import (
"bytes"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"strconv"
"strings"
"github.com/SIGBlockchain/aurum_client/internal/config"
"github.com/SIGBlockchain/aurum_client/internal/contracts"
"github.com/SIGBlockchain/aurum_client/internal/requests"
"github.com/SIGBlockchain/aurum_client/internal/wallet"
)
type Opts struct {
version *bool
setup *bool
info *bool
update *bool
value *string
recipient *string
producer *string
}
func main() {
log.SetFlags(0)
cfg, err := config.LoadConfiguration()
if err != nil {
log.Printf("Failed to load configuration file: %v", err)
os.Exit(1)
}
options := Opts{
version: flag.Bool("version", false, "client version"),
setup: flag.Bool("setup", false, "set up client"),
info: flag.Bool("info", false, "wallet info"),
update: flag.Bool("update", false, "update wallet info"),
recipient: flag.String("to", "", "recipient"),
value: flag.String("send", "", "value to send"),
producer: flag.String("producer", cfg.ProducerAddress, "IP address of the producer"),
}
flag.Parse()
if *options.version {
checkFlagCount(1)
log.Printf("Aurum client version: %d\n", cfg.Version)
}
if *options.info {
checkFlagCount(1)
if err := wallet.PrintInfo(); err != nil {
log.Fatalf("Failed to get wallet contents: %v\n", err)
}
return
}
if *options.producer != cfg.ProducerAddress {
//check if a valid ip was given
parts := strings.Split(*options.producer, ":")
if len(parts) != 2 {
log.Fatalf("%s is not a valid ip:port address", *options.producer)
}
port, err := strconv.Atoi(parts[1])
if err != nil || port > 65535 {
log.Fatalf("Invalid port %s", parts[1])
}
if net.ParseIP(parts[0]) == nil {
log.Fatalf("Invalid IP address \"%s\"", parts[0])
}
cfg.ProducerAddress = *options.producer
defer config.SaveConfiguration(cfg)
}
if *options.setup {
checkFlagCount(1)
log.Println("Initializing Aurum wallet...")
if err := wallet.SetupWallet(); err != nil {
log.Fatalf("Failed to set up wallet: %v\n", err)
}
log.Println("Wallet setup complete.")
if err := wallet.PrintInfo(); err != nil {
log.Fatalf("Failed to print wallet info: %v\n", err)
}
return
}
if *options.update {
checkFlagCount(1)
cli := new(http.Client)
walletAddress, err := wallet.GetWalletAddress()
if err != nil {
log.Fatalf("Failed to extract wallet address: %v\n", err)
}
req, err := requests.NewAccountInfoRequest(cfg.ProducerAddress, hex.EncodeToString(walletAddress))
if err != nil {
log.Fatalf("Failed to make update request: %v\n", err)
}
fmt.Println("Requesting wallet update from producer...")
resp, err := cli.Do(req)
if err != nil {
log.Fatalf("Failed getting response from producer: %v\n", err)
}
if resp.StatusCode != http.StatusOK {
// TODO: Include some kind of response body
log.Fatalf("Status code: %v\n", resp.StatusCode)
}
defer resp.Body.Close()
updatedWallet := new(wallet.Wallet)
body, err := ioutil.ReadAll(resp.Body)
if err := json.Unmarshal(body, &updatedWallet); err != nil {
log.Fatalf("Failed to unmarshall response body: %v\n", err)
}
defer resp.Body.Close()
if err := wallet.UpdateWallet(updatedWallet.Balance, updatedWallet.StateNonce); err != nil {
log.Fatalf("Failed to update wallet: %v\n", err)
}
log.Println("Wallet updated successfully.")
return
}
if *options.value != "" && *options.recipient != "" {
if !wallet.ValidRecipLen(*options.recipient) {
log.Fatalf("Recipient input is not 64 characters long\n")
}
newContract, err := contracts.ContractMessageFromInput(cfg.Version, *options.value, *options.recipient)
if err != nil {
log.Fatalf("Failed to construct new contract: %v\n", err)
}
cli := new(http.Client)
req, err := requests.NewContractRequest(cfg.ProducerAddress, *newContract)
if err != nil {
log.Fatalf("Failed to make contract request: %v\n", err)
}
fmt.Printf("Sending contract request with %s to %s", *options.value, *options.recipient)
resp, err := cli.Do(req)
if err != nil {
log.Fatalf("Failed getting response from producer: %v\n", err)
}
if resp.StatusCode != http.StatusOK {
buf := new(bytes.Buffer)
_, err := resp.Body.Read(buf.Bytes())
if err != nil {
log.Fatalf("Failed to read body of response: %v\n", err)
}
// TODO: Try again with incremented nonce
log.Println("Please wait for next block to be produced or update wallet.")
log.Fatalf("Status code: %v\nBody: %s\n", resp.StatusCode, buf.String())
}
defer resp.Body.Close()
currentBalance, err := wallet.GetBalance()
if err != nil {
log.Fatalf("Failed to get current balance: %v\n", err)
}
currentNonce, err := wallet.GetStateNonce()
if err != nil {
log.Fatalf("Failed to get current nonce: %v\n", err)
}
intVal, err := strconv.Atoi(*options.value)
if err != nil {
log.Fatalf("Failed to convert value to integer: %v", err)
}
if err := wallet.UpdateWallet(currentBalance-uint64(intVal), currentNonce+1); err != nil {
log.Fatalf("Failed to update wallet: %v\n", err)
}
log.Println("Successfully sent contract to producer.\nContract will be confirmed once next block is producer.")
}
}
func checkFlagCount(limit int) {
if flag.NFlag() > limit {
log.Fatalln("Too many arguments")
}
}