Add order page
This commit is contained in:
parent
58901e8d7e
commit
04ce96069b
12
init.sql
12
init.sql
|
@ -23,15 +23,19 @@ CREATE EXTENSION "uuid-ossp";
|
||||||
CREATE TABLE shares(
|
CREATE TABLE shares(
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
market_id INTEGER REFERENCES markets(id),
|
market_id INTEGER REFERENCES markets(id),
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL
|
||||||
quantity BIGINT NOT NULL DEFAULT 0
|
|
||||||
);
|
);
|
||||||
CREATE TYPE order_side AS ENUM ('BUY', 'SELL');
|
CREATE TYPE order_side AS ENUM ('BUY', 'SELL');
|
||||||
CREATE TABLE trades(
|
CREATE TABLE orders(
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
share_id UUID NOT NULL REFERENCES shares(id),
|
share_id UUID NOT NULL REFERENCES shares(id),
|
||||||
pubkey TEXT NOT NULL REFERENCES users(pubkey),
|
pubkey TEXT NOT NULL REFERENCES users(pubkey),
|
||||||
side ORDER_SIDE NOT NULL,
|
side ORDER_SIDE NOT NULL,
|
||||||
quantity BIGINT NOT NULL,
|
quantity BIGINT NOT NULL,
|
||||||
msats BIGINT NOT NULL
|
price BIGINT NOT NULL
|
||||||
|
);
|
||||||
|
CREATE TABLE trades(
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
order_id_1 UUID NOT NULL REFERENCES orders(id),
|
||||||
|
order_id_2 UUID NOT NULL REFERENCES orders(id)
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>delphi.market</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||||
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
|
<link rel="stylesheet" href="/index.css" />
|
||||||
|
<link rel="stylesheet" href="/market.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#091833" />
|
||||||
|
{{ if eq .ENV "development" }}
|
||||||
|
<script defer src="/hotreload.js"></script>
|
||||||
|
{{ end }}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="flex flex-row text-center justify-center pt-1">
|
||||||
|
<nav>
|
||||||
|
<a href="/">home</a>
|
||||||
|
{{ if .session }}
|
||||||
|
<form action='/logout' method='post'>
|
||||||
|
<button type='submit'>logout</button>
|
||||||
|
</form>
|
||||||
|
{{ else }} <a href="/login">login</a> {{ end }}
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<div class="container flex flex-column text-center">
|
||||||
|
<code>
|
||||||
|
<strong>
|
||||||
|
<pre>
|
||||||
|
_ _
|
||||||
|
_ __ ___ __ _ _ __| | _____| |_
|
||||||
|
| '_ ` _ \ / _` | '__| |/ / _ \ __|
|
||||||
|
| | | | | | (_| | | | < __/ |_
|
||||||
|
|_| |_| |_|\__,_|_| |_|\_\___|\__|</pre>
|
||||||
|
</strong>
|
||||||
|
</code>
|
||||||
|
<div class="font-mono mb-1">{{.Description}}</div>
|
||||||
|
<div class="flex justify-start mb-1">
|
||||||
|
<a class="mx-1 selected" href="/market/{{.Id}}">Orders</a>
|
||||||
|
<a class="mx-1" href="/market/{{.Id}}/trade">Trade</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row justify-center mb-1">
|
||||||
|
{{ range .Shares }}
|
||||||
|
<a class="mx-1 {{ if eq $.ShareId .Id }}selected{{end}}"
|
||||||
|
href="/market/{{$.Id}}/{{.Id}}">{{.Description}}</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th class="align-left">Quantity</th>
|
||||||
|
<th class="align-right">Price</th>
|
||||||
|
<th class="align-left">Price</th>
|
||||||
|
<th class="align-right">Quantity</th>
|
||||||
|
</tr>
|
||||||
|
{{ range .OrderBook }}
|
||||||
|
<tr>
|
||||||
|
<td style="width: auto" class="align-left">{{.BuyQuantity}}</td>
|
||||||
|
<td style="width: 50%">
|
||||||
|
<div class="flex">
|
||||||
|
<span style="width: {{ sub 100 .BuyQuantity}}%"></span>
|
||||||
|
<span style="width: {{.BuyQuantity}}%" class="align-right yes">{{.BuyPrice}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td style="width: 50%">
|
||||||
|
<div class="flex">
|
||||||
|
<span style="width: {{.SellQuantity}}%" class="align-left no">{{.SellPrice}}</span>
|
||||||
|
<span style="width: {{ sub 100 .SellQuantity}}%"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td style="width: auto" class="align-right">{{.SellQuantity}}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="/order.js"></script>
|
||||||
|
|
||||||
|
</html>
|
|
@ -40,6 +40,10 @@
|
||||||
</strong>
|
</strong>
|
||||||
</code>
|
</code>
|
||||||
<div class="font-mono mb-1">{{.Description}}</div>
|
<div class="font-mono mb-1">{{.Description}}</div>
|
||||||
|
<div class="flex justify-start mb-1">
|
||||||
|
<a class="mx-1" href="/market/{{.Id}}">Orders</a>
|
||||||
|
<a class="mx-1 selected" href="/market/{{.Id}}/trade">Trade</a>
|
||||||
|
</div>
|
||||||
<div class="flex flex-row justify-center mb-1">
|
<div class="flex flex-row justify-center mb-1">
|
||||||
{{ range .Shares }} {{ if eq .Description "YES" }}
|
{{ range .Shares }} {{ if eq .Description "YES" }}
|
||||||
<button id="yes-order" class="order-button sx-1 yes">YES</button>
|
<button id="yes-order" class="order-button sx-1 yes">YES</button>
|
||||||
|
@ -57,7 +61,7 @@
|
||||||
<input id="yes-side" hidden name="side" value="BUY" />
|
<input id="yes-side" hidden name="side" value="BUY" />
|
||||||
<label>shares</label>
|
<label>shares</label>
|
||||||
<input id="yes-quantity" type="number" name="quantity" placeholder="quantity" />
|
<input id="yes-quantity" type="number" name="quantity" placeholder="quantity" />
|
||||||
<label id="yes-cost-label">cost [sats]</label>
|
<label>price [sats]</label>
|
||||||
<input id="yes-cost" type="number" name="cost" disabled />
|
<input id="yes-cost" type="number" name="cost" disabled />
|
||||||
<label id="yes-submit-label">BUY YES shares</label>
|
<label id="yes-submit-label">BUY YES shares</label>
|
||||||
<button type="submit">SUBMIT</button>
|
<button type="submit">SUBMIT</button>
|
||||||
|
@ -71,7 +75,7 @@
|
||||||
<input id="no-side" hidden name="side" value="BUY" />
|
<input id="no-side" hidden name="side" value="BUY" />
|
||||||
<label>shares</label>
|
<label>shares</label>
|
||||||
<input id="no-quantity" type="number" name="quantity" placeholder="quantity" />
|
<input id="no-quantity" type="number" name="quantity" placeholder="quantity" />
|
||||||
<label id="no-cost-label">cost [sats]</label>
|
<label>price [sats]</label>
|
||||||
<input id="no-cost" type="number" name="cost" disabled />
|
<input id="no-cost" type="number" name="cost" disabled />
|
||||||
<label id="no-submit-label">BUY NO shares</label>
|
<label id="no-submit-label">BUY NO shares</label>
|
||||||
<button type="submit">SUBMIT</button>
|
<button type="submit">SUBMIT</button>
|
||||||
|
@ -80,6 +84,6 @@
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="/bmarket.js"></script>
|
<script src="/trade.js"></script>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -20,6 +20,10 @@ a:hover {
|
||||||
background: #8787A4;
|
background: #8787A4;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
a.selected {
|
||||||
|
background: #8787A4;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
nav > a {
|
nav > a {
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +134,20 @@ ul {
|
||||||
.pt-1 {
|
.pt-1 {
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
}
|
}
|
||||||
|
.mx-1 {
|
||||||
|
margin: 0 .2em;
|
||||||
|
}
|
||||||
|
|
||||||
.word-wrap {
|
.word-wrap {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
|
@ -20,11 +20,11 @@
|
||||||
background-color: rgba(20,158,97,.24);
|
background-color: rgba(20,158,97,.24);
|
||||||
color: #35df8d;
|
color: #35df8d;
|
||||||
}
|
}
|
||||||
.yes:hover {
|
button.yes:hover {
|
||||||
background-color: #35df8d;
|
background-color: #35df8d;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.yes.selected {
|
button.yes.selected {
|
||||||
background-color: #35df8d;
|
background-color: #35df8d;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,11 @@
|
||||||
background-color: rgba(245,57,94,.24);
|
background-color: rgba(245,57,94,.24);
|
||||||
color: #ff7386;
|
color: #ff7386;
|
||||||
}
|
}
|
||||||
.no:hover {
|
button.no:hover {
|
||||||
background-color: #ff7386;
|
background-color: #ff7386;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.no.selected {
|
button.no.selected {
|
||||||
background-color: #ff7386;
|
background-color: #ff7386;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ function toggleYesForm() {
|
||||||
noForm.style.display = "none"
|
noForm.style.display = "none"
|
||||||
}
|
}
|
||||||
yesOrderBtn.onclick = toggleYesForm
|
yesOrderBtn.onclick = toggleYesForm
|
||||||
|
toggleYesForm()
|
||||||
|
|
||||||
function toggleNoForm() {
|
function toggleNoForm() {
|
||||||
resetInputs()
|
resetInputs()
|
||||||
|
@ -62,27 +63,23 @@ function showBuyForm() {
|
||||||
resetInputs()
|
resetInputs()
|
||||||
yesBuyBtn.classList.add("selected")
|
yesBuyBtn.classList.add("selected")
|
||||||
yesSellBtn.classList.remove("selected")
|
yesSellBtn.classList.remove("selected")
|
||||||
yesCostLabel.textContent = 'cost [sats]'
|
|
||||||
yesSubmitLabel.textContent = 'BUY YES shares'
|
yesSubmitLabel.textContent = 'BUY YES shares'
|
||||||
yesSideInput.value = "BUY"
|
yesSideInput.value = "BUY"
|
||||||
|
|
||||||
noBuyBtn.classList.add("selected")
|
noBuyBtn.classList.add("selected")
|
||||||
noSellBtn.classList.remove("selected")
|
noSellBtn.classList.remove("selected")
|
||||||
noCostLabel.textContent = 'cost [sats]'
|
noSubmitLabel.textContent = 'BUY NO shares'
|
||||||
noSubmitLabel.textContent = 'BUY YES shares'
|
|
||||||
noSideInput.value = "BUY"
|
noSideInput.value = "BUY"
|
||||||
}
|
}
|
||||||
function showSellForm() {
|
function showSellForm() {
|
||||||
resetInputs()
|
resetInputs()
|
||||||
yesBuyBtn.classList.remove("selected")
|
yesBuyBtn.classList.remove("selected")
|
||||||
yesSellBtn.classList.add("selected")
|
yesSellBtn.classList.add("selected")
|
||||||
yesCostLabel.textContent = 'payout [sats]'
|
|
||||||
yesSubmitLabel.textContent = 'SELL NO shares'
|
yesSubmitLabel.textContent = 'SELL NO shares'
|
||||||
yesSideInput.value = "SELL"
|
yesSideInput.value = "SELL"
|
||||||
|
|
||||||
noBuyBtn.classList.remove("selected")
|
noBuyBtn.classList.remove("selected")
|
||||||
noSellBtn.classList.add("selected")
|
noSellBtn.classList.add("selected")
|
||||||
noCostLabel.textContent = 'payout [sats]'
|
|
||||||
noSubmitLabel.textContent = 'SELL YES shares'
|
noSubmitLabel.textContent = 'SELL YES shares'
|
||||||
noSideInput.value = "SELL"
|
noSideInput.value = "SELL"
|
||||||
}
|
}
|
||||||
|
@ -130,5 +127,5 @@ function updatePrice(marketId, shareId) {
|
||||||
yesCostDisplay.value = parseFloat(Math.abs(rBody.cost)).toFixed(3)
|
yesCostDisplay.value = parseFloat(Math.abs(rBody.cost)).toFixed(3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yesQuantityInput.oninput = debounce(250)(updatePrice, marketId, yesShareId)
|
// yesQuantityInput.oninput = debounce(250)(updatePrice, marketId, yesShareId)
|
||||||
noQuantityInput.onchange = debounce(250)(updatePrice, marketId, noShareId)
|
// noQuantityInput.onchange = debounce(250)(updatePrice, marketId, noShareId)
|
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
func add(arg1 int, arg2 int) int {
|
||||||
|
return arg1 + arg2
|
||||||
|
}
|
||||||
|
|
||||||
|
func sub(arg1 int, arg2 int) int {
|
||||||
|
return arg1 - arg2
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
FuncMap template.FuncMap = template.FuncMap{
|
||||||
|
"add": add,
|
||||||
|
"sub": sub,
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,8 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
func Max(x, y int) int {
|
||||||
|
if x < y {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
113
src/router.go
113
src/router.go
|
@ -12,7 +12,6 @@ import (
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
|
@ -30,7 +29,20 @@ type Share struct {
|
||||||
Id string
|
Id string
|
||||||
MarketId int
|
MarketId int
|
||||||
Description string
|
Description string
|
||||||
Quantity int
|
}
|
||||||
|
|
||||||
|
type Order struct {
|
||||||
|
ShareId string
|
||||||
|
Side string
|
||||||
|
Price int
|
||||||
|
Quantity int
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderBookEntry struct {
|
||||||
|
BuyQuantity int
|
||||||
|
BuyPrice int
|
||||||
|
SellPrice int
|
||||||
|
SellQuantity int
|
||||||
}
|
}
|
||||||
|
|
||||||
type MarketDataRequest struct {
|
type MarketDataRequest struct {
|
||||||
|
@ -196,7 +208,7 @@ func logout(c echo.Context) error {
|
||||||
return c.Redirect(http.StatusSeeOther, "/")
|
return c.Redirect(http.StatusSeeOther, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func bmarket(c echo.Context) error {
|
func trades(c echo.Context) error {
|
||||||
marketId := c.Param("id")
|
marketId := c.Param("id")
|
||||||
var market Market
|
var market Market
|
||||||
err := db.QueryRow("SELECT id, description FROM markets WHERE id = $1 AND active = true", marketId).Scan(&market.Id, &market.Description)
|
err := db.QueryRow("SELECT id, description FROM markets WHERE id = $1 AND active = true", marketId).Scan(&market.Id, &market.Description)
|
||||||
|
@ -205,7 +217,7 @@ func bmarket(c echo.Context) error {
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rows, err := db.Query("SELECT id, market_id, description, quantity FROM shares WHERE market_id = $1 ORDER BY description DESC", marketId)
|
rows, err := db.Query("SELECT id, market_id, description FROM shares WHERE market_id = $1 ORDER BY description DESC", marketId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -213,35 +225,30 @@ func bmarket(c echo.Context) error {
|
||||||
var shares []Share
|
var shares []Share
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var share Share
|
var share Share
|
||||||
rows.Scan(&share.Id, &share.MarketId, &share.Description, &share.Quantity)
|
rows.Scan(&share.Id, &share.MarketId, &share.Description)
|
||||||
shares = append(shares, share)
|
shares = append(shares, share)
|
||||||
}
|
}
|
||||||
data := map[string]any{
|
data := map[string]any{
|
||||||
"session": c.Get("session"),
|
"session": c.Get("session"),
|
||||||
|
"ENV": ENV,
|
||||||
"Id": market.Id,
|
"Id": market.Id,
|
||||||
"Description": market.Description,
|
"Description": market.Description,
|
||||||
"Shares": shares,
|
"Shares": shares,
|
||||||
}
|
}
|
||||||
return c.Render(http.StatusOK, "bmarket.html", data)
|
return c.Render(http.StatusOK, "bmarket_trade.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func marketCost(c echo.Context) error {
|
func orders(c echo.Context) error {
|
||||||
var req MarketDataRequest
|
|
||||||
err := c.Bind(&req)
|
|
||||||
if err != nil {
|
|
||||||
c.Logger().Error(err)
|
|
||||||
return c.JSON(http.StatusBadRequest, map[string]string{"status": "ERROR", "reason": "bad request"})
|
|
||||||
}
|
|
||||||
marketId := c.Param("id")
|
marketId := c.Param("id")
|
||||||
|
shareId := c.Param("sid")
|
||||||
var market Market
|
var market Market
|
||||||
err = db.QueryRow("SELECT id, description, funding FROM markets WHERE id = $1 AND active = true", marketId).Scan(&market.Id, &market.Description, &market.Funding)
|
err := db.QueryRow("SELECT id, description FROM markets WHERE id = $1 AND active = true", marketId).Scan(&market.Id, &market.Description)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.JSON(http.StatusBadRequest, map[string]string{"status": "ERROR", "reason": "market not found"})
|
return echo.NewHTTPError(http.StatusNotFound, "Not Found")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
c.Logger().Error(err)
|
return err
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{"status": "ERROR", "reason": "internal server error"})
|
|
||||||
}
|
}
|
||||||
rows, err := db.Query("SELECT id, market_id, description, quantity FROM shares WHERE market_id = $1", marketId)
|
rows, err := db.Query("SELECT id, market_id, description FROM shares WHERE market_id = $1 ORDER BY description DESC", marketId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -249,23 +256,67 @@ func marketCost(c echo.Context) error {
|
||||||
var shares []Share
|
var shares []Share
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var share Share
|
var share Share
|
||||||
rows.Scan(&share.Id, &share.MarketId, &share.Description, &share.Quantity)
|
rows.Scan(&share.Id, &share.MarketId, &share.Description)
|
||||||
shares = append(shares, share)
|
shares = append(shares, share)
|
||||||
}
|
}
|
||||||
dq1 := req.Quantity
|
if shareId == "" {
|
||||||
// share 1 is always the share which is bought or sold
|
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/market/%s/%s", marketId, shares[0].Id))
|
||||||
share1idx := slices.IndexFunc(shares, func(s Share) bool { return s.Id == req.ShareId })
|
|
||||||
share2idx := 0
|
|
||||||
if share1idx == 0 {
|
|
||||||
share2idx = 1
|
|
||||||
}
|
}
|
||||||
q1 := shares[share1idx].Quantity
|
rows, err = db.Query(""+
|
||||||
q2 := shares[share2idx].Quantity
|
"SELECT share_id, side, price, SUM(quantity)"+
|
||||||
if req.OrderSide == "SELL" {
|
"FROM orders WHERE share_id = $1"+
|
||||||
dq1 = -dq1
|
"GROUP BY (share_id, side, price)"+
|
||||||
|
"ORDER BY share_id DESC, side DESC, price DESC", shareId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
cost := BinaryLMSR(1, market.Funding, q1, q2, dq1)
|
defer rows.Close()
|
||||||
return c.JSON(http.StatusOK, map[string]string{"status": "OK", "cost": fmt.Sprint(cost)})
|
buyOrders := []Order{}
|
||||||
|
sellOrders := []Order{}
|
||||||
|
for rows.Next() {
|
||||||
|
var order Order
|
||||||
|
rows.Scan(&order.ShareId, &order.Side, &order.Price, &order.Quantity)
|
||||||
|
if order.Side == "BUY" {
|
||||||
|
buyOrders = append(buyOrders, Order{Price: order.Price, Quantity: order.Quantity})
|
||||||
|
} else {
|
||||||
|
sellOrders = append(sellOrders, Order{Price: order.Price, Quantity: order.Quantity})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderBook := []OrderBookEntry{}
|
||||||
|
buySum := 0
|
||||||
|
sellSum := 0
|
||||||
|
for i := 0; i < Max(len(buyOrders), len(sellOrders)); i++ {
|
||||||
|
buyPrice, buyQuantity, sellQuantity, sellPrice := 0, 0, 0, 0
|
||||||
|
if i < len(buyOrders) {
|
||||||
|
buyPrice = buyOrders[i].Price
|
||||||
|
buyQuantity = buySum + buyOrders[i].Quantity
|
||||||
|
}
|
||||||
|
if i < len(sellOrders) {
|
||||||
|
sellPrice = sellOrders[i].Price
|
||||||
|
sellQuantity = sellSum + sellOrders[i].Quantity
|
||||||
|
}
|
||||||
|
buySum += buyQuantity
|
||||||
|
sellSum += sellQuantity
|
||||||
|
orderBook = append(
|
||||||
|
orderBook,
|
||||||
|
OrderBookEntry{
|
||||||
|
BuyQuantity: buyQuantity,
|
||||||
|
BuyPrice: buyPrice,
|
||||||
|
SellPrice: sellPrice,
|
||||||
|
SellQuantity: sellQuantity,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
data := map[string]any{
|
||||||
|
"session": c.Get("session"),
|
||||||
|
"ENV": ENV,
|
||||||
|
"Id": market.Id,
|
||||||
|
"Description": market.Description,
|
||||||
|
"ShareId": shareId,
|
||||||
|
"Shares": shares,
|
||||||
|
"OrderBook": orderBook,
|
||||||
|
}
|
||||||
|
return c.Render(http.StatusOK, "bmarket_order.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serve500(c echo.Context) {
|
func serve500(c echo.Context) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
e = echo.New()
|
e = echo.New()
|
||||||
t = &Template{
|
t = &Template{
|
||||||
templates: template.Must(template.ParseGlob("pages/**.html")),
|
templates: template.Must(template.New("").Funcs(FuncMap).ParseGlob("pages/**.html")),
|
||||||
}
|
}
|
||||||
COMMIT_LONG_SHA = execCmd("git", "rev-parse", "HEAD")
|
COMMIT_LONG_SHA = execCmd("git", "rev-parse", "HEAD")
|
||||||
COMMIT_SHORT_SHA = execCmd("git", "rev-parse", "--short", "HEAD")
|
COMMIT_SHORT_SHA = execCmd("git", "rev-parse", "--short", "HEAD")
|
||||||
|
@ -63,8 +63,9 @@ func main() {
|
||||||
e.GET("/api/login", verifyLogin)
|
e.GET("/api/login", verifyLogin)
|
||||||
e.GET("/api/session", checkSession)
|
e.GET("/api/session", checkSession)
|
||||||
e.POST("/logout", logout)
|
e.POST("/logout", logout)
|
||||||
e.GET("/market/:id", sessionGuard(bmarket))
|
e.GET("/market/:id", sessionGuard(orders))
|
||||||
e.POST("/api/market/:id/cost", sessionGuard(marketCost))
|
e.GET("/market/:id/:sid", sessionGuard(orders))
|
||||||
|
e.GET("/market/:id/trade", sessionGuard(trades))
|
||||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||||
Format: "${time_custom} ${method} ${uri} ${status}\n",
|
Format: "${time_custom} ${method} ${uri} ${status}\n",
|
||||||
CustomTimeFormat: "2006-01-02 15:04:05.00000-0700",
|
CustomTimeFormat: "2006-01-02 15:04:05.00000-0700",
|
||||||
|
|
Loading…
Reference in New Issue