Redirect after payment
This commit is contained in:
		
							parent
							
								
									921623ee4d
								
							
						
					
					
						commit
						e5f5759871
					
				
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @ -92,6 +92,7 @@ require ( | ||||
| 	google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c // indirect | ||||
| 	google.golang.org/grpc v1.24.0 // indirect | ||||
| 	gopkg.in/errgo.v1 v1.0.1 // indirect | ||||
| 	gopkg.in/guregu/null.v4 v4.0.0 // indirect | ||||
| 	gopkg.in/macaroon-bakery.v2 v2.0.1 // indirect | ||||
| 	gopkg.in/macaroon.v2 v2.1.0 // indirect | ||||
| 	gopkg.in/yaml.v2 v2.2.3 // indirect | ||||
|  | ||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @ -358,6 +358,8 @@ gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= | ||||
| gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= | ||||
| gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | ||||
| gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||
| gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= | ||||
| gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= | ||||
| gopkg.in/macaroon-bakery.v2 v2.0.1 h1:0N1TlEdfLP4HXNCg7MQUMp5XwvOoxk+oe9Owr2cpvsc= | ||||
| gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= | ||||
| gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
|     <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" }} | ||||
| @ -38,7 +39,13 @@ | ||||
|    |_|  \___/_____|</pre> | ||||
|         </strong> | ||||
|         </code> | ||||
|         <div class="font-mono mb-1">Payment Required</div> | ||||
|         <div class="font-mono mb-1"> | ||||
|             <div class="mb-1">Payment Required</div> | ||||
|             <div id="paid" class="yes" hidden> | ||||
|                 <div>Paid</div> | ||||
|                 <div id="countdown">Redirecting in 3 ...</div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div id="qr"> | ||||
|             <a href="lightning:{{.lnurl}}"> | ||||
|                 <img class="m-auto mb-1" src="data:image/png;base64,{{.qr}}" width="100%" /> | ||||
| @ -55,7 +62,28 @@ | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
| {{ if .RedirectAfterPayment }} | ||||
| <script> | ||||
|     const invoiceId = "{{.Invoice.Id}}" | ||||
|     const paid = document.querySelector("#paid") | ||||
|     const countdown = document.querySelector("#countdown") | ||||
|     const interval = setInterval(async () => { | ||||
|         const body = await fetch(`/api/invoice/${invoiceId}`) | ||||
|             .then((r) => r.json()) | ||||
|             .catch(console.error) | ||||
|         if (body.ConfirmedAt) { | ||||
|             paid.removeAttribute("hidden") | ||||
|             clearInterval(interval) | ||||
|             let timer = 2 | ||||
|             const redirect = setInterval(() => { | ||||
|                 countdown.textContent = `Redirecting in ${timer--} ...` | ||||
|                 if (timer === -1) { | ||||
|                     window.location.href = "https://{{.PUBLIC_URL}}/market/{{.MarketId}}"; | ||||
|                 } | ||||
|             }, 1000) | ||||
|         } | ||||
|     }, 1000) | ||||
| </script> | ||||
| {{ end }} | ||||
| 
 | ||||
| </html> | ||||
| @ -112,7 +112,7 @@ func (db *DB) CreateInvoice(invoice *Invoice) error { | ||||
| 
 | ||||
| func (db *DB) FetchInvoice(invoiceId string, invoice *Invoice) error { | ||||
| 	if err := db.QueryRow(""+ | ||||
| 		"SELECT id, pubkey, msats, preimage, hash, bolt11, created_at, expires_at FROM invoices WHERE id = $1", invoiceId).Scan(&invoice.Id, &invoice.Pubkey, &invoice.Msats, &invoice.Preimage, &invoice.PaymentHash, &invoice.PaymentRequest, &invoice.CreatedAt, &invoice.ExpiresAt); err != nil { | ||||
| 		"SELECT id, pubkey, msats, preimage, hash, bolt11, created_at, expires_at, confirmed_at, held_since FROM invoices WHERE id = $1", invoiceId).Scan(&invoice.Id, &invoice.Pubkey, &invoice.Msats, &invoice.Preimage, &invoice.PaymentHash, &invoice.PaymentRequest, &invoice.CreatedAt, &invoice.ExpiresAt, &invoice.ConfirmedAt, &invoice.HeldSince); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
|  | ||||
							
								
								
									
										16
									
								
								src/lnd.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/lnd.go
									
									
									
									
									
								
							| @ -122,3 +122,19 @@ func invoice(c echo.Context) error { | ||||
| 	} | ||||
| 	return c.Render(http.StatusOK, "invoice.html", data) | ||||
| } | ||||
| 
 | ||||
| func invoiceStatus(c echo.Context) error { | ||||
| 	invoiceId := c.Param("id") | ||||
| 	var invoice Invoice | ||||
| 	if err := db.FetchInvoice(invoiceId, &invoice); err == sql.ErrNoRows { | ||||
| 		return echo.NewHTTPError(http.StatusNotFound, "Not Found") | ||||
| 	} else if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	session := c.Get("session").(Session) | ||||
| 	if invoice.Pubkey != session.Pubkey { | ||||
| 		return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized") | ||||
| 	} | ||||
| 	invoice.Preimage = "" | ||||
| 	return c.JSON(http.StatusOK, invoice) | ||||
| } | ||||
|  | ||||
| @ -8,6 +8,7 @@ import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/labstack/echo/v4" | ||||
| 	"gopkg.in/guregu/null.v4" | ||||
| ) | ||||
| 
 | ||||
| type Market struct { | ||||
| @ -43,8 +44,8 @@ type Invoice struct { | ||||
| 	PaymentHash    string | ||||
| 	CreatedAt      time.Time | ||||
| 	ExpiresAt      time.Time | ||||
| 	ConfirmedAt    time.Time | ||||
| 	HeldSince      time.Time | ||||
| 	ConfirmedAt    null.Time | ||||
| 	HeldSince      null.Time | ||||
| } | ||||
| 
 | ||||
| func costFunction(b float64, q1 float64, q2 float64) float64 { | ||||
| @ -63,6 +64,7 @@ func BinaryLMSR(invariant int, funding int, q1 int, q2 int, dq1 int) float64 { | ||||
| } | ||||
| 
 | ||||
| func order(c echo.Context) error { | ||||
| 	marketId := c.Param("id") | ||||
| 	// (TBD) Step 0: If SELL order, check share balance of user | ||||
| 	// (TBD) Step 1: respond with HODL invoice | ||||
| 	o := new(Order) | ||||
| @ -91,6 +93,9 @@ func order(c echo.Context) error { | ||||
| 		"lnurl":                invoice.PaymentRequest, | ||||
| 		"qr":                   qr, | ||||
| 		"Invoice":              invoice, | ||||
| 		"RedirectAfterPayment": true, | ||||
| 		"PUBLIC_URL":           PUBLIC_URL, | ||||
| 		"MarketId":             marketId, | ||||
| 	} | ||||
| 	return c.Render(http.StatusPaymentRequired, "invoice.html", data) | ||||
| 	// Step 2: After payment, confirm order if no matching order was found | ||||
|  | ||||
| @ -66,6 +66,7 @@ func main() { | ||||
| 	e.GET("/market/:id", sessionGuard(market)) | ||||
| 	e.POST("/market/:id/order", sessionGuard(order)) | ||||
| 	e.GET("/invoice/:id", sessionGuard(invoice)) | ||||
| 	e.GET("/api/invoice/:id", sessionGuard(invoiceStatus)) | ||||
| 	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