forked from zupzup/eth-prepaid-transaction
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
124 lines (113 loc) · 3.87 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
package main
import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/render"
"github.com/go-chi/cors"
"github.com/pressly/chi"
"log"
"math/big"
"net/http"
)
var key = "b4087f10eacc3a032a2d550c02ae7a3ff88bc62eb0d9f6c02c9d5ef4d1562862"
// Agreement is an agreement
type Agreement struct {
Account string `json:"account"`
Agreement string `json:"agreement"`
}
// Bind binds the request parameters
func (a *Agreement) Bind(r *http.Request) error {
return nil
}
var nonceCounter int64
func main() {
// setup
privKey, err := crypto.HexToECDSA(key)
if err != nil {
log.Fatalf("Failed to convert private key: %v", err)
}
conn, err := ethclient.Dial("http://localhost:8545")
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}
auth := bind.NewKeyedTransactor(privKey)
if err != nil {
log.Fatalf("Failed to create Transactor: %v", err)
}
auth.Nonce = big.NewInt(nonceCounter)
// contract deployment
addr, _, contract, err := DeploySigner(auth, conn)
if err != nil {
log.Fatalf("Failed to deploy contract: %v", err)
}
fmt.Println("Contract Deployed to: ", addr.String())
// webserver setup
r := chi.NewRouter()
corsOption := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
AllowCredentials: true,
MaxAge: 300,
})
r.Use(corsOption.Handler)
r.Use(middleware.Logger)
r.Post("/agreement", createAgreementHandler(contract, auth, conn, privKey))
log.Println("Server started on localhost:8080")
log.Fatal(http.ListenAndServe(":8080", r))
}
// createAgreementHandler adds the provided agreement, if it is valid, to the contract and sends the client a transaction fee, so they can sign it from their side
func createAgreementHandler(contract *Signer, auth *bind.TransactOpts, conn *ethclient.Client, privKey *ecdsa.PrivateKey) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Create Agreement
agreement := &Agreement{}
if err := render.Bind(r, agreement); err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Invalid Request, Account and Agreement need to be set"))
return
}
if agreement.Account == "" || agreement.Agreement == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Account and Agreement need to be set"))
return
}
nonceCounter = nonceCounter + 1
_, err := contract.CreateAgreement(&bind.TransactOpts{
From: auth.From,
Signer: auth.Signer,
GasLimit: big.NewInt(200000),
Value: big.NewInt(0),
Nonce: big.NewInt(nonceCounter),
}, agreement.Agreement, common.HexToAddress(agreement.Account))
if err != nil {
log.Fatalf("Failed to create agreement: %v", err)
}
fmt.Println("Agreement created: ", agreement.Agreement)
// Send enough Gas to the Client so they can sign
nonceCounter = nonceCounter + 1
gasPrice, err := conn.SuggestGasPrice(context.Background())
if err != nil {
log.Fatalf("Failed to get gas price: %v", err)
}
signer := types.HomesteadSigner{}
tx := types.NewTransaction(uint64(nonceCounter), common.HexToAddress(agreement.Account), big.NewInt(100000), big.NewInt(21000), gasPrice, nil)
signed, err := types.SignTx(tx, signer, privKey)
if err != nil {
log.Fatalf("Failed to sign transaction: %v", err)
}
err = conn.SendTransaction(context.Background(), signed)
if err != nil {
log.Fatalf("Failed to send transaction: %v", err)
}
fmt.Println("Transaction Fee sent to client!")
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
}