mirror of
https://github.com/number571/blockchain.git
synced 2026-09-12 19:50:00 +05:00
add ethereum examples
This commit is contained in:
parent
eb07f8a186
commit
58ab8edc6c
8
.gitignore
vendored
8
.gitignore
vendored
@ -2,10 +2,18 @@ mainbc
|
||||
mainnt
|
||||
node
|
||||
client
|
||||
client_eth
|
||||
gclient
|
||||
gclient_eth
|
||||
node1.key
|
||||
node2.key
|
||||
chain1.db
|
||||
chain2.db
|
||||
todo.txt
|
||||
blockchain.db
|
||||
contract.address
|
||||
deploy
|
||||
contracts/Contract.go
|
||||
build/WorldSkills.abi
|
||||
build/WorldSkills.bin
|
||||
abigen
|
||||
|
||||
15
Makefile
15
Makefile
@ -1,6 +1,15 @@
|
||||
.PHONY: default build
|
||||
default: build
|
||||
build: node.go client.go gclient.go serve.go values.go
|
||||
.PHONY: default xbuild ybuild
|
||||
default: xbuild ybuild
|
||||
# Self-written part
|
||||
xbuild: node.go client.go gclient.go serve.go values.go
|
||||
go build -o node node.go serve.go values.go
|
||||
go build -o client client.go values.go
|
||||
go build -o gclient gclient.go values.go
|
||||
# Ethereum part
|
||||
ybuild: contract.sol deploy.go client_eth.go gclient_eth.go values_eth.go
|
||||
solc --overwrite --abi --bin contract.sol -o build
|
||||
mkdir -p contracts
|
||||
./abigen --bin=./build/WorldSkills.bin --abi=./build/WorldSkills.abi --pkg=contract --out=./contracts/Contract.go
|
||||
go build -o deploy deploy.go
|
||||
go build -o client_eth client_eth.go values_eth.go
|
||||
go build -o gclient_eth gclient_eth.go values_eth.go
|
||||
|
||||
720
client_eth.go
Normal file
720
client_eth.go
Normal file
@ -0,0 +1,720 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"bufio"
|
||||
"context"
|
||||
"strings"
|
||||
"math/big"
|
||||
"encoding/json"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if len(os.Args) < 2 {
|
||||
panic("failed: len(os.Args) < 2")
|
||||
}
|
||||
var (
|
||||
userLoadStr = ""
|
||||
userLoadExist = false
|
||||
)
|
||||
for i := 1; i < len(os.Args); i++ {
|
||||
arg := os.Args[i]
|
||||
switch {
|
||||
case strings.HasPrefix(arg, "-loaduser:"):
|
||||
userLoadStr = strings.Replace(arg, "-loaduser:", "", 1)
|
||||
userLoadExist = true
|
||||
}
|
||||
}
|
||||
if !userLoadExist {
|
||||
panic("failed: !userLoadExist")
|
||||
}
|
||||
if ClientETH == nil {
|
||||
panic("failed: connect to ETH")
|
||||
}
|
||||
if Instance == nil {
|
||||
panic("failed: instance is nil")
|
||||
}
|
||||
User = loadUser(userLoadStr)
|
||||
if User == nil {
|
||||
panic("failed: load user")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
message string
|
||||
splited []string
|
||||
)
|
||||
for {
|
||||
message = inputString("> ")
|
||||
splited = strings.Split(message, " ")
|
||||
switch splited[0] {
|
||||
case "/exit":
|
||||
os.Exit(0)
|
||||
case "/user":
|
||||
if len(splited) < 2 {
|
||||
fmt.Println("failed: len(user) < 2\n")
|
||||
continue
|
||||
}
|
||||
switch splited[1] {
|
||||
case "address":
|
||||
userAddress()
|
||||
case "purse":
|
||||
userPurse()
|
||||
case "balance":
|
||||
userBalance()
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
case "/chain":
|
||||
if len(splited) < 3 {
|
||||
fmt.Println("failed: len(chain) < 3\n")
|
||||
continue
|
||||
}
|
||||
switch splited[1] {
|
||||
case "get":
|
||||
switch splited[2] {
|
||||
case "estates":
|
||||
// chain get estates address
|
||||
chainGetEstates(splited[2:])
|
||||
case "presents":
|
||||
// chain get presents address
|
||||
chainGetPresents(splited[2:])
|
||||
case "sales":
|
||||
// chain get sales address
|
||||
chainGetSales(splited[2:])
|
||||
case "rents":
|
||||
// chain get rents address
|
||||
chainGetRents(splited[2:])
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
case "create":
|
||||
switch splited[2] {
|
||||
case "estate":
|
||||
// chain create estate address info squere usefulSquere
|
||||
chainCreateEstate(splited[2:])
|
||||
case "present":
|
||||
// chain create present id_estate address
|
||||
chainCreatePresent(splited[2:])
|
||||
case "sale":
|
||||
// chain create sale id_estate money
|
||||
chainCreateSale(splited[2:])
|
||||
case "rent":
|
||||
// chain create rent id_estate hours price
|
||||
chainCreateRent(splited[2:])
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
case "cancel":
|
||||
switch splited[2] {
|
||||
case "present":
|
||||
// chain cancel present id_present
|
||||
chainCancelPresent(splited[2:])
|
||||
case "sale":
|
||||
// chain cancel sale id_sale
|
||||
chainCancelSale(splited[2:])
|
||||
case "rent":
|
||||
// chain cancel rent id_rent
|
||||
chainCancelRent(splited[2:])
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
case "confirm":
|
||||
switch splited[2] {
|
||||
case "present":
|
||||
// chain confirm present id_present
|
||||
chainConfirmPresent(splited[2:])
|
||||
case "sale":
|
||||
// chain confirm sale id_sale id_customer
|
||||
chainConfirmSale(splited[2:])
|
||||
case "rent":
|
||||
// chain confirm rent id_rent
|
||||
chainConfirmRent(splited[2:])
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
case "try-buy":
|
||||
// chain try-buy id_sale money
|
||||
chainTryBuy(splited[1:])
|
||||
case "cancel-buy":
|
||||
// chain cancel-buy id_sale
|
||||
chainCancelBuy(splited[1:])
|
||||
case "finish-rent":
|
||||
// chain finish-rent id_rent
|
||||
finishRent(splited[1:])
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
default:
|
||||
fmt.Println("command undefined\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func chainTryBuy(splited []string) {
|
||||
if len(splited) != 3 {
|
||||
fmt.Println("failed: len(splited) != 3\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
saleNumber = new(big.Int)
|
||||
value = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
saleNumber, ok = saleNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
value, ok = value.SetString(splited[2], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str2) to num\n")
|
||||
return
|
||||
}
|
||||
auth := resetAuth(User)
|
||||
if auth == nil {
|
||||
fmt.Println("failed: auth is nil\n")
|
||||
return
|
||||
}
|
||||
auth.Value = value
|
||||
tx, err := Instance.CheckToBuy(
|
||||
auth,
|
||||
saleNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCancelBuy(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
saleNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
saleNumber, ok = saleNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CancelToBuy(
|
||||
resetAuth(User),
|
||||
saleNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func finishRent(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
rentNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
rentNumber, ok = rentNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.FinishRent(
|
||||
resetAuth(User),
|
||||
rentNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCreateEstate(splited []string) {
|
||||
if len(splited) != 5 {
|
||||
fmt.Println("failed: len(splited) != 5\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
squere = new(big.Int)
|
||||
usefulSquere = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
squere, ok = squere.SetString(splited[3], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
usefulSquere, ok = usefulSquere.SetString(splited[4], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str2) to num\n")
|
||||
return
|
||||
}
|
||||
var address common.Address
|
||||
if splited[1] == "my" {
|
||||
address = User.AddressEth
|
||||
} else {
|
||||
address = common.HexToAddress(splited[1])
|
||||
}
|
||||
tx, err := Instance.CreateEstate(
|
||||
resetAuth(User),
|
||||
address,
|
||||
splited[2],
|
||||
squere,
|
||||
usefulSquere,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCreatePresent(splited []string) {
|
||||
if len(splited) != 3 {
|
||||
fmt.Println("failed: len(splited) != 3\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
estateId = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
estateId, ok = estateId.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CreatePresent(
|
||||
resetAuth(User),
|
||||
estateId,
|
||||
common.HexToAddress(splited[2]),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCreateSale(splited []string) {
|
||||
if len(splited) != 3 {
|
||||
fmt.Println("failed: len(splited) != 3\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
estateId = new(big.Int)
|
||||
price = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
estateId, ok = estateId.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
price, ok = price.SetString(splited[2], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str2) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CreateSale(
|
||||
resetAuth(User),
|
||||
estateId,
|
||||
price,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCreateRent(splited []string) {
|
||||
if len(splited) != 4 {
|
||||
fmt.Println("failed: len(splited) != 4\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
estateId = new(big.Int)
|
||||
hours = new(big.Int)
|
||||
price = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
estateId, ok = estateId.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
hours, ok = hours.SetString(splited[2], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str2) to num\n")
|
||||
return
|
||||
}
|
||||
price, ok = price.SetString(splited[3], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str3) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CreateRent(
|
||||
resetAuth(User),
|
||||
estateId,
|
||||
hours,
|
||||
price,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCancelPresent(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
presentNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
presentNumber, ok = presentNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CancelPresent(
|
||||
resetAuth(User),
|
||||
presentNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCancelSale(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
saleNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
saleNumber, ok = saleNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CancelSale(
|
||||
resetAuth(User),
|
||||
saleNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainCancelRent(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
rentNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
rentNumber, ok = rentNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.CancelRent(
|
||||
resetAuth(User),
|
||||
rentNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainConfirmPresent(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
presentNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
presentNumber, ok = presentNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.ConfirmPresent(
|
||||
resetAuth(User),
|
||||
presentNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainConfirmSale(splited []string) {
|
||||
if len(splited) != 3 {
|
||||
fmt.Println("failed: len(splited) != 3\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
saleNumber = new(big.Int)
|
||||
saleTo = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
saleNumber, ok = saleNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
saleTo, ok = saleTo.SetString(splited[2], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str2) to num\n")
|
||||
return
|
||||
}
|
||||
tx, err := Instance.ConfirmSale(
|
||||
resetAuth(User),
|
||||
saleNumber,
|
||||
saleTo,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainConfirmRent(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var (
|
||||
rentNumber = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
rentNumber, ok = rentNumber.SetString(splited[1], 10)
|
||||
if !ok {
|
||||
fmt.Println("failed: conv(str1) to num\n")
|
||||
return
|
||||
}
|
||||
rent := getRents(rentNumber)
|
||||
if rent == nil {
|
||||
fmt.Println("failed: get rent\n")
|
||||
return
|
||||
}
|
||||
auth := resetAuth(User)
|
||||
if auth == nil {
|
||||
fmt.Println("failed: auth is nil\n")
|
||||
return
|
||||
}
|
||||
auth.Value = rent.Money
|
||||
tx, err := Instance.ToRent(
|
||||
auth,
|
||||
rentNumber,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Tx:", tx.Hash().Hex(), "\n")
|
||||
}
|
||||
|
||||
func chainGetEstates(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
estatesnum, err := Instance.GetEstatesNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0) ; index.Cmp(estatesnum) == -1; index.Add(index, inc) {
|
||||
data := getEstates(index)
|
||||
if data == nil {
|
||||
fmt.Println("data is nil\n")
|
||||
return
|
||||
}
|
||||
if splited[1] == "my" && User.AddressHex != data.Owner.Hex() {
|
||||
continue
|
||||
}
|
||||
if splited[1] != "all" && splited[1] != "my" &&
|
||||
strings.ToLower(splited[1]) != strings.ToLower(data.Owner.Hex()) {
|
||||
continue
|
||||
}
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func chainGetPresents(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
prenetsnum, err := Instance.GetPresentsNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(prenetsnum) == -1; index.Add(index, inc) {
|
||||
data := getPresents(index)
|
||||
if data == nil {
|
||||
fmt.Println("data is nil\n")
|
||||
return
|
||||
}
|
||||
if data.Finished {
|
||||
continue
|
||||
}
|
||||
if splited[1] == "my" &&
|
||||
(User.AddressHex != data.AddressFrom.Hex() && User.AddressHex != data.AddressTo.Hex()){
|
||||
continue
|
||||
}
|
||||
if splited[1] != "all" && splited[1] != "my" &&
|
||||
(strings.ToLower(splited[1]) != strings.ToLower(data.AddressFrom.Hex()) &&
|
||||
strings.ToLower(splited[1]) != strings.ToLower(data.AddressTo.Hex())) {
|
||||
continue
|
||||
}
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func chainGetSales(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
salesnum, err := Instance.GetSalesNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(salesnum) == -1; index.Add(index, inc) {
|
||||
data := getSales(index)
|
||||
if data == nil {
|
||||
fmt.Println("data is nil\n")
|
||||
return
|
||||
}
|
||||
if data.Finished {
|
||||
continue
|
||||
}
|
||||
if splited[1] == "my" && User.AddressHex != data.Owner.Hex() {
|
||||
continue
|
||||
}
|
||||
if splited[1] != "all" && splited[1] != "my" &&
|
||||
strings.ToLower(splited[1]) != strings.ToLower(data.Owner.Hex()) {
|
||||
continue
|
||||
}
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func chainGetRents(splited []string) {
|
||||
if len(splited) != 2 {
|
||||
fmt.Println("failed: len(splited) != 2\n")
|
||||
return
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
rentsnum, err := Instance.GetRentsNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(rentsnum) == -1; index.Add(index, inc) {
|
||||
data := getRents(index)
|
||||
if data == nil {
|
||||
fmt.Println("data is nil\n")
|
||||
return
|
||||
}
|
||||
if data.Finished {
|
||||
continue
|
||||
}
|
||||
if splited[1] == "my" &&
|
||||
(User.AddressHex != data.Owner.Hex() && User.AddressHex != data.Renter.Hex()){
|
||||
continue
|
||||
}
|
||||
if splited[1] != "all" && splited[1] != "my" &&
|
||||
(strings.ToLower(splited[1]) != strings.ToLower(data.Owner.Hex()) &&
|
||||
strings.ToLower(splited[1]) != strings.ToLower(data.Renter.Hex())) {
|
||||
continue
|
||||
}
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println(string(jsonData))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func userAddress() {
|
||||
fmt.Println("Address:", User.AddressHex, "\n")
|
||||
}
|
||||
|
||||
func userPurse() {
|
||||
fmt.Println("Purse:", User.Purse, "\n")
|
||||
}
|
||||
|
||||
func userBalance() {
|
||||
balance, err := ClientETH.BalanceAt(context.Background(), User.AddressEth, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err, "\n")
|
||||
return
|
||||
}
|
||||
fmt.Println("Balance:", balance, "\n")
|
||||
}
|
||||
|
||||
func inputString(begin string) string {
|
||||
fmt.Print(begin)
|
||||
msg, _ := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
return strings.Replace(msg, "\n", "", 1)
|
||||
}
|
||||
256
contract.sol
Normal file
256
contract.sol
Normal file
@ -0,0 +1,256 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
|
||||
contract WorldSkills {
|
||||
|
||||
struct Estate {
|
||||
uint estate_id;
|
||||
address owner;
|
||||
string info;
|
||||
uint squere;
|
||||
uint useful_squere;
|
||||
address renter_address;
|
||||
bool present_status;
|
||||
bool sale_status;
|
||||
bool rent_status;
|
||||
}
|
||||
|
||||
struct Present {
|
||||
uint estate_id;
|
||||
address address_from;
|
||||
address address_to;
|
||||
bool finished;
|
||||
}
|
||||
|
||||
struct Sale {
|
||||
uint estate_id;
|
||||
address owner;
|
||||
uint price;
|
||||
address payable[] customers;
|
||||
uint[] prices;
|
||||
bool finished;
|
||||
}
|
||||
|
||||
struct Rent {
|
||||
uint estate_id;
|
||||
address payable owner_address;
|
||||
address payable renter_address;
|
||||
uint time;
|
||||
uint money;
|
||||
uint deadline;
|
||||
bool finished;
|
||||
}
|
||||
|
||||
Estate[] estates;
|
||||
Present[] presents;
|
||||
Sale[] sales;
|
||||
Rent[] rents;
|
||||
|
||||
address admin = msg.sender;
|
||||
address payable default_address = 0x0000000000000000000000000000000000000000;
|
||||
|
||||
// ADD FUNCTION
|
||||
function iam_admin() public view returns(bool) {
|
||||
return msg.sender == admin;
|
||||
}
|
||||
|
||||
function get_estates_number() public view returns(uint) {
|
||||
return estates.length;
|
||||
}
|
||||
|
||||
function get_presents_number() public view returns(uint) {
|
||||
return presents.length;
|
||||
}
|
||||
|
||||
function get_sales_number() public view returns(uint) {
|
||||
return sales.length;
|
||||
}
|
||||
|
||||
function get_rents_number() public view returns(uint) {
|
||||
return rents.length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function get_estates(uint estate_number) public view returns(uint, address, string memory, uint, uint, address) {
|
||||
return(estates[estate_number].estate_id, estates[estate_number].owner, estates[estate_number].info, estates[estate_number].squere, estates[estate_number].useful_squere, estates[estate_number].renter_address);
|
||||
}
|
||||
|
||||
function get_estates_statuses(uint estate_number) public view returns(bool, bool, bool) {
|
||||
return(estates[estate_number].present_status, estates[estate_number].sale_status, estates[estate_number].rent_status);
|
||||
}
|
||||
|
||||
function get_presents(uint present_number) public view returns(uint, address, address, bool) {
|
||||
return(presents[present_number].estate_id, presents[present_number].address_from, presents[present_number].address_to, presents[present_number].finished);
|
||||
}
|
||||
|
||||
function get_sales(uint sale_number) public view returns(uint, address, uint, address payable[] memory, uint[] memory prices, bool) {
|
||||
return(sales[sale_number].estate_id, sales[sale_number].owner, sales[sale_number].price, sales[sale_number].customers, sales[sale_number].prices, sales[sale_number].finished);
|
||||
}
|
||||
|
||||
function get_rents(uint rent_number) public view returns(uint, address, address, uint, uint, uint, bool) {
|
||||
return(rents[rent_number].estate_id, rents[rent_number].owner_address, rents[rent_number].renter_address, rents[rent_number].time, rents[rent_number].money, rents[rent_number].deadline, rents[rent_number].finished);
|
||||
}
|
||||
|
||||
modifier status_OK(uint estate_id) {
|
||||
require(estates[estate_id].present_status == false);
|
||||
require(estates[estate_id].sale_status == false);
|
||||
require(estates[estate_id].rent_status == false);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier is_owner(uint estate_id) {
|
||||
require(msg.sender == estates[estate_id].owner);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier is_admin {
|
||||
require(msg.sender == admin);
|
||||
_;
|
||||
}
|
||||
|
||||
//Admin's function
|
||||
// РАБОТАЕТ
|
||||
//Создать объект собственности
|
||||
function create_estate(address owner, string memory info, uint squere, uint useful_squere) public is_admin{
|
||||
estates.push(Estate(estates.length, owner, info, squere, useful_squere, 0x0000000000000000000000000000000000000000, false, false, false));
|
||||
}
|
||||
|
||||
//Present's functions
|
||||
|
||||
// Создать предложение подарка
|
||||
function create_present(uint estate_id, address address_to) public status_OK(estate_id) is_owner(estate_id) {
|
||||
presents.push(Present(estate_id, msg.sender, address_to, false));
|
||||
estates[estate_id].present_status = true;
|
||||
}
|
||||
|
||||
// Отменить свой подарок(доступна до принятие подарка адресатом)
|
||||
function cancel_present(uint present_number) payable public {
|
||||
require(msg.sender == presents[present_number].address_from);
|
||||
require(presents[present_number].finished == false);
|
||||
estates[presents[present_number].estate_id].present_status = false;
|
||||
presents[present_number].finished = true;
|
||||
|
||||
}
|
||||
|
||||
// Принять подарок
|
||||
function confirm_present(uint present_number) payable public {
|
||||
require(msg.sender == presents[present_number].address_to);
|
||||
require(presents[present_number].finished == false);
|
||||
estates[presents[present_number].estate_id].owner = presents[present_number].address_to;
|
||||
estates[presents[present_number].estate_id].present_status = false;
|
||||
presents[present_number].finished = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Sale's functions
|
||||
|
||||
// Разместить объявление о продаже
|
||||
function create_sale(uint estate_id, uint price) public status_OK(estate_id) is_owner(estate_id){
|
||||
address payable[] memory customers;
|
||||
uint[] memory prices;
|
||||
sales.push(Sale(estate_id, msg.sender, price, customers, prices, false));
|
||||
estates[estate_id].sale_status = true;
|
||||
}
|
||||
|
||||
// Отменить объявление о продаже и вернуть деньги всем, кто успел внести
|
||||
function cancel_sale(uint sale_number) public {
|
||||
require(msg.sender == sales[sale_number].owner);
|
||||
require(sales[sale_number].finished == false);
|
||||
for (uint i = 0; i < sales[sale_number].customers.length; i++){
|
||||
(sales[sale_number].customers[i]).transfer(sales[sale_number].prices[i]);
|
||||
}
|
||||
estates[sales[sale_number].estate_id].sale_status = false;
|
||||
sales[sale_number].finished = true;
|
||||
|
||||
}
|
||||
|
||||
// Выбрать чтобы купить
|
||||
function check_to_buy(uint sale_number) public payable {
|
||||
require(msg.sender != sales[sale_number].owner);
|
||||
require(msg.value >= sales[sale_number].price);
|
||||
require(sales[sale_number].finished == false);
|
||||
uint status = 0;
|
||||
for (uint i=0; i < sales[sale_number].customers.length; i++) {
|
||||
if (sales[sale_number].customers[i] == msg.sender) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
require(status == 0);
|
||||
sales[sale_number].customers.push(msg.sender);
|
||||
sales[sale_number].prices.push(msg.value);
|
||||
}
|
||||
|
||||
// Отменить выбор покупки
|
||||
function cancel_to_buy(uint sale_number) public payable {
|
||||
require(sales[sale_number].finished == false);
|
||||
for (uint i=0; i<sales[sale_number].customers.length; i++){
|
||||
if (sales[sale_number].customers[i] == msg.sender){
|
||||
msg.sender.transfer(sales[sale_number].prices[i]);
|
||||
delete sales[sale_number].prices[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Подтвердить продажу и вернуть деньги остальным
|
||||
function confirm_sale(uint sale_number, uint sale_to) public payable {
|
||||
require(msg.sender == sales[sale_number].owner);
|
||||
require(sales[sale_number].prices[sale_to] != 0);
|
||||
require(sales[sale_number].finished == false);
|
||||
estates[sales[sale_number].estate_id].owner = sales[sale_number].customers[sale_to];
|
||||
msg.sender.transfer(sales[sale_number].prices[sale_to]);
|
||||
for (uint i=0; i<sales[sale_number].customers.length; i++){
|
||||
if (i != sale_to) {
|
||||
sales[sale_number].customers[i].transfer(sales[sale_number].prices[i]);
|
||||
}
|
||||
else {
|
||||
sales[sale_number].prices[sale_to] = 0;
|
||||
}
|
||||
}
|
||||
estates[sales[sale_number].estate_id].sale_status = false;
|
||||
sales[sale_number].finished = true;
|
||||
}
|
||||
|
||||
// Rent's function
|
||||
// Создание объявления об аренде
|
||||
function create_rent(uint estate_id, uint time, uint money) public is_owner(estate_id) status_OK(estate_id){
|
||||
rents.push(Rent(estate_id, msg.sender, default_address, time, money, 0, false));
|
||||
estates[estate_id].rent_status=true;
|
||||
}
|
||||
|
||||
// Арендовать
|
||||
function to_rent(uint rent_id) public payable{
|
||||
require(rents[rent_id].finished == false);
|
||||
require(rents[rent_id].renter_address == default_address);
|
||||
require(rents[rent_id].owner_address != msg.sender);
|
||||
// CHANGE require(rents[rent_id].money != msg.value);
|
||||
// TO require(rents[rent_id].money == msg.value);
|
||||
require(rents[rent_id].money == msg.value);
|
||||
rents[rent_id].renter_address = msg.sender;
|
||||
estates[rents[rent_id].estate_id].renter_address = msg.sender;
|
||||
rents[rent_id].deadline = now + rents[rent_id].time*86400;
|
||||
rents[rent_id].owner_address.transfer(rents[rent_id].money);
|
||||
}
|
||||
|
||||
//Отменить объявление об аренде
|
||||
function cancel_rent(uint rent_id) public {
|
||||
require(rents[rent_id].finished == false);
|
||||
require(rents[rent_id].owner_address == msg.sender);
|
||||
require(rents[rent_id].renter_address == default_address);
|
||||
estates[rents[rent_id].estate_id].rent_status=false;
|
||||
rents[rent_id].finished = true;
|
||||
}
|
||||
|
||||
//Истечение срока аренды
|
||||
// ADD 'is_owner(rents[rent_id].estate_id)''
|
||||
function finish_rent(uint rent_id) public is_owner(rents[rent_id].estate_id) {
|
||||
require(rents[rent_id].finished == false);
|
||||
require(rents[rent_id].deadline < now);
|
||||
estates[rents[rent_id].estate_id].renter_address = default_address;
|
||||
estates[rents[rent_id].estate_id].rent_status=false;
|
||||
rents[rent_id].finished = true;
|
||||
}
|
||||
}
|
||||
135
deploy.go
Normal file
135
deploy.go
Normal file
@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"strings"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
contract "./contracts"
|
||||
)
|
||||
|
||||
type UserType struct {
|
||||
Purse string
|
||||
AddressHex string
|
||||
AddressEth common.Address
|
||||
PublicKey *ecdsa.PublicKey
|
||||
PrivateKey *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
var (
|
||||
ClientETH = connectToETH("http://127.0.0.1:5555")
|
||||
User *UserType
|
||||
)
|
||||
|
||||
func init() {
|
||||
if len(os.Args) < 2 {
|
||||
panic("failed: len(os.Args) < 2")
|
||||
}
|
||||
var (
|
||||
userLoadStr = ""
|
||||
userLoadExist = false
|
||||
)
|
||||
for i := 1; i < len(os.Args); i++ {
|
||||
arg := os.Args[i]
|
||||
switch {
|
||||
case strings.HasPrefix(arg, "-loaduser:"):
|
||||
userLoadStr = strings.Replace(arg, "-loaduser:", "", 1)
|
||||
userLoadExist = true
|
||||
}
|
||||
}
|
||||
if !userLoadExist {
|
||||
panic("failed: !userLoadExist")
|
||||
}
|
||||
if ClientETH == nil {
|
||||
panic("failed: connect to ETH")
|
||||
}
|
||||
User = userLoad(userLoadStr)
|
||||
if User == nil {
|
||||
panic("failed: load user")
|
||||
}
|
||||
}
|
||||
|
||||
// Deploy contract and save address in file.
|
||||
func main() {
|
||||
auth := resetAuth(User)
|
||||
address, tx, instance, err := contract.DeployContract(auth, ClientETH)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(address.Hex())
|
||||
fmt.Println(tx.Hash().Hex())
|
||||
_ = instance
|
||||
|
||||
contractFile := "contract.address"
|
||||
writeFile(contractFile, address.Hex())
|
||||
}
|
||||
|
||||
func writeFile(filename string, data string) error {
|
||||
return ioutil.WriteFile(filename, []byte(data), 0644)
|
||||
}
|
||||
|
||||
func userLoad(purse string) *UserType {
|
||||
priv, err := crypto.HexToECDSA(purse)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
pub, ok := priv.Public().(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
addressHex := crypto.PubkeyToAddress(*pub).Hex()
|
||||
addressEth := common.HexToAddress(addressHex)
|
||||
return &UserType{
|
||||
Purse: purse,
|
||||
AddressHex: addressHex,
|
||||
AddressEth: addressEth,
|
||||
PublicKey: pub,
|
||||
PrivateKey: priv,
|
||||
}
|
||||
}
|
||||
|
||||
func connectToETH(address string) *ethclient.Client {
|
||||
client, err := ethclient.Dial(address)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func resetAuth(user *UserType) *bind.TransactOpts {
|
||||
nonce, err := ClientETH.PendingNonceAt(context.Background(), User.AddressEth)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
gasPrice, err := ClientETH.SuggestGasPrice(context.Background())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
auth := bind.NewKeyedTransactor(user.PrivateKey)
|
||||
auth.Nonce = big.NewInt(int64(nonce))
|
||||
auth.Value = big.NewInt(0)
|
||||
|
||||
// auth.GasLimit = uint64(3000000)
|
||||
auth.GasPrice = gasPrice
|
||||
|
||||
return auth
|
||||
}
|
||||
|
||||
func fileIsExist(name string) bool {
|
||||
if _, err := os.Stat(name); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
905
gclient_eth.go
Normal file
905
gclient_eth.go
Normal file
@ -0,0 +1,905 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"strings"
|
||||
"context"
|
||||
"net/http"
|
||||
"math/big"
|
||||
"html/template"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const (
|
||||
STTC_PATH = "static/"
|
||||
TMPL_PATH = "templates_eth/"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if ClientETH == nil {
|
||||
panic("failed: connect to ETH")
|
||||
}
|
||||
if Instance == nil {
|
||||
panic("failed: instance is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("Server is running ...")
|
||||
|
||||
http.Handle("/static/", http.StripPrefix(
|
||||
"/static/",
|
||||
handleFileServer(http.Dir(STTC_PATH))),
|
||||
)
|
||||
|
||||
http.HandleFunc("/", indexPage)
|
||||
http.HandleFunc("/login", loginPage)
|
||||
http.HandleFunc("/logout", logoutPage)
|
||||
http.HandleFunc("/account", accountPage)
|
||||
|
||||
http.HandleFunc("/blockchain", blockchainPage)
|
||||
http.HandleFunc("/blockchain/estates", blockchainEstatesPage)
|
||||
http.HandleFunc("/blockchain/presents", blockchainPresentsPage)
|
||||
http.HandleFunc("/blockchain/sales", blockchainSalesPage)
|
||||
http.HandleFunc("/blockchain/rents", blockchainRentsPage)
|
||||
|
||||
http.HandleFunc("/blockchain/estates/", blockchainEstatesXPage)
|
||||
http.HandleFunc("/blockchain/presents/", blockchainPresentsXPage)
|
||||
http.HandleFunc("/blockchain/sales/", blockchainSalesXPage)
|
||||
http.HandleFunc("/blockchain/rents/", blockchainRentsXPage)
|
||||
|
||||
http.HandleFunc("/blockchain/presents/do/", blockchainPresentsDoPage)
|
||||
http.HandleFunc("/blockchain/sales/do/", blockchainSalesDoPage)
|
||||
http.HandleFunc("/blockchain/rents/do/", blockchainRentsDoPage)
|
||||
|
||||
http.ListenAndServe(":7545", nil)
|
||||
}
|
||||
|
||||
func handleFileServer(fs http.FileSystem) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := fs.Open(r.URL.Path); os.IsNotExist(err) {
|
||||
indexPage(w, r)
|
||||
return
|
||||
}
|
||||
http.FileServer(fs).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func indexPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"index.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
}
|
||||
data.User = User
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func loginPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"login.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Error string
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
User = loadUser(r.FormValue("private"))
|
||||
if User == nil {
|
||||
data.Error = "Load Private Key Error"
|
||||
} else {
|
||||
http.Redirect(w, r, "/", 302)
|
||||
return
|
||||
}
|
||||
}
|
||||
data.User = User
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func logoutPage(w http.ResponseWriter, r *http.Request) {
|
||||
User = nil
|
||||
http.Redirect(w, r, "/", 302)
|
||||
}
|
||||
|
||||
func accountPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"account.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Address string
|
||||
Balance string
|
||||
}
|
||||
data.User = User
|
||||
if data.User != nil {
|
||||
data.Address = User.AddressHex
|
||||
balance, err := ClientETH.BalanceAt(context.Background(), User.AddressEth, nil)
|
||||
if err == nil {
|
||||
data.Balance = balance.String()
|
||||
}
|
||||
} else {
|
||||
http.Redirect(w, r, "/", 302)
|
||||
return
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainPresentsDoPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"presentsDo.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *EstateStr
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/presents/do/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
estate := getEstates(index)
|
||||
if estate == nil {
|
||||
data.Error = "estate is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = estatesToString(estate)
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
_, err := Instance.CreatePresent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
common.HexToAddress(r.FormValue("address")),
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success created"
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainSalesDoPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"salesDo.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *EstateStr
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/sales/do/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
estate := getEstates(index)
|
||||
if estate == nil {
|
||||
data.Error = "estate is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = estatesToString(estate)
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
var (
|
||||
price = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
price, ok = price.SetString(r.FormValue("price"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
_, err := Instance.CreateSale(
|
||||
resetAuth(User),
|
||||
index,
|
||||
price,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success created"
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainRentsDoPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"rentsDo.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *EstateStr
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/rents/do/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
rent := getEstates(index)
|
||||
if rent == nil {
|
||||
data.Error = "rent is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = estatesToString(rent)
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
var (
|
||||
days = new(big.Int)
|
||||
price = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
days, ok = days.SetString(r.FormValue("days"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
price, ok = price.SetString(r.FormValue("price"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
_, err := Instance.CreateRent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
days,
|
||||
price,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success created"
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainEstatesXPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"estatesX.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *EstateStr
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/estates/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
estate := getEstates(index)
|
||||
if estate == nil {
|
||||
data.Error = "estate is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = estatesToString(estate)
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainPresentsXPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"presentsX.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *PresentStr
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/presents/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
present := getPresents(index)
|
||||
if present == nil {
|
||||
data.Error = "present is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = presentsToString(present)
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
if r.FormValue("cancel") != "" {
|
||||
_, err := Instance.CancelPresent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success cancel"
|
||||
}
|
||||
if r.FormValue("confirm") != "" {
|
||||
_, err := Instance.ConfirmPresent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success confirm"
|
||||
}
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainSalesXPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"salesX.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *SaleStr
|
||||
Error string
|
||||
InCustomers bool
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/sales/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
sale := getSales(index)
|
||||
if sale == nil {
|
||||
data.Error = "sale is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = salesToString(sale)
|
||||
for _, cust := range data.Block.Customers {
|
||||
if cust == User.AddressHex {
|
||||
data.InCustomers = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
if r.FormValue("cancel") != "" {
|
||||
_, err := Instance.CancelSale(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success cancel"
|
||||
}
|
||||
if r.FormValue("confirm") != "" {
|
||||
var (
|
||||
saleTo = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
saleTo, ok = saleTo.SetString(r.FormValue("addrnum"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
_, err := Instance.ConfirmSale(
|
||||
resetAuth(User),
|
||||
index,
|
||||
saleTo,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success confirm"
|
||||
}
|
||||
if r.FormValue("buy") != "" {
|
||||
var (
|
||||
price = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
price, ok = price.SetString(r.FormValue("price"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
auth := resetAuth(User)
|
||||
if auth == nil {
|
||||
data.Error = "failed: auth is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
auth.Value = price
|
||||
_, err := Instance.CheckToBuy(
|
||||
auth,
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success buy request"
|
||||
}
|
||||
if r.FormValue("close") != "" {
|
||||
_, err := Instance.CancelToBuy(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success close buy request"
|
||||
}
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainRentsXPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"rentsX.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
Block *RentStr
|
||||
Error string
|
||||
Confirmed bool
|
||||
}
|
||||
data.User = User
|
||||
var (
|
||||
index = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
num := strings.Replace(r.URL.Path, "/blockchain/rents/", "", 1)
|
||||
index, ok = index.SetString(num, 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
rent := getRents(index)
|
||||
if rent == nil {
|
||||
data.Error = "rent is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Block = rentsToString(rent)
|
||||
if data.Block.Renter != "0x0000000000000000000000000000000000000000" {
|
||||
data.Confirmed = true
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
if r.FormValue("cancel") != "" {
|
||||
_, err := Instance.CancelRent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success cancel"
|
||||
}
|
||||
if r.FormValue("confirm") != "" {
|
||||
auth := resetAuth(User)
|
||||
if auth == nil {
|
||||
data.Error = "failed: auth is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
auth.Value = rent.Money
|
||||
_, err := Instance.ToRent(
|
||||
auth,
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success confirm"
|
||||
}
|
||||
if r.FormValue("finish") != "" {
|
||||
_, err := Instance.FinishRent(
|
||||
resetAuth(User),
|
||||
index,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success finish"
|
||||
}
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"blockchain.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
User *UserType
|
||||
IsAdmin bool
|
||||
Error string
|
||||
}
|
||||
data.User = User
|
||||
iamAdmin, err := Instance.IamAdmin(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
if iamAdmin {
|
||||
data.IsAdmin = true
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
var (
|
||||
squere = new(big.Int)
|
||||
usefulSquere = new(big.Int)
|
||||
ok bool
|
||||
)
|
||||
squere, ok = squere.SetString(r.FormValue("squere"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error 1"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
usefulSquere, ok = usefulSquere.SetString(r.FormValue("usefulsquere"), 10)
|
||||
if !ok {
|
||||
data.Error = "strconv error 2"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
_, err := Instance.CreateEstate(
|
||||
resetAuth(User),
|
||||
User.AddressEth,
|
||||
r.FormValue("info"),
|
||||
squere,
|
||||
usefulSquere,
|
||||
)
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
data.Error = "Success created"
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainEstatesPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"estates.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
Error string
|
||||
Blocks []uint64
|
||||
Address string
|
||||
User *UserType
|
||||
}
|
||||
data.User = User
|
||||
data.Address = User.AddressHex
|
||||
if r.Method == "POST" {
|
||||
data.Address = r.FormValue("address")
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
num, err := Instance.GetEstatesNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(num) == -1; index.Add(index, inc) {
|
||||
block := getEstates(index)
|
||||
if block == nil {
|
||||
data.Error = "data is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
if data.Address != "all" && strings.ToLower(data.Address) != strings.ToLower(block.Owner.Hex()) {
|
||||
continue
|
||||
}
|
||||
data.Blocks = append(data.Blocks, index.Uint64())
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainPresentsPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"presents.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
Error string
|
||||
Blocks []uint64
|
||||
Address string
|
||||
User *UserType
|
||||
}
|
||||
data.User = User
|
||||
data.Address = User.AddressHex
|
||||
if r.Method == "POST" {
|
||||
data.Address = r.FormValue("address")
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
num, err := Instance.GetPresentsNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(num) == -1; index.Add(index, inc) {
|
||||
block := getPresents(index)
|
||||
if block == nil {
|
||||
data.Error = "data is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
if block.Finished {
|
||||
continue
|
||||
}
|
||||
if data.Address != "all" &&
|
||||
strings.ToLower(data.Address) != strings.ToLower(block.AddressFrom.Hex()) &&
|
||||
strings.ToLower(data.Address) != strings.ToLower(block.AddressTo.Hex()) {
|
||||
continue
|
||||
}
|
||||
data.Blocks = append(data.Blocks, index.Uint64())
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainSalesPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"sales.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
Error string
|
||||
Blocks []uint64
|
||||
Address string
|
||||
User *UserType
|
||||
}
|
||||
data.User = User
|
||||
data.Address = User.AddressHex
|
||||
if r.Method == "POST" {
|
||||
data.Address = r.FormValue("address")
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
num, err := Instance.GetSalesNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(num) == -1; index.Add(index, inc) {
|
||||
block := getSales(index)
|
||||
if block == nil {
|
||||
data.Error = "data is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
if block.Finished {
|
||||
continue
|
||||
}
|
||||
if data.Address != "all" &&
|
||||
strings.ToLower(data.Address) != strings.ToLower(block.Owner.Hex()) {
|
||||
continue
|
||||
}
|
||||
data.Blocks = append(data.Blocks, index.Uint64())
|
||||
}
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func blockchainRentsPage(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := template.ParseFiles(
|
||||
TMPL_PATH+"base.html",
|
||||
TMPL_PATH+"rents.html",
|
||||
)
|
||||
if err != nil {
|
||||
panic("can't load hmtl files")
|
||||
}
|
||||
if User == nil {
|
||||
http.Redirect(w, r, "/login", 302)
|
||||
return
|
||||
}
|
||||
var data struct{
|
||||
Error string
|
||||
Blocks []uint64
|
||||
Address string
|
||||
User *UserType
|
||||
}
|
||||
data.User = User
|
||||
data.Address = User.AddressHex
|
||||
if r.Method == "POST" {
|
||||
data.Address = r.FormValue("address")
|
||||
}
|
||||
var inc = big.NewInt(1)
|
||||
num, err := Instance.GetRentsNumber(&bind.CallOpts{From: User.AddressEth})
|
||||
if err != nil {
|
||||
data.Error = err.Error()
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
for index := big.NewInt(0); index.Cmp(num) == -1; index.Add(index, inc) {
|
||||
block := getRents(index)
|
||||
if block == nil {
|
||||
data.Error = "data is nil"
|
||||
t.Execute(w, data)
|
||||
return
|
||||
}
|
||||
if block.Finished {
|
||||
continue
|
||||
}
|
||||
if data.Address != "all" &&
|
||||
strings.ToLower(data.Address) != strings.ToLower(block.Owner.Hex()) &&
|
||||
strings.ToLower(data.Address) != strings.ToLower(block.Renter.Hex()) {
|
||||
continue
|
||||
}
|
||||
data.Blocks = append(data.Blocks, index.Uint64())
|
||||
}
|
||||
|
||||
t.Execute(w, data)
|
||||
}
|
||||
18
templates_eth/account.html
Normal file
18
templates_eth/account.html
Normal file
@ -0,0 +1,18 @@
|
||||
{{define "title"}}
|
||||
Account
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-12 mx-auto">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<input id="address" readonly class="form-control bg-light" type="text" name="coins" value="Address: {{ .Address }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input readonly class="form-control bg-light" type="text" name="coins" value="Balance: {{ if .Balance }} {{ .Balance }} {{ else }} 0 {{ end }} coins;">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
43
templates_eth/base.html
Normal file
43
templates_eth/base.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
{{block "title" .}}
|
||||
Title
|
||||
{{end}}
|
||||
</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a href="/" class="navbar-brand" exact><h4>Home</h4></a>
|
||||
<div class="navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<a href="/blockchain" class="nav-link"><h5>Blockchain</h5></a>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
{{ if (not .User) }}
|
||||
<!-- <a href="/signup" class="nav-link"><h5>Signup</h5></a> -->
|
||||
<a href="/login" class="nav-link"><h5>Login</h5></a>
|
||||
{{ else }}
|
||||
<!-- <a href="/transaction" class="nav-link"><h5>Transaction</h5></a> -->
|
||||
<a href="/account" class="nav-link"><h5>Account</h5></a>
|
||||
<a href="/logout" class="nav-link"><h5>Logout</h5></a>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<div class="col-md-9 mx-auto">
|
||||
{{block "content" .}}
|
||||
Content
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
45
templates_eth/blockchain.html
Normal file
45
templates_eth/blockchain.html
Normal file
@ -0,0 +1,45 @@
|
||||
{{define "title"}}
|
||||
Chain
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .IsAdmin }}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain">
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" name="info" placeholder="Information">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="number" name="squere" placeholder="Squere">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="number" name="usefulsquere" placeholder="Userful Squere">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Create">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="jumbotron">
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/estates">Estates</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/presents">Presents</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/sales">Sales</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/rents">Rents</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
32
templates_eth/estates.html
Normal file
32
templates_eth/estates.html
Normal file
@ -0,0 +1,32 @@
|
||||
{{define "title"}}
|
||||
Estates
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-12 mx-auto">
|
||||
<form method="POST" action="/blockchain/estates">
|
||||
<div class="form-group">
|
||||
{{ if .Address }}
|
||||
<input readonly class="form-control bg-light" type="text" name="coins" value="Address: {{ .Address }}">
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="address" placeholder="Address">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Get estates">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jumbotron">
|
||||
{{ if .Error }}
|
||||
{{ .Error }}
|
||||
{{ else }}
|
||||
{{ range $i, $e := .Blocks }}
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/estates/{{$e}}">[Estate {{ $e }}]</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{end}}
|
||||
63
templates_eth/estatesX.html
Normal file
63
templates_eth/estatesX.html
Normal file
@ -0,0 +1,63 @@
|
||||
{{define "title"}}
|
||||
Estate
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (and (eq .Block.Owner .User.AddressHex) (not .Block.PresentStatus) (not .Block.SaleStatus) (not .Block.RentStatus)) }}
|
||||
<div class="jumbotron">
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/presents/do/{{ .Block.Id }}">Do present</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/sales/do/{{ .Block.Id }}">Do sales</a>
|
||||
</div>
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/rents/do/{{ .Block.Id }}">Do rents</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Info</th>
|
||||
<td width="100%">{{ .Block.Info }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Squere</th>
|
||||
<td width="100%">{{ .Block.Squere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>UsefulSquere</th>
|
||||
<td width="100%">{{ .Block.UsefulSquere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RenterAddress</th>
|
||||
<td width="100%">{{ .Block.RenterAddress }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PresentStatus</th>
|
||||
<td width="100%">{{ .Block.PresentStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SaleStatus</th>
|
||||
<td width="100%">{{ .Block.SaleStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RentStatus</th>
|
||||
<td width="100%">{{ .Block.RentStatus }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
9
templates_eth/index.html
Normal file
9
templates_eth/index.html
Normal file
@ -0,0 +1,9 @@
|
||||
{{define "title"}}
|
||||
Index
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<h1 class="text-center">Blockchain</h1>
|
||||
</div>
|
||||
{{end}}
|
||||
22
templates_eth/login.html
Normal file
22
templates_eth/login.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{define "title"}}
|
||||
Login
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/login">
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="private" placeholder="Private Key">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="login" value="Login">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
32
templates_eth/presents.html
Normal file
32
templates_eth/presents.html
Normal file
@ -0,0 +1,32 @@
|
||||
{{define "title"}}
|
||||
Presents
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-12 mx-auto">
|
||||
<form method="POST" action="/blockchain/presents">
|
||||
<div class="form-group">
|
||||
{{ if .Address }}
|
||||
<input readonly class="form-control bg-light" type="text" name="coins" value="Address: {{ .Address }}">
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="address" placeholder="Address">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Get presents">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jumbotron">
|
||||
{{ if .Error }}
|
||||
<p>{{ .Error }}</p>
|
||||
{{ else }}
|
||||
{{ range $i, $e := .Blocks }}
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/presents/{{$e}}">[Presents {{ $e }}]</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{end}}
|
||||
62
templates_eth/presentsDo.html
Normal file
62
templates_eth/presentsDo.html
Normal file
@ -0,0 +1,62 @@
|
||||
{{define "title"}}
|
||||
Present
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Owner .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/presents/do/{{ .Block.Id }}">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="address" placeholder="Address">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Send present">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Info</th>
|
||||
<td width="100%">{{ .Block.Info }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Squere</th>
|
||||
<td width="100%">{{ .Block.Squere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>UsefulSquere</th>
|
||||
<td width="100%">{{ .Block.UsefulSquere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RenterAddress</th>
|
||||
<td width="100%">{{ .Block.RenterAddress }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PresentStatus</th>
|
||||
<td width="100%">{{ .Block.PresentStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SaleStatus</th>
|
||||
<td width="100%">{{ .Block.SaleStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RentStatus</th>
|
||||
<td width="100%">{{ .Block.RentStatus }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
52
templates_eth/presentsX.html
Normal file
52
templates_eth/presentsX.html
Normal file
@ -0,0 +1,52 @@
|
||||
{{define "title"}}
|
||||
Present
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.AddressFrom .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/presents/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="cancel" value="Cancel">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ if (eq .Block.AddressTo .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/presents/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="confirm" value="Confirm">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>EstateId</th>
|
||||
<td width="100%">{{ .Block.EstateId }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>AddressFrom</th>
|
||||
<td width="100%">{{ .Block.AddressFrom }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>AddressTo</th>
|
||||
<td width="100%">{{ .Block.AddressTo }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Finished</th>
|
||||
<td width="100%">{{ .Block.Finished }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
32
templates_eth/rents.html
Normal file
32
templates_eth/rents.html
Normal file
@ -0,0 +1,32 @@
|
||||
{{define "title"}}
|
||||
Rents
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-12 mx-auto">
|
||||
<form method="POST" action="/blockchain/rents">
|
||||
<div class="form-group">
|
||||
{{ if .Address }}
|
||||
<input readonly class="form-control bg-light" type="text" name="coins" value="Address: {{ .Address }}">
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="address" placeholder="Address">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Balance">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jumbotron">
|
||||
{{ if .Error }}
|
||||
Error: {{ .Error }}
|
||||
{{ else }}
|
||||
{{ range $i, $e := .Blocks }}
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/rents/{{$e}}">[Rents {{ $e }}]</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{end}}
|
||||
65
templates_eth/rentsDo.html
Normal file
65
templates_eth/rentsDo.html
Normal file
@ -0,0 +1,65 @@
|
||||
{{define "title"}}
|
||||
Rent
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Owner .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/rents/do/{{ .Block.Id }}">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" name="days" placeholder="Days">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" name="price" placeholder="Price">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Do rent">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Info</th>
|
||||
<td width="100%">{{ .Block.Info }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Squere</th>
|
||||
<td width="100%">{{ .Block.Squere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>UsefulSquere</th>
|
||||
<td width="100%">{{ .Block.UsefulSquere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RenterAddress</th>
|
||||
<td width="100%">{{ .Block.RenterAddress }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PresentStatus</th>
|
||||
<td width="100%">{{ .Block.PresentStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SaleStatus</th>
|
||||
<td width="100%">{{ .Block.SaleStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RentStatus</th>
|
||||
<td width="100%">{{ .Block.RentStatus }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
75
templates_eth/rentsX.html
Normal file
75
templates_eth/rentsX.html
Normal file
@ -0,0 +1,75 @@
|
||||
{{define "title"}}
|
||||
Rent
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Owner .User.AddressHex)}}
|
||||
{{ if (not .Confirmed) }}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/rents/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="cancel" value="Cancel">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/rents/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="finish" value="Finish">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end}}
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Renter "0x0000000000000000000000000000000000000000")}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/rents/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="confirm" value="Confirm">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>EstateId</th>
|
||||
<td width="100%">{{ .Block.EstateId }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Renter</th>
|
||||
<td width="100%">{{ .Block.Renter }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<td width="100%">{{ .Block.Time }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Money</th>
|
||||
<td width="100%">{{ .Block.Money }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>DeadLine</th>
|
||||
<td width="100%">{{ .Block.DeadLine }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Finished</th>
|
||||
<td width="100%">{{ .Block.Finished }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
32
templates_eth/sales.html
Normal file
32
templates_eth/sales.html
Normal file
@ -0,0 +1,32 @@
|
||||
{{define "title"}}
|
||||
Sales
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-12 mx-auto">
|
||||
<form method="POST" action="/blockchain/sales">
|
||||
<div class="form-group">
|
||||
{{ if .Address }}
|
||||
<input readonly class="form-control bg-light" type="text" name="coins" value="Address: {{ .Address }}">
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="address" placeholder="Address">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Get sales">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jumbotron">
|
||||
{{ if .Error }}
|
||||
<p>{{ .Error }}</p>
|
||||
{{ else }}
|
||||
{{ range $i, $e := .Blocks }}
|
||||
<div class="card">
|
||||
<a class="btn btn-info" href="/blockchain/sales/{{$e}}">[Sales {{ $e }}]</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
{{end}}
|
||||
62
templates_eth/salesDo.html
Normal file
62
templates_eth/salesDo.html
Normal file
@ -0,0 +1,62 @@
|
||||
{{define "title"}}
|
||||
Sale
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Owner .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/sales/do/{{ .Block.Id }}">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" name="price" placeholder="Price">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="submit" value="Do sale">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Info</th>
|
||||
<td width="100%">{{ .Block.Info }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Squere</th>
|
||||
<td width="100%">{{ .Block.Squere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>UsefulSquere</th>
|
||||
<td width="100%">{{ .Block.UsefulSquere }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RenterAddress</th>
|
||||
<td width="100%">{{ .Block.RenterAddress }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PresentStatus</th>
|
||||
<td width="100%">{{ .Block.PresentStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SaleStatus</th>
|
||||
<td width="100%">{{ .Block.SaleStatus }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RentStatus</th>
|
||||
<td width="100%">{{ .Block.RentStatus }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
95
templates_eth/salesX.html
Normal file
95
templates_eth/salesX.html
Normal file
@ -0,0 +1,95 @@
|
||||
{{define "title"}}
|
||||
Sale
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{ if .Error }}
|
||||
<div class="jumbotron">
|
||||
<p>{{ .Error }}</p>
|
||||
</div>
|
||||
{{ else }}
|
||||
{{ if (eq .Block.Owner .User.AddressHex )}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/sales/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="cancel" value="Cancel">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<form id="my_form" method="POST" action="/blockchain/sales/{{ .Block.Id }}">
|
||||
</form>
|
||||
{{ else }}
|
||||
{{ if .InCustomers}}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/sales/{{ .Block.Id }}">
|
||||
<input type="submit" class="btn btn-success w-100" name="close" value="Close">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="jumbotron">
|
||||
<div class="col-10 mx-auto">
|
||||
<form method="POST" action="/blockchain/sales/{{ .Block.Id }}">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control" name="price" value="{{ .Block.Price }}">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success w-100" name="buy" value="Buy">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td width="100%">{{ .Block.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>EstateId</th>
|
||||
<td width="100%">{{ .Block.EstateId }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner</th>
|
||||
<td width="100%">{{ .Block.Owner }} - {{ .User.AddressHex }} </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Price</th>
|
||||
<td width="100%">{{ .Block.Price }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Customers</th>
|
||||
<td>
|
||||
{{ $owner := .Block.Owner }}
|
||||
{{ $useraddr := .User.AddressHex }}
|
||||
{{ $prices := .Block.Prices }}
|
||||
{{ range $i, $e := .Block.Customers }}
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Customer</th>
|
||||
<td width="100%">{{ $e }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Price</th>
|
||||
<td width="100%">{{ index $prices $i }}</td>
|
||||
</tr>
|
||||
{{ if (eq $owner $useraddr) }}
|
||||
<tr>
|
||||
<th>Confirm</th>
|
||||
<td width="100%">
|
||||
<input form="my_form" type="hidden" name="addrnum" value="{{ $i }}">
|
||||
<input form="my_form" type="submit" class="btn btn-success w-100" name="confirm" value="Confirm">
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</table>
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Finished</th>
|
||||
<td width="100%">{{ .Block.Finished }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
301
values_eth.go
Normal file
301
values_eth.go
Normal file
@ -0,0 +1,301 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"io/ioutil"
|
||||
"crypto/ecdsa"
|
||||
contract "./contracts"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
)
|
||||
|
||||
type UserType struct {
|
||||
Purse string
|
||||
AddressHex string
|
||||
AddressEth common.Address
|
||||
PublicKey *ecdsa.PublicKey
|
||||
PrivateKey *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
type Estate struct{
|
||||
Id *big.Int
|
||||
Owner common.Address
|
||||
Info string
|
||||
Squere *big.Int
|
||||
UsefulSquere *big.Int
|
||||
RenterAddress common.Address
|
||||
PresentStatus bool
|
||||
SaleStatus bool
|
||||
RentStatus bool
|
||||
}
|
||||
|
||||
type Present struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
AddressFrom common.Address
|
||||
AddressTo common.Address
|
||||
Finished bool
|
||||
}
|
||||
|
||||
type Sale struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
Owner common.Address
|
||||
Price *big.Int
|
||||
Customers []common.Address
|
||||
Prices []*big.Int
|
||||
Finished bool
|
||||
}
|
||||
|
||||
type Rent struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
Owner common.Address
|
||||
Renter common.Address
|
||||
Time *big.Int
|
||||
Money *big.Int
|
||||
DeadLine *big.Int
|
||||
Finished bool
|
||||
}
|
||||
|
||||
var (
|
||||
User *UserType
|
||||
ClientETH = connectToETH("http://127.0.0.1:5555")
|
||||
ContractAddr = common.HexToAddress(readFile("contract.address"))
|
||||
Instance = newContract(ContractAddr, ClientETH)
|
||||
)
|
||||
|
||||
func loadUser(purse string) *UserType {
|
||||
priv, err := crypto.HexToECDSA(purse)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
pub, ok := priv.Public().(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
addressHex := crypto.PubkeyToAddress(*pub).Hex()
|
||||
addressEth := common.HexToAddress(addressHex)
|
||||
return &UserType{
|
||||
Purse: purse,
|
||||
AddressHex: addressHex,
|
||||
AddressEth: addressEth,
|
||||
PublicKey: pub,
|
||||
PrivateKey: priv,
|
||||
}
|
||||
}
|
||||
|
||||
func newContract(contractAddr common.Address, clientEth *ethclient.Client) *contract.Contract {
|
||||
instance, err := contract.NewContract(contractAddr, clientEth)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func connectToETH(address string) *ethclient.Client {
|
||||
client, err := ethclient.Dial(address)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func readFile(filename string) string {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func resetAuth(user *UserType) *bind.TransactOpts {
|
||||
nonce, err := ClientETH.PendingNonceAt(context.Background(), crypto.PubkeyToAddress(*user.PublicKey))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
gasPrice, err := ClientETH.SuggestGasPrice(context.Background())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
auth := bind.NewKeyedTransactor(user.PrivateKey)
|
||||
auth.Nonce = big.NewInt(int64(nonce))
|
||||
auth.Value = big.NewInt(0)
|
||||
|
||||
auth.GasLimit = uint64(3000000)
|
||||
auth.GasPrice = gasPrice
|
||||
|
||||
return auth
|
||||
}
|
||||
|
||||
func getEstates(index *big.Int) *Estate {
|
||||
// (*big.Int, common.Address, string, *big.Int, *big.Int, common.Address, error)
|
||||
id, owner, info, squere, usefulsquere, renteraddress, err := Instance.GetEstates(&bind.CallOpts{From: User.AddressEth}, index)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
presentS, saleS, rentS, err := Instance.GetEstatesStatuses(&bind.CallOpts{From: User.AddressEth}, index)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &Estate{
|
||||
Id: id,
|
||||
Owner: owner,
|
||||
Info: info,
|
||||
Squere: squere,
|
||||
UsefulSquere: usefulsquere,
|
||||
RenterAddress: renteraddress,
|
||||
PresentStatus: presentS,
|
||||
SaleStatus: saleS,
|
||||
RentStatus: rentS,
|
||||
}
|
||||
}
|
||||
|
||||
func getPresents(index *big.Int) *Present {
|
||||
// (*big.Int, common.Address, common.Address, bool, error)
|
||||
id, from, to, finished, err := Instance.GetPresents(&bind.CallOpts{From: User.AddressEth}, index)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &Present{
|
||||
Id: index,
|
||||
EstateId: id,
|
||||
AddressFrom: from,
|
||||
AddressTo: to,
|
||||
Finished: finished,
|
||||
}
|
||||
}
|
||||
|
||||
func getSales(index *big.Int) *Sale {
|
||||
// (*big.Int, common.Address, *big.Int, []common.Address, []*big.Int, bool, error)
|
||||
id, owner, price, customers, prices, finished, err := Instance.GetSales(&bind.CallOpts{From: User.AddressEth}, index)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &Sale{
|
||||
Id: index,
|
||||
EstateId: id,
|
||||
Owner: owner,
|
||||
Price: price,
|
||||
Customers: customers,
|
||||
Prices: prices,
|
||||
Finished: finished,
|
||||
}
|
||||
}
|
||||
|
||||
func getRents(index *big.Int) *Rent {
|
||||
// (*big.Int, common.Address, common.Address, *big.Int, *big.Int, *big.Int, bool, error)
|
||||
id, owner, renter, time, money, deadline, finished, err := Instance.GetRents(&bind.CallOpts{From: User.AddressEth}, index)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &Rent{
|
||||
Id: index,
|
||||
EstateId: id,
|
||||
Owner: owner,
|
||||
Renter: renter,
|
||||
Time: time,
|
||||
Money: money,
|
||||
DeadLine: deadline,
|
||||
Finished: finished,
|
||||
}
|
||||
}
|
||||
|
||||
type EstateStr struct {
|
||||
Id *big.Int
|
||||
Owner string
|
||||
Info string
|
||||
Squere *big.Int
|
||||
UsefulSquere *big.Int
|
||||
RenterAddress string
|
||||
PresentStatus bool
|
||||
SaleStatus bool
|
||||
RentStatus bool
|
||||
}
|
||||
|
||||
func estatesToString(estate *Estate) *EstateStr {
|
||||
return &EstateStr{
|
||||
Id: estate.Id,
|
||||
Owner: estate.Owner.Hex(),
|
||||
Info: estate.Info,
|
||||
Squere: estate.Squere,
|
||||
UsefulSquere: estate.UsefulSquere,
|
||||
RenterAddress: estate.RenterAddress.Hex(),
|
||||
PresentStatus: estate.PresentStatus,
|
||||
SaleStatus: estate.SaleStatus,
|
||||
RentStatus: estate.RentStatus,
|
||||
}
|
||||
}
|
||||
|
||||
type PresentStr struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
AddressFrom string
|
||||
AddressTo string
|
||||
Finished bool
|
||||
}
|
||||
|
||||
func presentsToString(present *Present) *PresentStr {
|
||||
return &PresentStr{
|
||||
Id: present.Id,
|
||||
EstateId: present.EstateId,
|
||||
AddressFrom: present.AddressFrom.Hex(),
|
||||
AddressTo: present.AddressTo.Hex(),
|
||||
Finished: present.Finished,
|
||||
}
|
||||
}
|
||||
|
||||
type SaleStr struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
Owner string
|
||||
Price *big.Int
|
||||
Customers []string
|
||||
Prices []*big.Int
|
||||
Finished bool
|
||||
}
|
||||
|
||||
func salesToString(sale *Sale) *SaleStr {
|
||||
var customers []string
|
||||
for _, cust := range sale.Customers {
|
||||
customers = append(customers, cust.Hex())
|
||||
}
|
||||
return &SaleStr{
|
||||
Id: sale.Id,
|
||||
EstateId: sale.EstateId,
|
||||
Owner: sale.Owner.Hex(),
|
||||
Price: sale.Price,
|
||||
Customers: customers,
|
||||
Prices: sale.Prices,
|
||||
Finished: sale.Finished,
|
||||
}
|
||||
}
|
||||
|
||||
type RentStr struct {
|
||||
Id *big.Int
|
||||
EstateId *big.Int
|
||||
Owner string
|
||||
Renter string
|
||||
Time *big.Int
|
||||
Money *big.Int
|
||||
DeadLine *big.Int
|
||||
Finished bool
|
||||
}
|
||||
|
||||
func rentsToString(rent *Rent) *RentStr {
|
||||
return &RentStr{
|
||||
Id: rent.Id,
|
||||
EstateId: rent.EstateId,
|
||||
Owner: rent.Owner.Hex(),
|
||||
Renter: rent.Renter.Hex(),
|
||||
Time: rent.Time,
|
||||
Money: rent.Money,
|
||||
DeadLine: rent.DeadLine,
|
||||
Finished: rent.Finished,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user