Skip to content

Commit

Permalink
feat(SPV-848) notifications (#630)
Browse files Browse the repository at this point in the history
* feat(SPV-848): notifiactions & webhook notifier

* feat(SVP-848): notifications manager

* feat(SPV-848): notifications unit tests

* feat(SPV-848): package notification moved to engine

* feat(SPV-848): webhook_notifier tests

* feat(SPV-848): webhook manager tests

* feat(SPV-848): fix some tests

* feat(SPV-848): call with token & test for ban fcn

* feat(SPV-848): webhook subscribtion

* feat(SPV-848): fix deadlock

* feat(SPV-848): update webhook info

* feat(SPV-848): blocking select instead of with-default Sleep

* feat(SPV-848): unsubscribe

* feat(SPV-848): event type

* feat(SPV-848): event names by reflect::Name

* feat(SPV-848): tidy things

* fix(SPV-848): fix linter errors

* feat(SPV-848): fix lint errors and a unit test; and a swagger comments

* feat(SPV-848): regenerate swagger

* feat(SPV-848): fix nil ptr exception

* feat(SPV-848): fix minor unit tests

* feat(SPV-848): adjust to self-review

* feat(SPV-848): events defined in models package

* feat(SPV-848): wrong log placement

* feat(SPV-848): adjust to new ExtendedError approach

* feat(SPV-848): adjust to review

* feat(SVP-848): typo

* feat(SPV-848): update swagger

* feat(SPV-848): reimplement webhook model-repository logic

* feat(SPV-848): webhooks errors and minor changes

* feat(SPV-848): lint errors

* feat(SPV-848): update swagger

* feat(SPV-848): one empty file removed

* feat(SPV-848): adjust to minor comments

* feat(SPV-848): BanUntil

* feat(SPV-848): remove mocked notifications
  • Loading branch information
chris-4chain authored Jul 12, 2024
1 parent ac3ad4e commit 9814cfb
Show file tree
Hide file tree
Showing 38 changed files with 1,819 additions and 475 deletions.
2 changes: 2 additions & 0 deletions actions/admin/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func NewHandler(appConfig *config.AppConfig, services *config.AppServices) route
adminGroup.POST("/xpub", action.xpubsCreate)
adminGroup.POST("/xpubs/search", action.xpubsSearch)
adminGroup.POST("/xpubs/count", action.xpubsCount)
adminGroup.POST("/webhooks/subscriptions", action.subscribeWebhook)
adminGroup.DELETE("/webhooks/subscriptions", action.unsubscribeWebhook)
})

return adminEndpoints
Expand Down
61 changes: 61 additions & 0 deletions actions/admin/webhooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package admin

import (
"net/http"

"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/models"
"github.com/gin-gonic/gin"
)

// subscribeWebhook will subscribe to a webhook to receive notifications
// @Summary Subscribe to a webhook
// @Description Subscribe to a webhook to receive notifications
// @Tags Admin
// @Produce json
// @Param SubscribeRequestBody body models.SubscribeRequestBody false "URL to subscribe to and optional token header and value"
// @Success 200 {boolean} bool "Success response"
// @Failure 500 "Internal server error - Error while subscribing to the webhook"
// @Router /v1/admin/webhooks/subscriptions [post]
// @Security x-auth-xpub
func (a *Action) subscribeWebhook(c *gin.Context) {
requestBody := models.SubscribeRequestBody{}
if err := c.Bind(&requestBody); err != nil {
c.JSON(http.StatusBadRequest, err.Error())
return
}

err := a.Services.SpvWalletEngine.SubscribeWebhook(c.Request.Context(), requestBody.URL, requestBody.TokenHeader, requestBody.TokenValue)
if err != nil {
spverrors.ErrorResponse(c, err, a.Services.Logger)
return
}

c.JSON(http.StatusOK, true)
}

