kaspad/apiserver/mqtt/transactions.go
Dan Aharoni 28ee6a8026 [NOD-381] Send transaction notifications to MQTT (#483)
* [NOD-381] Publish transaction messages to MQTT

* [NOD-381] Remove redundant variable

* [NOD-381] Send payload as string

* [NOD-381] Add Error handling

* [NOD-381] Respond with TransactionResponse

* [NOD-381] Use transactionResponse for notifications

* [NOD-381] Move code to appropriate places

* [NOD-381] Pass raw block instead of txId

* [NOD-381] Add comments to public functions

* [NOD-381] Remove print statement

* [NOD-381] Pass transaction instead of block; Use pointers so default will be nil;

* [NOD-381] Use pointers so value could be nil

* [NOD-381] Change variable name

* [NOD-381] Set QoS to 2

* [NOD-381] Move isConnected to MQTT, so client won't have to worry about it; General code refactors;
2019-11-24 10:53:09 +02:00

78 lines
1.9 KiB
Go

package mqtt
import (
"encoding/json"
"fmt"
"github.com/daglabs/btcd/apiserver/apimodels"
"github.com/daglabs/btcd/apiserver/controllers"
"github.com/daglabs/btcd/btcjson"
"github.com/jinzhu/gorm"
)
// PublishTransactionsNotifications publishes notification for each transaction of the given block
func PublishTransactionsNotifications(db *gorm.DB, rawTransactions []btcjson.TxRawResult) error {
if !isConnected() {
return nil
}
transactionIds := make([]string, len(rawTransactions))
for i, tx := range rawTransactions {
transactionIds[i] = tx.TxID
}
transactions, err := controllers.GetTransactionsByIdsHandler(db, transactionIds)
if err != nil {
return err
}
for _, transaction := range transactions {
err = publishTransactionNotifications(transaction)
if err != nil {
return err
}
}
return nil
}
func publishTransactionNotifications(transaction *apimodels.TransactionResponse) error {
addresses := uniqueAddressesForTransaction(transaction)
for _, address := range addresses {
err := publishTransactionNotificationForAddress(transaction, address)
if err != nil {
return err
}
}
return nil
}
func uniqueAddressesForTransaction(transaction *apimodels.TransactionResponse) []string {
addressesMap := make(map[string]struct{})
addresses := []string{}
for _, output := range transaction.Outputs {
if _, exists := addressesMap[output.Address]; !exists {
addresses = append(addresses, output.Address)
addressesMap[output.Address] = struct{}{}
}
}
return addresses
}
func publishTransactionNotificationForAddress(transaction *apimodels.TransactionResponse, address string) error {
payload, err := json.Marshal(transaction)
if err != nil {
return err
}
token := client.Publish(transactionsTopic(address), 2, false, payload)
token.Wait()
if token.Error() != nil {
return token.Error()
}
return nil
}
func transactionsTopic(address string) string {
return fmt.Sprintf("transactions/%s", address)
}