Skip to content

Commit

Permalink
decent mental model for js and basic calls working
Browse files Browse the repository at this point in the history
  • Loading branch information
ardan-bkennedy committed Mar 17, 2024
1 parent 3c5143a commit 41b88dc
Show file tree
Hide file tree
Showing 66 changed files with 11,058 additions and 2,093 deletions.
28 changes: 14 additions & 14 deletions app/services/engine/v1/handlers/gamegrp/gamegrp.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func (h *handlers) configuration(ctx context.Context, w http.ResponseWriter, r *
// usd2Wei converts the us dollar amount to wei based on the game engine's
// conversion rate.
func (h *handlers) usd2Wei(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
usd, err := strconv.ParseFloat(web.Param(ctx, "usd"), 64)
usd, err := strconv.ParseFloat(web.Param(r, "usd"), 64)
if err != nil {
return v1.NewTrustedError(fmt.Errorf("converting usd: %s", err), http.StatusBadRequest)
}
Expand Down Expand Up @@ -213,7 +213,7 @@ func (h *handlers) tables(ctx context.Context, w http.ResponseWriter, r *http.Re
func (h *handlers) state(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
claims := mid.GetClaims(ctx)

gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand Down Expand Up @@ -244,14 +244,14 @@ func (h *handlers) newGame(ctx context.Context, w http.ResponseWriter, r *http.R
return v1.NewTrustedError(fmt.Errorf("unable to add player %q to game: %w", subjectID, err), http.StatusBadRequest)
}

ctx = web.SetParam(ctx, "id", g.ID().String())
web.SetParam(r, "id", g.ID().String())

return h.state(ctx, w, r)
}

// join adds the given player to the game.
func (h *handlers) join(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand Down Expand Up @@ -287,7 +287,7 @@ func (h *handlers) join(ctx context.Context, w http.ResponseWriter, r *http.Requ

// startGame changes the status of the game so players can begin to play.
func (h *handlers) startGame(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -308,7 +308,7 @@ func (h *handlers) startGame(ctx context.Context, w http.ResponseWriter, r *http

// rollDice will roll 5 dice for the given player and game.
func (h *handlers) rollDice(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -329,7 +329,7 @@ func (h *handlers) rollDice(ctx context.Context, w http.ResponseWriter, r *http.

// bet processes a bet made by a player in a game.
func (h *handlers) bet(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -339,12 +339,12 @@ func (h *handlers) bet(ctx context.Context, w http.ResponseWriter, r *http.Reque
return v1.NewTrustedError(errors.New("no game exists"), http.StatusBadRequest)
}

number, err := strconv.Atoi(web.Param(ctx, "number"))
number, err := strconv.Atoi(web.Param(r, "number"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("converting number: %s", err), http.StatusBadRequest)
}

suit, err := strconv.Atoi(web.Param(ctx, "suit"))
suit, err := strconv.Atoi(web.Param(r, "suit"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("converting suit: %s", err), http.StatusBadRequest)
}
Expand All @@ -362,7 +362,7 @@ func (h *handlers) bet(ctx context.Context, w http.ResponseWriter, r *http.Reque

// callLiar processes the claims and defines a winner and a loser for the round.
func (h *handlers) callLiar(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -387,7 +387,7 @@ func (h *handlers) callLiar(ctx context.Context, w http.ResponseWriter, r *http.

// reconcile calls the smart contract reconcile method.
func (h *handlers) reconcile(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand Down Expand Up @@ -432,7 +432,7 @@ func (h *handlers) balance(ctx context.Context, w http.ResponseWriter, r *http.R

// nextTurn changes the account that will make the next move.
func (h *handlers) nextTurn(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -455,7 +455,7 @@ func (h *handlers) nextTurn(ctx context.Context, w http.ResponseWriter, r *http.
// part of the game flow, it is used to control when a player should be removed
// from the game.
func (h *handlers) updateOut(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
gameID, err := uuid.Parse(web.Param(ctx, "id"))
gameID, err := uuid.Parse(web.Param(r, "id"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("unable to parse game id: %w", err), http.StatusBadRequest)
}
Expand All @@ -465,7 +465,7 @@ func (h *handlers) updateOut(ctx context.Context, w http.ResponseWriter, r *http
return v1.NewTrustedError(errors.New("no game exists"), http.StatusBadRequest)
}

outs, err := strconv.Atoi(web.Param(ctx, "outs"))
outs, err := strconv.Atoi(web.Param(r, "outs"))
if err != nil {
return v1.NewTrustedError(fmt.Errorf("converting outs: %s", err), http.StatusBadRequest)
}
Expand Down
2 changes: 1 addition & 1 deletion app/services/ui/website/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class App {
}

async handlerGameTables() {
const [tables, err] = await this.engine.queryTables(this.url, this.token);
const [tables, err] = await this.engine.queryTables();
if (err != null) {
$("#error").text(err);
return;
Expand Down
8 changes: 3 additions & 5 deletions app/services/ui/website/scripts/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,12 @@ class Engine {
}
}

static async queryTables() {
async queryTables() {
try {
const tables = await $.ajax({
type: "get",
url: `${this.url}/v1/game/table`,
beforeSend: function(xhr) {
xhr.setRequestHeader ("Authorization", "Bearer " + this.token);
},
url: `${this.url}/v1/game/tables`,
headers: { "Authorization": "Bearer " + this.token }
});

return [tables, null];
Expand Down
8 changes: 4 additions & 4 deletions app/services/ui/website/scripts/init.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
const app = new App("http://0.0.0.0:3000");

window.onload = function () {
app.init();
}

const sdk = new MetaMaskSDK.MetaMaskSDK({
dappMetadata: {
name: "Pure JS example",
Expand All @@ -17,3 +13,7 @@ const sdk = new MetaMaskSDK.MetaMaskSDK({
$.ajaxSetup({
contentType: "application/json; charset=utf-8",
});

window.onload = function () {
app.init();
}
1 change: 1 addition & 0 deletions business/web/v1/mux/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func WebAPI(cfg Config, routeAdder RouteAdder, options ...func(opts *Options)) h
mid.Errors(cfg.Log),
mid.Metrics(),
mid.Panics(),
mid.Cors(opts.corsOrigin),
)

if len(opts.corsOrigin) > 0 {
Expand Down
19 changes: 6 additions & 13 deletions foundation/web/request.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
package web

import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/dimfeld/httptreemux/v5"
"github.com/go-json-experiment/json"
)

// Param returns the web call parameters from the request.
func Param(ctx context.Context, key string) string {
m := httptreemux.ContextParams(ctx)
return m[key]
func Param(r *http.Request, key string) string {
return r.PathValue(key)
}

// SetParam sets a param into the context
func SetParam(ctx context.Context, key string, value string) context.Context {
m := httptreemux.ContextParams(ctx)
m[key] = value
return httptreemux.AddParamsToContext(ctx, m)
func SetParam(r *http.Request, key string, value string) {
r.SetPathValue(key, value)
}

type validator interface {
Expand All @@ -31,9 +26,7 @@ type validator interface {
// If the provided value is a struct then it is checked for validation tags.
// If the value implements a validate function, it is executed.
func Decode(r *http.Request, val any) error {
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
if err := decoder.Decode(val); err != nil {
if err := json.UnmarshalRead(r.Body, val, json.RejectUnknownMembers(false)); err != nil {
return fmt.Errorf("unable to decode payload: %w", err)
}

Expand Down
3 changes: 2 additions & 1 deletion foundation/web/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package web

import (
"context"
"encoding/json"
"net/http"

"github.com/go-json-experiment/json"
)

// Respond converts a Go value to JSON and sends it to the client.
Expand Down
52 changes: 34 additions & 18 deletions foundation/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ package web
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"syscall"
"time"

"github.com/dimfeld/httptreemux/v5"
"github.com/google/uuid"
)

Expand All @@ -21,17 +21,27 @@ type Handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) e
// object for each of our http handlers. Feel free to add any configuration
// data/logic on this App struct.
type App struct {
*httptreemux.ContextMux
mux *http.ServeMux
shutdown chan os.Signal
mw []MidHandler
}

// NewApp creates an App value that handle a set of routes for the application.
func NewApp(shutdown chan os.Signal, mw ...MidHandler) *App {

// Create an OpenTelemetry HTTP Handler which wraps our router. This will start
// the initial span and annotate it with information about the request/trusted.
//
// This is configured to use the W3C TraceContext standard to set the remote
// parent if a client request includes the appropriate headers.
// https://w3c.github.io/trace-context/

mux := http.NewServeMux()

return &App{
ContextMux: httptreemux.NewContextMux(),
shutdown: shutdown,
mw: mw,
mux: mux,
shutdown: shutdown,
mw: mw,
}
}

Expand All @@ -41,26 +51,30 @@ func (a *App) SignalShutdown() {
a.shutdown <- syscall.SIGTERM
}

// ServeHTTP implements the http.Handler interface. It's the entry point for
// all http traffic and allows the opentelemetry mux to run first to handle
// tracing. The opentelemetry mux then calls the application mux to handle
// application traffic. This was set up on line 44 in the NewApp function.
func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
a.mux.ServeHTTP(w, r)
}

// EnableCORS enables CORS preflight requests to work in the middleware. It
// prevents the MethodNotAllowedHandler from being called. This must be enabled
// for the CORS middleware to work.
func (a *App) EnableCORS(mw MidHandler) {
a.mw = append(a.mw, mw)

handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
return Respond(ctx, w, "OK", http.StatusOK)
}
handler = wrapMiddleware(a.mw, handler)

a.ContextMux.OptionsHandler = func(w http.ResponseWriter, r *http.Request, params map[string]string) {
v := Values{
TraceID: uuid.NewString(),
Now: time.Now().UTC(),
}
ctx := setValues(r.Context(), &v)
handler = wrapMiddleware([]MidHandler{mw}, handler)

handler(ctx, w, r)
h := func(w http.ResponseWriter, r *http.Request) {
handler(r.Context(), w, r)
}

finalPath := fmt.Sprintf("%s %s", http.MethodOptions, "/")

a.mux.HandleFunc(finalPath, h)
}

// HandleNoMiddleware sets a handler function for a given HTTP method and path pair
Expand All @@ -86,8 +100,9 @@ func (a *App) HandleNoMiddleware(method string, group string, path string, handl
if group != "" {
finalPath = "/" + group + path
}
finalPath = fmt.Sprintf("%s %s", method, finalPath)

a.ContextMux.Handle(method, finalPath, h)
a.mux.HandleFunc(finalPath, h)
}

// Handle sets a handler function for a given HTTP method and path pair
Expand Down Expand Up @@ -115,8 +130,9 @@ func (a *App) Handle(method string, group string, path string, handler Handler,
if group != "" {
finalPath = "/" + group + path
}
finalPath = fmt.Sprintf("%s %s", method, finalPath)

a.ContextMux.Handle(method, finalPath, h)
a.mux.HandleFunc(finalPath, h)
}

// validateError validates the error for special conditions that do not
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ require (
github.com/ardanlabs/darwin/v3 v3.3.1
github.com/ardanlabs/ethereum v0.19.0
github.com/arl/statsviz v0.6.0
github.com/dimfeld/httptreemux/v5 v5.5.0
github.com/ethereum/go-ethereum v1.13.14
github.com/gdamore/tcell/v2 v2.7.4
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.19.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWa
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/dimfeld/httptreemux/v5 v5.5.0 h1:p8jkiMrCuZ0CmhwYLcbNbl7DDo21fozhKHQ2PccwOFQ=
github.com/dimfeld/httptreemux/v5 v5.5.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
Expand Down Expand Up @@ -119,6 +117,8 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 h1:ymLjT4f35nQbASLnvxEde4XOBL+Sn7rFuV+FOJqkljg=
github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Expand Down
25 changes: 0 additions & 25 deletions vendor/github.com/dimfeld/httptreemux/v5/.gitignore

This file was deleted.

Loading

0 comments on commit 41b88dc

Please sign in to comment.