// unsubscribeWebhook will unsubscribe to a webhook to receive notifications
// @Summary Unsubscribe to a webhook
// @Description Unsubscribe to a webhook to stop receiving notifications
// @Tags Admin
// @Produce json
// @Param UnsubscribeRequestBody body models.UnsubscribeRequestBody false "URL to unsubscribe from"
// @Success 200 {boolean} bool "Success response"
// @Failure 500 "Internal server error - Error while unsubscribing to the webhook"
// @Router /v1/admin/webhooks/subscriptions [delete]
// @Security x-auth-xpub
func (a *Action) unsubscribeWebhook(c *gin.Context) {
requestModel := models.UnsubscribeRequestBody{}
if err := c.Bind(&requestModel); err != nil {
c.JSON(http.StatusBadRequest, err.Error())
return
}

err := a.Services.SpvWalletEngine.UnsubscribeWebhook(c.Request.Context(), requestModel.URL)
if err != nil {
spverrors.ErrorResponse(c, err, a.Services.Logger)
return
}

c.JSON(http.StatusOK, true)
}
2 changes: 0 additions & 2 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ nodes:
bytes: 1000
notifications:
enabled: false
# url to send notifications
webhook_endpoint: ""
paymail:
beef:
block_headers_service_auth_token: mQZQ6WmxURxWz5ch
Expand Down
2 changes: 0 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,6 @@ type ArcAPI struct {

// NotificationsConfig is the configuration for notifications
type NotificationsConfig struct {
// WebhookEndpoint is the endpoint for webhook registration.
WebhookEndpoint string `json:"webhook_endpoint" mapstructure:"webhook_endpoint"`
// Enabled is the flag that enables notifications service.
Enabled bool `json:"enabled" mapstructure:"enabled"`
}
Expand Down
3 changes: 1 addition & 2 deletions config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ func getNodesDefaults() *NodesConfig {

func getNotificationDefaults() *NotificationsConfig {
return &NotificationsConfig{
Enabled: false,
WebhookEndpoint: "",
Enabled: true,
}
}

Expand Down
2 changes: 1 addition & 1 deletion config/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (s *AppServices) loadSPVWallet(ctx context.Context, appConfig *AppConfig, t
options = loadTaskManager(appConfig, options)

if appConfig.Notifications != nil && appConfig.Notifications.Enabled {
options = append(options, engine.WithNotifications(appConfig.Notifications.WebhookEndpoint))
options = append(options, engine.WithNotifications())
}

options = loadBroadcastClientArc(appConfig, options, logger)
Expand Down
106 changes: 98 additions & 8 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,80 @@ const docTemplate = `{
}
}
},
"/v1/admin/webhooks/subscriptions": {
"post": {
"security": [
{
"x-auth-xpub": []
}
],
"description": "Subscribe to a webhook to receive notifications",
"produces": [
"application/json"
],
"tags": [
"Admin"
],
"summary": "Subscribe to a webhook",
"parameters": [
{
"description": "URL to subscribe to and optional token header and value",
"name": "SubscribeRequestBody",
"in": "body",
"schema": {
"$ref": "#/definitions/models.SubscribeRequestBody"
}
}
],
"responses": {
"200": {
"description": "Success response",
"schema": {
"type": "boolean"
}
},
"500": {
"description": "Internal server error - Error while subscribing to the webhook"
}
}
},
"delete": {
"security": [
{
"x-auth-xpub": []
}
],
"description": "Unsubscribe to a webhook to stop receiving notifications",
"produces": [
"application/json"
],
"tags": [
"Admin"
],
"summary": "Unsubscribe to a webhook",
"parameters": [
{
"description": "URL to unsubscribe from",
"name": "UnsubscribeRequestBody",
"in": "body",
"schema": {
"$ref": "#/definitions/models.UnsubscribeRequestBody"
}
}
],
"responses": {
"200": {
"description": "Success response",
"schema": {
"type": "boolean"
}
},
"500": {
"description": "Internal server error - Error while unsubscribing to the webhook"
}
}
}
},
"/v1/admin/xpub": {
"post": {
"security": [
Expand Down Expand Up @@ -4005,6 +4079,20 @@ const docTemplate = `{
}
}
},
"models.SubscribeRequestBody": {
"type": "object",
"properties": {
"tokenHeader": {
"type": "string"
},
"tokenValue": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"models.SyncConfig": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -4390,6 +4478,14 @@ const docTemplate = `{
}
}
},
"models.UnsubscribeRequestBody": {
"type": "object",
"properties": {
"url": {
"type": "string"
}
}
},
"models.Utxo": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -4556,14 +4652,11 @@ const docTemplate = `{
1000000000,
60000000000,
3600000000000,
-9223372036854775808,
9223372036854775807,
1,
1000,
1000000,
1000000000,
60000000000,
3600000000000
60000000000
],
"x-enum-varnames": [
"minDuration",
Expand All @@ -4574,14 +4667,11 @@ const docTemplate = `{
"Second",
"Minute",
"Hour",
"minDuration",
"maxDuration",
"Nanosecond",
"Microsecond",
"Millisecond",
"Second",
"Minute",
"Hour"
"Minute"
]
},
"transactions.NewTransaction": {
Expand Down
Loading

0 comments on commit 9814cfb

Please sign in to comment.