Skip to content

Commit 155aa72

Browse files
authored
feat: api for submit tx (#108)
Signed-off-by: Chris Gianelloni <[email protected]>
1 parent 163a379 commit 155aa72

File tree

7 files changed

+202
-5
lines changed

7 files changed

+202
-5
lines changed

docs/docs.go

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,62 @@ const docTemplate = `{
247247
}
248248
}
249249
}
250+
},
251+
"/api/tx/submit": {
252+
"post": {
253+
"description": "Submit a signed transaction to the blockchain",
254+
"consumes": [
255+
"application/cbor"
256+
],
257+
"produces": [
258+
"application/json"
259+
],
260+
"summary": "TxSubmit",
261+
"parameters": [
262+
{
263+
"enum": [
264+
"application/cbor"
265+
],
266+
"type": "string",
267+
"description": "Content type",
268+
"name": "Content-Type",
269+
"in": "header",
270+
"required": true
271+
}
272+
],
273+
"responses": {
274+
"200": {
275+
"description": "Ok",
276+
"schema": {
277+
"type": "string"
278+
}
279+
},
280+
"400": {
281+
"description": "Bad Request",
282+
"schema": {
283+
"type": "string"
284+
}
285+
},
286+
"405": {
287+
"description": "Method Not Allowed",
288+
"schema": {
289+
"type": "string"
290+
}
291+
},
292+
"415": {
293+
"description": "Unsupported Media Type",
294+
"schema": {
295+
"type": "string"
296+
}
297+
},
298+
"500": {
299+
"description": "Server Error",
300+
"schema": {
301+
"type": "string"
302+
}
303+
}
304+
}
305+
}
250306
}
251307
},
252308
"definitions": {
@@ -363,8 +419,6 @@ var SwaggerInfo = &swag.Spec{
363419
Description: "NABU VPN indexer API",
364420
InfoInstanceName: "swagger",
365421
SwaggerTemplate: docTemplate,
366-
LeftDelim: "{{",
367-
RightDelim: "}}",
368422
}
369423

370424
func init() {

docs/swagger.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,62 @@
240240
}
241241
}
242242
}
243+
},
244+
"/api/tx/submit": {
245+
"post": {
246+
"description": "Submit a signed transaction to the blockchain",
247+
"consumes": [
248+
"application/cbor"
249+
],
250+
"produces": [
251+
"application/json"
252+
],
253+
"summary": "TxSubmit",
254+
"parameters": [
255+
{
256+
"enum": [
257+
"application/cbor"
258+
],
259+
"type": "string",
260+
"description": "Content type",
261+
"name": "Content-Type",
262+
"in": "header",
263+
"required": true
264+
}
265+
],
266+
"responses": {
267+
"200": {
268+
"description": "Ok",
269+
"schema": {
270+
"type": "string"
271+
}
272+
},
273+
"400": {
274+
"description": "Bad Request",
275+
"schema": {
276+
"type": "string"
277+
}
278+
},
279+
"405": {
280+
"description": "Method Not Allowed",
281+
"schema": {
282+
"type": "string"
283+
}
284+
},
285+
"415": {
286+
"description": "Unsupported Media Type",
287+
"schema": {
288+
"type": "string"
289+
}
290+
},
291+
"500": {
292+
"description": "Server Error",
293+
"schema": {
294+
"type": "string"
295+
}
296+
}
297+
}
298+
}
243299
}
244300
},
245301
"definitions": {

docs/swagger.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,41 @@ paths:
223223
schema:
224224
type: string
225225
summary: TxSignup
226+
/api/tx/submit:
227+
post:
228+
consumes:
229+
- application/cbor
230+
description: Submit a signed transaction to the blockchain
231+
parameters:
232+
- description: Content type
233+
enum:
234+
- application/cbor
235+
in: header
236+
name: Content-Type
237+
required: true
238+
type: string
239+
produces:
240+
- application/json
241+
responses:
242+
"200":
243+
description: Ok
244+
schema:
245+
type: string
246+
"400":
247+
description: Bad Request
248+
schema:
249+
type: string
250+
"405":
251+
description: Method Not Allowed
252+
schema:
253+
type: string
254+
"415":
255+
description: Unsupported Media Type
256+
schema:
257+
type: string
258+
"500":
259+
description: Server Error
260+
schema:
261+
type: string
262+
summary: TxSubmit
226263
swagger: "2.0"

internal/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func Start(cfg *config.Config, db *database.Database, ca *ca.Ca) error {
7676
mainMux.HandleFunc("/api/client/available", api.handleClientAvailable)
7777
mainMux.HandleFunc("/api/refdata", api.handleRefData)
7878
mainMux.HandleFunc("/api/tx/signup", api.handleTxSignup)
79+
mainMux.HandleFunc("/api/tx/submit", api.handleTxSubmit)
7980

8081
// Wrap the mainMux with a CORS middleware
8182
mainHandler := api.corsMiddleware(mainMux)

internal/api/tx.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
package api
1616

1717
import (
18+
"context"
1819
"encoding/hex"
1920
"encoding/json"
21+
"fmt"
22+
"io"
2023
"log/slog"
2124
"net/http"
2225

@@ -88,3 +91,49 @@ func (a *Api) handleTxSignup(w http.ResponseWriter, r *http.Request) {
8891
resp, _ := json.Marshal(tmpResp)
8992
_, _ = w.Write(resp)
9093
}
94+
95+
// handleTxSubmit godoc
96+
//
97+
// @Summary TxSubmit
98+
// @Description Submit a signed transaction to the blockchain
99+
// @Produce json
100+
// @Accept application/cbor
101+
// @Param Content-Type header string true "Content type" Enums(application/cbor)
102+
// @Success 200 {object} string "Ok"
103+
// @Failure 400 {object} string "Bad Request"
104+
// @Failure 405 {object} string "Method Not Allowed"
105+
// @Failure 415 {object} string "Unsupported Media Type"
106+
// @Failure 500 {object} string "Server Error"
107+
// @Router /api/tx/submit [post]
108+
func (a *Api) handleTxSubmit(w http.ResponseWriter, r *http.Request) {
109+
if r.Method != http.MethodPost {
110+
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
111+
return
112+
}
113+
114+
if r.Header.Get("Content-Type") != "application/cbor" {
115+
http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
116+
return
117+
}
118+
119+
// Read raw transaction bytes from the request body and store in a byte array
120+
txRawBytes, err := io.ReadAll(r.Body)
121+
if err != nil {
122+
http.Error(w, "Server Error", http.StatusInternalServerError)
123+
return
124+
}
125+
defer r.Body.Close() //nolint:errcheck
126+
127+
submit, err := txbuilder.OgmiosClient().SubmitTx(context.Background(), hex.EncodeToString(txRawBytes))
128+
if err != nil {
129+
http.Error(w, fmt.Sprintf("%s", err), http.StatusBadRequest)
130+
return
131+
}
132+
if submit.Error != nil {
133+
http.Error(w, submit.Error.Message, submit.Error.Code)
134+
return
135+
}
136+
w.Header().Set("Content-Type", "application/json")
137+
resp, _ := json.Marshal(submit.ID)
138+
_, _ = w.Write(resp)
139+
}

internal/txbuilder/signup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func BuildSignupTx(
9999
return nil, nil, fmt.Errorf("query latest block slot: %w", err)
100100
}
101101
// Calculate time for last known slot
102-
ogmios := ogmiosClient()
102+
ogmios := OgmiosClient()
103103
systemStart, err := ogmiosSystemStart(ogmios)
104104
if err != nil {
105105
return nil, nil, fmt.Errorf("query system start: %w", err)

internal/txbuilder/txbuilder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ var systemStart *time.Time
4444

4545
func apolloBackend() (*OgmiosChainContext.OgmiosChainContext, error) {
4646
cfg := config.GetConfig()
47-
ogmiosClient := ogmiosClient()
47+
ogmiosClient := OgmiosClient()
4848
kupoClient := kugo.New(
4949
kugo.WithEndpoint(cfg.TxBuilder.KupoUrl),
5050
kugo.WithTimeout(defaultKupoTimeout),
@@ -53,7 +53,7 @@ func apolloBackend() (*OgmiosChainContext.OgmiosChainContext, error) {
5353
return &occ, nil
5454
}
5555

56-
func ogmiosClient() *ogmigo.Client {
56+
func OgmiosClient() *ogmigo.Client {
5757
cfg := config.GetConfig()
5858
ogmiosClient := ogmigo.New(
5959
ogmigo.WithEndpoint(cfg.TxBuilder.OgmiosUrl),

0 commit comments

Comments
 (0)