From 6d7cd2573dbabae0b0ac526a0da87964fae2b352 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 26 Nov 2023 22:07:56 +0100 Subject: [PATCH 01/22] Show user invoices --- db/invoice.go | 27 ++++++++++++++ db/types.go | 1 + server/router/handler/invoice.go | 15 ++++++++ server/router/router.go | 3 ++ vue/package.json | 1 + vue/src/components/UserHome.vue | 18 ++++++++++ vue/src/components/UserInvoices.vue | 56 +++++++++++++++++++++++++++++ vue/src/main.js | 9 ++++- vue/src/views/UserView.vue | 31 ++++++++-------- vue/yarn.lock | 5 +++ 10 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 vue/src/components/UserHome.vue create mode 100644 vue/src/components/UserInvoices.vue diff --git a/db/invoice.go b/db/invoice.go index 82d60db..e2c9bae 100644 --- a/db/invoice.go +++ b/db/invoice.go @@ -70,6 +70,33 @@ func (db *DB) FetchInvoices(where *FetchInvoicesWhere, invoices *[]Invoice) erro return nil } +func (db *DB) FetchUserInvoices(pubkey string, invoices *[]Invoice) error { + var ( + rows *sql.Rows + invoice Invoice + err error + ) + var ( + query = "" + + "SELECT id, pubkey, msats, preimage, hash, bolt11, created_at, expires_at, confirmed_at, held_since, COALESCE(description, ''), " + + "CASE WHEN confirmed_at IS NOT NULL THEN 'PAID' WHEN expires_at < CURRENT_TIMESTAMP THEN 'EXPIRED' ELSE 'WAITING' END AS status " + + "FROM invoices " + + "WHERE pubkey = $1 " + + "ORDER BY created_at DESC" + ) + if rows, err = db.Query(query, pubkey); err != nil { + return err + } + defer rows.Close() + for rows.Next() { + rows.Scan( + &invoice.Id, &invoice.Pubkey, &invoice.Msats, &invoice.Preimage, &invoice.Hash, + &invoice.PaymentRequest, &invoice.CreatedAt, &invoice.ExpiresAt, &invoice.ConfirmedAt, &invoice.HeldSince, &invoice.Description, &invoice.Status) + *invoices = append(*invoices, invoice) + } + return nil +} + func (db *DB) ConfirmInvoice(hash string, confirmedAt time.Time, msatsReceived int) error { if _, err := db.Exec("UPDATE invoices SET confirmed_at = $2, msats_received = $3 WHERE hash = $1", hash, confirmedAt, msatsReceived); err != nil { return err diff --git a/db/types.go b/db/types.go index e0d817e..fa8cd81 100644 --- a/db/types.go +++ b/db/types.go @@ -47,6 +47,7 @@ type ( ConfirmedAt null.Time HeldSince null.Time Description string + Status string } Order struct { Id UUID diff --git a/server/router/handler/invoice.go b/server/router/handler/invoice.go index 45e888d..f9d1073 100644 --- a/server/router/handler/invoice.go +++ b/server/router/handler/invoice.go @@ -93,3 +93,18 @@ func HandleInvoice(sc context.ServerContext) echo.HandlerFunc { return sc.Render(c, http.StatusOK, "invoice.html", data) } } + +func HandleInvoices(sc context.ServerContext) echo.HandlerFunc { + return func(c echo.Context) error { + var ( + u db.User + invoices []db.Invoice + err error + ) + u = c.Get("session").(db.User) + if err = sc.Db.FetchUserInvoices(u.Pubkey, &invoices); err != nil { + return err + } + return c.JSON(http.StatusOK, invoices) + } +} diff --git a/server/router/router.go b/server/router/router.go index 25a3b8b..bbd9569 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -57,6 +57,9 @@ func addBackendRoutes(e *echo.Echo, sc ServerContext) { GET(e, sc, "/api/invoice/:id", handler.HandleInvoiceStatus, middleware.SessionGuard) + GET(e, sc, "/api/invoices", + handler.HandleInvoices, + middleware.SessionGuard) } func GET(e *echo.Echo, sc ServerContext, path string, scF HandlerFunc, scM ...MiddlewareFunc) *echo.Route { diff --git a/vue/package.json b/vue/package.json index 43f3368..260bc1c 100644 --- a/vue/package.json +++ b/vue/package.json @@ -12,6 +12,7 @@ "core-js": "^3.8.3", "pinia": "^2.1.7", "register-service-worker": "^1.7.2", + "s-ago": "^2.2.0", "vite": "^4.5.0", "vue": "^3.2.13", "vue-router": "4" diff --git a/vue/src/components/UserHome.vue b/vue/src/components/UserHome.vue new file mode 100644 index 0000000..2fe2f69 --- /dev/null +++ b/vue/src/components/UserHome.vue @@ -0,0 +1,18 @@ + + + diff --git a/vue/src/components/UserInvoices.vue b/vue/src/components/UserInvoices.vue new file mode 100644 index 0000000..11f2d59 --- /dev/null +++ b/vue/src/components/UserInvoices.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/vue/src/main.js b/vue/src/main.js index 3fa9819..948895e 100644 --- a/vue/src/main.js +++ b/vue/src/main.js @@ -10,6 +10,8 @@ import LoginView from '@/views/LoginView' import UserView from '@/views/UserView' import MarketView from '@/views/MarketView' import InvoiceView from '@/views/InvoiceView' +import UserHome from '@/components/UserHome' +import UserInvoices from '@/components/UserInvoices' const routes = [ { @@ -19,7 +21,12 @@ const routes = [ path: '/login', component: LoginView }, { - path: '/user', component: UserView + path: '/user', + component: UserView, + children: [ + { path: '', name: 'user', component: UserHome }, + { path: 'invoices', name: 'invoices', component: UserInvoices } + ] }, { path: '/market/:id', component: MarketView diff --git a/vue/src/views/UserView.vue b/vue/src/views/UserView.vue index 73201f6..2521a67 100644 --- a/vue/src/views/UserView.vue +++ b/vue/src/views/UserView.vue @@ -9,21 +9,24 @@ \__,_|___/\___|_| -
-
authenticated as {{ session.pubkey.slice(0, 8) }}
- -
+
+ +
+ + + - +nav>a { + margin: 0 3px; +} + diff --git a/vue/yarn.lock b/vue/yarn.lock index f20a5cf..bbd5f2a 100644 --- a/vue/yarn.lock +++ b/vue/yarn.lock @@ -4012,6 +4012,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +s-ago@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/s-ago/-/s-ago-2.2.0.tgz#4143a9d0176b3100dcf649c78e8a1ec8a59b1312" + integrity sha512-t6Q/aFCCJSBf5UUkR/WH0mDHX8EGm2IBQ7nQLobVLsdxOlkryYMbOlwu2D4Cf7jPUp0v1LhfPgvIZNoi9k8lUA== + safe-array-concat@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" From 46c2a4eceba75902d4fdeab4119923d0e764ce6e Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sun, 26 Nov 2023 22:28:38 +0100 Subject: [PATCH 02/22] Add StyledLink --- vue/src/components/StyledLink.vue | 16 ++++++++++++++++ vue/src/main.js | 2 +- vue/src/views/UserView.vue | 8 ++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 vue/src/components/StyledLink.vue diff --git a/vue/src/components/StyledLink.vue b/vue/src/components/StyledLink.vue new file mode 100644 index 0000000..11831cd --- /dev/null +++ b/vue/src/components/StyledLink.vue @@ -0,0 +1,16 @@ + + + diff --git a/vue/src/main.js b/vue/src/main.js index 948895e..0417c64 100644 --- a/vue/src/main.js +++ b/vue/src/main.js @@ -24,7 +24,7 @@ const routes = [ path: '/user', component: UserView, children: [ - { path: '', name: 'user', component: UserHome }, + { path: 'settings', name: 'user', component: UserHome }, { path: 'invoices', name: 'invoices', component: UserInvoices } ] }, diff --git a/vue/src/views/UserView.vue b/vue/src/views/UserView.vue index 2521a67..d38593f 100644 --- a/vue/src/views/UserView.vue +++ b/vue/src/views/UserView.vue @@ -11,8 +11,8 @@
@@ -20,6 +20,10 @@ + + diff --git a/vue/src/main.js b/vue/src/main.js index 9c06add..ba00761 100644 --- a/vue/src/main.js +++ b/vue/src/main.js @@ -12,6 +12,7 @@ import MarketView from '@/views/MarketView' import InvoiceView from '@/views/InvoiceView' import UserSettings from '@/components/UserSettings' import UserInvoices from '@/components/UserInvoices' +import UserOrders from '@/components/UserOrders' const routes = [ { @@ -25,7 +26,8 @@ const routes = [ component: UserView, children: [ { path: 'settings', name: 'user', component: UserSettings }, - { path: 'invoices', name: 'invoices', component: UserInvoices } + { path: 'invoices', name: 'invoices', component: UserInvoices }, + { path: 'orders', name: 'orders', component: UserOrders } ] }, { diff --git a/vue/src/views/UserView.vue b/vue/src/views/UserView.vue index d38593f..204dc45 100644 --- a/vue/src/views/UserView.vue +++ b/vue/src/views/UserView.vue @@ -13,6 +13,7 @@ From 98faad9129de7e8f2497ef843b30d76be31523d8 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 27 Nov 2023 00:44:56 +0100 Subject: [PATCH 12/22] Remove console.log --- vue/src/components/UserOrders.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/vue/src/components/UserOrders.vue b/vue/src/components/UserOrders.vue index 51670fb..9e1f3ff 100644 --- a/vue/src/components/UserOrders.vue +++ b/vue/src/components/UserOrders.vue @@ -29,7 +29,6 @@ const url = '/api/orders' await fetch(url) .then(r => r.json()) .then(body => { - console.log(body) orders.value = body }) .catch(console.error) From 6b9dd419d4bf9bce04bf0c0adfe9997babeced05 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 27 Nov 2023 00:58:50 +0100 Subject: [PATCH 13/22] Fix missing title --- vue/src/components/UserOrders.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vue/src/components/UserOrders.vue b/vue/src/components/UserOrders.vue index 9e1f3ff..ccc5f01 100644 --- a/vue/src/components/UserOrders.vue +++ b/vue/src/components/UserOrders.vue @@ -11,7 +11,7 @@ {{ o.MarketId }} {{ o.side }} {{ o.quantity }} {{ o.ShareDescription }} @ {{ o.price }} sats - {{ ago(new Date(o.CreatedAt)) }} + {{ ago(new Date(o.CreatedAt)) }} From e84db076a449a62d5e980431a8e5eb86aa9ed482 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 27 Nov 2023 00:59:15 +0100 Subject: [PATCH 14/22] Use router-view for markets --- db/market.go | 20 +++++ server/router/handler/market.go | 17 ++++ server/router/router.go | 1 + vue/src/components/Market.vue | 122 ++++---------------------- vue/src/components/MarketOrders.vue | 57 ++++++++++++ vue/src/components/OrderForm.vue | 129 ++++++++++++++++++++++++++++ vue/src/index.css | 2 + vue/src/main.js | 9 +- vue/src/views/UserView.vue | 2 +- 9 files changed, 252 insertions(+), 107 deletions(-) create mode 100644 vue/src/components/MarketOrders.vue create mode 100644 vue/src/components/OrderForm.vue diff --git a/db/market.go b/db/market.go index 39db574..f1b4bed 100644 --- a/db/market.go +++ b/db/market.go @@ -132,3 +132,23 @@ func (db *DB) FetchUserOrders(pubkey string, orders *[]Order) error { } return nil } + +func (db *DB) FetchMarketOrders(marketId int64, orders *[]Order) error { + query := "" + + "SELECT o.id, share_id, o.pubkey, o.side, o.quantity, o.price, o.invoice_id, o.created_at, s.description, s.market_id " + + "FROM orders o " + + "JOIN shares s ON o.share_id = s.id " + + "WHERE s.market_id = $1 " + + "ORDER BY o.created_at DESC" + rows, err := db.Query(query, marketId) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var order Order + rows.Scan(&order.Id, &order.ShareId, &order.Pubkey, &order.Side, &order.Quantity, &order.Price, &order.InvoiceId, &order.CreatedAt, &order.ShareDescription, &order.Share.MarketId) + *orders = append(*orders, order) + } + return nil +} diff --git a/server/router/handler/market.go b/server/router/handler/market.go index e170191..8b2babc 100644 --- a/server/router/handler/market.go +++ b/server/router/handler/market.go @@ -112,6 +112,23 @@ func HandleCreateMarket(sc context.ServerContext) echo.HandlerFunc { } } +func HandleMarketOrders(sc context.ServerContext) echo.HandlerFunc { + return func(c echo.Context) error { + var ( + marketId int64 + orders []db.Order + err error + ) + if marketId, err = strconv.ParseInt(c.Param("id"), 10, 64); err != nil { + return echo.NewHTTPError(http.StatusBadRequest, "Bad Request") + } + if err = sc.Db.FetchMarketOrders(marketId, &orders); err != nil { + return err + } + return c.JSON(http.StatusOK, orders) + } +} + func HandleOrder(sc context.ServerContext) echo.HandlerFunc { return func(c echo.Context) error { var ( diff --git a/server/router/router.go b/server/router/router.go index dd86dd0..c1fb901 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -46,6 +46,7 @@ func addBackendRoutes(e *echo.Echo, sc ServerContext) { middleware.SessionGuard, middleware.LNDGuard) GET(e, sc, "/api/market/:id", handler.HandleMarket) + GET(e, sc, "/api/market/:id/orders", handler.HandleMarketOrders) POST(e, sc, "/api/order", handler.HandleOrder, middleware.SessionGuard, diff --git a/vue/src/components/Market.vue b/vue/src/components/Market.vue index 31cde0b..023ad79 100644 --- a/vue/src/components/Market.vue +++ b/vue/src/components/Market.vue @@ -10,62 +10,24 @@
{{ market.Description }}
- - -
- - - - - - - - - - - -
-
{{ err }}
+
+ +
+ + + diff --git a/vue/src/components/MarketOrders.vue b/vue/src/components/MarketOrders.vue new file mode 100644 index 0000000..07f3671 --- /dev/null +++ b/vue/src/components/MarketOrders.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/vue/src/components/OrderForm.vue b/vue/src/components/OrderForm.vue new file mode 100644 index 0000000..0da5ccc --- /dev/null +++ b/vue/src/components/OrderForm.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/vue/src/index.css b/vue/src/index.css index e6d2af9..d3d3e38 100644 --- a/vue/src/index.css +++ b/vue/src/index.css @@ -50,6 +50,7 @@ a.selected { .success:hover { background-color: #35df8d; + color: white; } .red { @@ -63,6 +64,7 @@ a.selected { .error:hover { background-color: #ff7386; + color: white; } .text-muted { diff --git a/vue/src/main.js b/vue/src/main.js index ba00761..299b429 100644 --- a/vue/src/main.js +++ b/vue/src/main.js @@ -13,6 +13,8 @@ import InvoiceView from '@/views/InvoiceView' import UserSettings from '@/components/UserSettings' import UserInvoices from '@/components/UserInvoices' import UserOrders from '@/components/UserOrders' +import OrderForm from '@/components/OrderForm' +import MarketOrders from '@/components/MarketOrders' const routes = [ { @@ -31,7 +33,12 @@ const routes = [ ] }, { - path: '/market/:id', component: MarketView + path: '/market/:id', + component: MarketView, + children: [ + { path: 'form', name: 'form', component: OrderForm }, + { path: 'orders', name: 'market-orders', component: MarketOrders } + ] }, { path: '/invoice/:id', component: InvoiceView diff --git a/vue/src/views/UserView.vue b/vue/src/views/UserView.vue index 204dc45..7a04c25 100644 --- a/vue/src/views/UserView.vue +++ b/vue/src/views/UserView.vue @@ -17,7 +17,7 @@ - + From b49cdb9b8ba9e4cbe4d6fd6d4866380c8dadb77d Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 27 Nov 2023 01:03:31 +0100 Subject: [PATCH 15/22] Use font-mono for status --- vue/src/components/MarketOrders.vue | 2 +- vue/src/components/UserInvoices.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vue/src/components/MarketOrders.vue b/vue/src/components/MarketOrders.vue index 07f3671..b0cbcff 100644 --- a/vue/src/components/MarketOrders.vue +++ b/vue/src/components/MarketOrders.vue @@ -10,7 +10,7 @@ {{ o.side }} {{ o.quantity }} {{ o.ShareDescription }} @ {{ o.price }} sats {{ ago(new Date(o.CreatedAt)) }} - PENDING + PENDING diff --git a/vue/src/components/UserInvoices.vue b/vue/src/components/UserInvoices.vue index 5b6659c..7554146 100644 --- a/vue/src/components/UserInvoices.vue +++ b/vue/src/components/UserInvoices.vue @@ -13,7 +13,7 @@ {{ i.Msats / 1000 }} {{ ago(new Date(i.CreatedAt)) }} {{ ago(new Date(i.ExpiresAt)) }} - {{ i.Status }} + {{ i.Status }} open From 798b28999c016e567a0243fd13f2a730be177cbd Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 27 Nov 2023 01:12:54 +0100 Subject: [PATCH 16/22] Create OrderRow component --- vue/src/components/MarketOrders.vue | 14 +++++++------- vue/src/components/OrderRow.vue | 22 ++++++++++++++++++++++ vue/src/components/UserOrders.vue | 9 ++------- 3 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 vue/src/components/OrderRow.vue diff --git a/vue/src/components/MarketOrders.vue b/vue/src/components/MarketOrders.vue index b0cbcff..73f2608 100644 --- a/vue/src/components/MarketOrders.vue +++ b/vue/src/components/MarketOrders.vue @@ -7,11 +7,7 @@ status - - {{ o.side }} {{ o.quantity }} {{ o.ShareDescription }} @ {{ o.price }} sats - {{ ago(new Date(o.CreatedAt)) }} - PENDING - + @@ -20,7 +16,7 @@ diff --git a/vue/src/components/OrderRow.vue b/vue/src/components/OrderRow.vue new file mode 100644 index 0000000..aae9b2d --- /dev/null +++ b/vue/src/components/OrderRow.vue @@ -0,0 +1,22 @@ + + + diff --git a/vue/src/components/UserOrders.vue b/vue/src/components/UserOrders.vue index ccc5f01..80ee0ec 100644 --- a/vue/src/components/UserOrders.vue +++ b/vue/src/components/UserOrders.vue @@ -8,12 +8,7 @@ status - - {{ o.MarketId }} - {{ o.side }} {{ o.quantity }} {{ o.ShareDescription }} @ {{ o.price }} sats - {{ ago(new Date(o.CreatedAt)) }} - - + @@ -21,7 +16,7 @@ -