add ethereum examples

This commit is contained in:
server 2020-08-06 15:15:48 -04:00
parent eb07f8a186
commit 58ab8edc6c
23 changed files with 3076 additions and 3 deletions

8
.gitignore vendored
View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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)
}

View 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
View 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>

View 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}}

View 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}}

View 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
View 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
View 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}}

View 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}}

View 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}}

View 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
View 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}}

View 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
View 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
View 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}}

View 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
View 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
View 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,
}
}