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(
 | 
			
		||||
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
 | 
			
		||||
    market_id INTEGER REFERENCES markets(id),
 | 
			
		||||
    description TEXT NOT NULL,
 | 
			
		||||
    quantity BIGINT NOT NULL DEFAULT 0
 | 
			
		||||
    description TEXT NOT NULL
 | 
			
		||||
);
 | 
			
		||||
CREATE TYPE order_side AS ENUM ('BUY', 'SELL');
 | 
			
		||||
CREATE TABLE trades(
 | 
			
		||||
CREATE TABLE orders(
 | 
			
		||||
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
 | 
			
		||||
    share_id UUID NOT NULL REFERENCES shares(id),
 | 
			
		||||
    pubkey TEXT NOT NULL REFERENCES users(pubkey),
 | 
			
		||||
    side ORDER_SIDE 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)
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										83
									
								
								pages/bmarket_order.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								pages/bmarket_order.html
									
									
									
									
									
										Normal file
									
								
							@ -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>
 | 
			
		||||
      </code>
 | 
			
		||||
    <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">
 | 
			
		||||
      {{ range .Shares }} {{ if eq .Description "YES" }}
 | 
			
		||||
      <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" />
 | 
			
		||||
      <label>shares</label>
 | 
			
		||||
      <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 />
 | 
			
		||||
      <label id="yes-submit-label">BUY YES shares</label>
 | 
			
		||||
      <button type="submit">SUBMIT</button>
 | 
			
		||||
@ -71,7 +75,7 @@
 | 
			
		||||
      <input id="no-side" hidden name="side" value="BUY" />
 | 
			
		||||
      <label>shares</label>
 | 
			
		||||
      <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 />
 | 
			
		||||
      <label id="no-submit-label">BUY NO shares</label>
 | 
			
		||||
      <button type="submit">SUBMIT</button>
 | 
			
		||||
@ -80,6 +84,6 @@
 | 
			
		||||
    {{ end }}
 | 
			
		||||
  </div>
 | 
			
		||||
</body>
 | 
			
		||||
<script src="/bmarket.js"></script>
 | 
			
		||||
<script src="/trade.js"></script>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
@ -20,6 +20,10 @@ a:hover {
 | 
			
		||||
  background: #8787A4;
 | 
			
		||||
  color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
a.selected {
 | 
			
		||||
  background: #8787A4;
 | 
			
		||||
  color: #ffffff;
 | 
			
		||||
}
 | 
			
		||||
nav > a {
 | 
			
		||||
  margin: 0 3px;
 | 
			
		||||
}
 | 
			
		||||
@ -130,7 +134,20 @@ ul {
 | 
			
		||||
.pt-1 {
 | 
			
		||||
  padding-top: 1em;
 | 
			
		||||
}
 | 
			
		||||
.mx-1 {
 | 
			
		||||
  margin: 0 .2em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.word-wrap {
 | 
			
		||||
  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);
 | 
			
		||||
    color: #35df8d;
 | 
			
		||||
}
 | 
			
		||||
.yes:hover {
 | 
			
		||||
button.yes:hover {
 | 
			
		||||
    background-color: #35df8d;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
.yes.selected {
 | 
			
		||||
button.yes.selected {
 | 
			
		||||
    background-color: #35df8d;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
@ -33,11 +33,11 @@
 | 
			
		||||
    background-color: rgba(245,57,94,.24);
 | 
			
		||||
    color: #ff7386;
 | 
			
		||||
}
 | 
			
		||||
.no:hover {
 | 
			
		||||
button.no:hover {
 | 
			
		||||
    background-color: #ff7386;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
.no.selected {
 | 
			
		||||
button.no.selected {
 | 
			
		||||
    background-color: #ff7386;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								public/order.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								public/order.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
.align-left {
 | 
			
		||||
    text-align: left;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .align-center {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .align-right {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
  }
 | 
			
		||||
							
								
								
									
										0
									
								
								public/order.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								public/order.js
									
									
									
									
									
										Normal file
									
								
							@ -43,6 +43,7 @@ function toggleYesForm() {
 | 
			
		||||
    noForm.style.display = "none"
 | 
			
		||||
}
 | 
			
		||||
yesOrderBtn.onclick = toggleYesForm
 | 
			
		||||
toggleYesForm()
 | 
			
		||||
 | 
			
		||||
function toggleNoForm() {
 | 
			
		||||
    resetInputs()
 | 
			
		||||
@ -62,27 +63,23 @@ function showBuyForm() {
 | 
			
		||||
    resetInputs()
 | 
			
		||||
    yesBuyBtn.classList.add("selected")
 | 
			
		||||
    yesSellBtn.classList.remove("selected")
 | 
			
		||||
    yesCostLabel.textContent = 'cost [sats]'
 | 
			
		||||
    yesSubmitLabel.textContent = 'BUY YES shares'
 | 
			
		||||
    yesSideInput.value = "BUY"
 | 
			
		||||
 | 
			
		||||
    noBuyBtn.classList.add("selected")
 | 
			
		||||
    noSellBtn.classList.remove("selected")
 | 
			
		||||
    noCostLabel.textContent = 'cost [sats]'
 | 
			
		||||
    noSubmitLabel.textContent = 'BUY YES shares'
 | 
			
		||||
    noSubmitLabel.textContent = 'BUY NO shares'
 | 
			
		||||
    noSideInput.value = "BUY"
 | 
			
		||||
}
 | 
			
		||||
function showSellForm() {
 | 
			
		||||
    resetInputs()
 | 
			
		||||
    yesBuyBtn.classList.remove("selected")
 | 
			
		||||
    yesSellBtn.classList.add("selected")
 | 
			
		||||
    yesCostLabel.textContent = 'payout [sats]'
 | 
			
		||||
    yesSubmitLabel.textContent = 'SELL NO shares'
 | 
			
		||||
    yesSideInput.value = "SELL"
 | 
			
		||||
 | 
			
		||||
    noBuyBtn.classList.remove("selected")
 | 
			
		||||
    noSellBtn.classList.add("selected")
 | 
			
		||||
    noCostLabel.textContent = 'payout [sats]'
 | 
			
		||||
    noSubmitLabel.textContent = 'SELL YES shares'
 | 
			
		||||
    noSideInput.value = "SELL"
 | 
			
		||||
}
 | 
			
		||||
@ -130,5 +127,5 @@ function updatePrice(marketId, shareId) {
 | 
			
		||||
        yesCostDisplay.value = parseFloat(Math.abs(rBody.cost)).toFixed(3)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
yesQuantityInput.oninput = debounce(250)(updatePrice, marketId, yesShareId)
 | 
			
		||||
noQuantityInput.onchange = debounce(250)(updatePrice, marketId, noShareId)
 | 
			
		||||
// yesQuantityInput.oninput = debounce(250)(updatePrice, marketId, yesShareId)
 | 
			
		||||
// noQuantityInput.onchange = debounce(250)(updatePrice, marketId, noShareId)
 | 
			
		||||
							
								
								
									
										20
									
								
								src/funcs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/funcs.go
									
									
									
									
									
										Normal file
									
								
							@ -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,
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										8
									
								
								src/lib.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/lib.go
									
									
									
									
									
										Normal file
									
								
							@ -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/skip2/go-qrcode"
 | 
			
		||||
	"golang.org/x/exp/slices"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Template struct {
 | 
			
		||||
@ -30,7 +29,20 @@ type Share struct {
 | 
			
		||||
	Id          string
 | 
			
		||||
	MarketId    int
 | 
			
		||||
	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 {
 | 
			
		||||
@ -196,7 +208,7 @@ func logout(c echo.Context) error {
 | 
			
		||||
	return c.Redirect(http.StatusSeeOther, "/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bmarket(c echo.Context) error {
 | 
			
		||||
func trades(c echo.Context) error {
 | 
			
		||||
	marketId := c.Param("id")
 | 
			
		||||
	var market Market
 | 
			
		||||
	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 {
 | 
			
		||||
		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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -213,35 +225,30 @@ func bmarket(c echo.Context) error {
 | 
			
		||||
	var shares []Share
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		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)
 | 
			
		||||
	}
 | 
			
		||||
	data := map[string]any{
 | 
			
		||||
		"session":     c.Get("session"),
 | 
			
		||||
		"ENV":         ENV,
 | 
			
		||||
		"Id":          market.Id,
 | 
			
		||||
		"Description": market.Description,
 | 
			
		||||
		"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 {
 | 
			
		||||
	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"})
 | 
			
		||||
	}
 | 
			
		||||
func orders(c echo.Context) error {
 | 
			
		||||
	marketId := c.Param("id")
 | 
			
		||||
	shareId := c.Param("sid")
 | 
			
		||||
	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 {
 | 
			
		||||
		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 {
 | 
			
		||||
		c.Logger().Error(err)
 | 
			
		||||
		return c.JSON(http.StatusInternalServerError, map[string]string{"status": "ERROR", "reason": "internal server error"})
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -249,23 +256,67 @@ func marketCost(c echo.Context) error {
 | 
			
		||||
	var shares []Share
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		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)
 | 
			
		||||
	}
 | 
			
		||||
	dq1 := req.Quantity
 | 
			
		||||
	// share 1 is always the share which is bought or sold
 | 
			
		||||
	share1idx := slices.IndexFunc(shares, func(s Share) bool { return s.Id == req.ShareId })
 | 
			
		||||
	share2idx := 0
 | 
			
		||||
	if share1idx == 0 {
 | 
			
		||||
		share2idx = 1
 | 
			
		||||
	if shareId == "" {
 | 
			
		||||
		c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/market/%s/%s", marketId, shares[0].Id))
 | 
			
		||||
	}
 | 
			
		||||
	q1 := shares[share1idx].Quantity
 | 
			
		||||
	q2 := shares[share2idx].Quantity
 | 
			
		||||
	if req.OrderSide == "SELL" {
 | 
			
		||||
		dq1 = -dq1
 | 
			
		||||
	rows, err = db.Query(""+
 | 
			
		||||
		"SELECT share_id, side, price, SUM(quantity)"+
 | 
			
		||||
		"FROM orders WHERE share_id = $1"+
 | 
			
		||||
		"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)
 | 
			
		||||
	return c.JSON(http.StatusOK, map[string]string{"status": "OK", "cost": fmt.Sprint(cost)})
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
	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) {
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ func init() {
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
	e = echo.New()
 | 
			
		||||
	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_SHORT_SHA = execCmd("git", "rev-parse", "--short", "HEAD")
 | 
			
		||||
@ -63,8 +63,9 @@ func main() {
 | 
			
		||||
	e.GET("/api/login", verifyLogin)
 | 
			
		||||
	e.GET("/api/session", checkSession)
 | 
			
		||||
	e.POST("/logout", logout)
 | 
			
		||||
	e.GET("/market/:id", sessionGuard(bmarket))
 | 
			
		||||
	e.POST("/api/market/:id/cost", sessionGuard(marketCost))
 | 
			
		||||
	e.GET("/market/:id", sessionGuard(orders))
 | 
			
		||||
	e.GET("/market/:id/:sid", sessionGuard(orders))
 | 
			
		||||
	e.GET("/market/:id/trade", sessionGuard(trades))
 | 
			
		||||
	e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
 | 
			
		||||
		Format:           "${time_custom} ${method} ${uri} ${status}\n",
 | 
			
		||||
		CustomTimeFormat: "2006-01-02 15:04:05.00000-0700",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user