diff --git a/main.go b/main.go
index 928652848245ce63a37a29830c9540d467cb53fc..bf91966f1f9ad06f9bd1a968f9fbe86441515b1c 100644
--- a/main.go
+++ b/main.go
@@ -4,16 +4,21 @@ import (
 	"net/http"
 	_ "net/http/pprof"
 
+	"github.com/iotaledger/goshimmer/plugins/analysis"
+	"github.com/iotaledger/goshimmer/plugins/autopeering"
+	"github.com/iotaledger/goshimmer/plugins/cli"
 	"github.com/iotaledger/goshimmer/plugins/config"
+	"github.com/iotaledger/goshimmer/plugins/gossip"
 	"github.com/iotaledger/goshimmer/plugins/gracefulshutdown"
 	"github.com/iotaledger/goshimmer/plugins/logger"
-
+	"github.com/iotaledger/goshimmer/plugins/metrics"
+	"github.com/iotaledger/goshimmer/plugins/remotelog"
 	"github.com/iotaledger/goshimmer/plugins/tangle"
+	"github.com/iotaledger/goshimmer/plugins/webapi"
+	webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta"
+	webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer"
+	webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth"
 
-	"github.com/iotaledger/goshimmer/plugins/autopeering"
-	"github.com/iotaledger/goshimmer/plugins/cli"
-	"github.com/iotaledger/goshimmer/plugins/gossip"
-	"github.com/iotaledger/goshimmer/plugins/remotelog"
 	"github.com/iotaledger/hive.go/node"
 )
 
@@ -32,20 +37,20 @@ func main() {
 			gossip.PLUGIN,
 			gracefulshutdown.PLUGIN,
 
-			/*
-				analysis.PLUGIN,
-				metrics.PLUGIN,
+			analysis.PLUGIN,
+			metrics.PLUGIN,
+
+			webapi.PLUGIN,
+			webapi_auth.PLUGIN,
+			webapi_gtta.PLUGIN,
+			webapi_spammer.PLUGIN,
 
-				webapi.PLUGIN,
-				webapi_auth.PLUGIN,
-				webapi_gtta.PLUGIN,
-				webapi_spammer.PLUGIN,
+			/*
 				webapi_broadcastData.PLUGIN,
 				webapi_getTransactionTrytesByHash.PLUGIN,
 				webapi_getTransactionObjectsByHash.PLUGIN,
 				webapi_findTransactionHashes.PLUGIN,
 				webapi_getNeighbors.PLUGIN,
-				webapi_spammer.PLUGIN,
 
 				//spa.PLUGIN,
 				//graph.PLUGIN,
diff --git a/packages/binary/spammer/spammer.go b/packages/binary/spammer/spammer.go
new file mode 100644
index 0000000000000000000000000000000000000000..95b4bd5aa243211cab416c144f68574b983f10cf
--- /dev/null
+++ b/packages/binary/spammer/spammer.go
@@ -0,0 +1,83 @@
+package spammer
+
+import (
+	"sync"
+	"time"
+
+	"github.com/iotaledger/hive.go/types"
+
+	"github.com/iotaledger/goshimmer/packages/binary/identity"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload/data"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/tipselector"
+)
+
+type Spammer struct {
+	tangle      *tangle.Tangle
+	tipSelector *tipselector.TipSelector
+
+	running        bool
+	startStopMutex sync.Mutex
+	shutdownSignal chan types.Empty
+}
+
+func New(tangle *tangle.Tangle, tipSelector *tipselector.TipSelector) *Spammer {
+	return &Spammer{
+		tangle:      tangle,
+		tipSelector: tipSelector,
+	}
+}
+
+func (spammer *Spammer) Start(tps int) {
+	spammer.startStopMutex.Lock()
+	defer spammer.startStopMutex.Unlock()
+
+	if !spammer.running {
+		spammer.running = true
+
+		go spammer.run(tps)
+	}
+}
+
+func (spammer *Spammer) Shutdown() {
+	spammer.startStopMutex.Lock()
+	defer spammer.startStopMutex.Unlock()
+
+	if !spammer.running {
+		spammer.running = false
+
+		spammer.shutdownSignal <- types.Void
+	}
+}
+
+func (spammer *Spammer) run(tps int) {
+	currentSentCounter := 0
+	start := time.Now()
+
+	for {
+		select {
+		case <-spammer.shutdownSignal:
+			return
+
+		default:
+			trunkTransactionId, branchTransactionId := spammer.tipSelector.GetTips()
+			spammer.tangle.AttachTransaction(
+				transaction.New(trunkTransactionId, branchTransactionId, identity.Generate(), data.New([]byte("SPAM"))),
+			)
+
+			currentSentCounter++
+
+			// rate limit to the specified TPS
+			if currentSentCounter >= tps {
+				duration := time.Since(start)
+				if duration < time.Second {
+					time.Sleep(time.Second - duration)
+				}
+
+				start = time.Now()
+				currentSentCounter = 0
+			}
+		}
+	}
+}
diff --git a/packages/transactionspammer/transactionspammer.go b/packages/transactionspammer/transactionspammer.go
deleted file mode 100644
index 00493158b87578f095deb48939f49321475ded94..0000000000000000000000000000000000000000
--- a/packages/transactionspammer/transactionspammer.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package transactionspammer
-
-import (
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/iotaledger/goshimmer/packages/gossip"
-	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
-	"github.com/iotaledger/goshimmer/packages/model/value_transaction"
-	"github.com/iotaledger/goshimmer/packages/shutdown"
-	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
-	"github.com/iotaledger/goshimmer/plugins/tipselection"
-	"github.com/iotaledger/hive.go/daemon"
-	"github.com/iotaledger/hive.go/logger"
-)
-
-const logEveryNTransactions = 5000
-
-var log *logger.Logger
-
-var spamming = false
-var spammingMutex sync.Mutex
-
-var shutdownSignal chan struct{}
-var done chan struct{}
-
-func init() {
-	shutdownSignal = make(chan struct{})
-	done = make(chan struct{})
-}
-
-var targetAddress = strings.Repeat("SPAMMMMER", 9)
-
-func Start(tps uint64) {
-	log = logger.NewLogger("Transaction Spammer")
-	spammingMutex.Lock()
-	spamming = true
-	spammingMutex.Unlock()
-
-	daemon.BackgroundWorker("Transaction Spammer", func(daemonShutdownSignal <-chan struct{}) {
-		start := time.Now()
-
-		var totalSentCounter, currentSentCounter uint64
-
-		log.Infof("started spammer...will output sent count every %d transactions", logEveryNTransactions)
-		defer log.Infof("spammer stopped, spammed %d transactions", totalSentCounter)
-		for {
-			select {
-			case <-daemonShutdownSignal:
-				return
-
-			case <-shutdownSignal:
-				done <- struct{}{}
-				return
-
-			default:
-				currentSentCounter++
-				totalSentCounter++
-
-				tx := value_transaction.New()
-				tx.SetHead(true)
-				tx.SetTail(true)
-				tx.SetAddress(targetAddress)
-				tx.SetBranchTransactionHash(tipselection.GetRandomTip())
-				tx.SetTrunkTransactionHash(tipselection.GetRandomTip(tx.GetBranchTransactionHash()))
-				tx.SetTimestamp(uint(time.Now().Unix()))
-				if err := tx.DoProofOfWork(meta_transaction.MIN_WEIGHT_MAGNITUDE); err != nil {
-					log.Warn("PoW failed", err)
-					continue
-				}
-
-				gossip.Events.TransactionReceived.Trigger(&gossip.TransactionReceivedEvent{Data: tx.GetBytes(), Peer: &local.GetInstance().Peer})
-
-				if totalSentCounter%logEveryNTransactions == 0 {
-					log.Infof("spammed %d transactions", totalSentCounter)
-				}
-
-				// rate limit to the specified TPS
-				if currentSentCounter >= tps {
-					duration := time.Since(start)
-
-					if duration < time.Second {
-						time.Sleep(time.Second - duration)
-					}
-
-					start = time.Now()
-					currentSentCounter = 0
-				}
-			}
-		}
-	}, shutdown.ShutdownPriorityTangleSpammer)
-}
-
-func Stop() {
-	spammingMutex.Lock()
-	if spamming {
-		shutdownSignal <- struct{}{}
-		// wait for spammer to be done
-		<-done
-		spamming = false
-	}
-	spammingMutex.Unlock()
-}
diff --git a/plugins/tangle/tangle.go b/plugins/tangle/plugin.go
similarity index 97%
rename from plugins/tangle/tangle.go
rename to plugins/tangle/plugin.go
index 23edfe1fd03392590e9e5929308ed8b6e55395a8..533d644f3c2e52ad49b8f2c361a8f5ca6866f401 100644
--- a/plugins/tangle/tangle.go
+++ b/plugins/tangle/plugin.go
@@ -63,7 +63,7 @@ func configure(*node.Plugin) {
 }
 
 func run(*node.Plugin) {
-	daemon.BackgroundWorker("Tangle", func(shutdownSignal <-chan struct{}) {
+	_ = daemon.BackgroundWorker("Tangle", func(shutdownSignal <-chan struct{}) {
 		<-shutdownSignal
 
 		TransactionParser.Shutdown()
diff --git a/plugins/webapi/gtta/plugin.go b/plugins/webapi/gtta/plugin.go
index 54444bce56bcbb2a7df88dc54816433f5871e762..4e05e8e3c7a0de8b3e523ce948de8bfec2ab23c9 100644
--- a/plugins/webapi/gtta/plugin.go
+++ b/plugins/webapi/gtta/plugin.go
@@ -3,10 +3,10 @@ package gtta
 import (
 	"net/http"
 
-	"github.com/iotaledger/goshimmer/plugins/tipselection"
+	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
+	"github.com/iotaledger/goshimmer/plugins/tangle"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
 	"github.com/iotaledger/hive.go/node"
-	"github.com/iotaledger/iota.go/trinary"
 	"github.com/labstack/echo"
 )
 
@@ -15,17 +15,15 @@ var PLUGIN = node.NewPlugin("WebAPI GTTA Endpoint", node.Disabled, func(plugin *
 })
 
 func Handler(c echo.Context) error {
-
-	branchTransactionHash := tipselection.GetRandomTip()
-	trunkTransactionHash := tipselection.GetRandomTip(branchTransactionHash)
+	trunkTransactionId, branchTransactionId := tangle.TipSelector.GetTips()
 
 	return c.JSON(http.StatusOK, Response{
-		BranchTransaction: branchTransactionHash,
-		TrunkTransaction:  trunkTransactionHash,
+		TrunkTransaction:  trunkTransactionId,
+		BranchTransaction: branchTransactionId,
 	})
 }
 
 type Response struct {
-	BranchTransaction trinary.Trytes `json:"branchTransaction"`
-	TrunkTransaction  trinary.Trytes `json:"trunkTransaction"`
+	BranchTransaction transaction.Id `json:"branchTransaction"`
+	TrunkTransaction  transaction.Id `json:"trunkTransaction"`
 }
diff --git a/plugins/webapi/spammer/plugin.go b/plugins/webapi/spammer/plugin.go
index 7aa057fc2fc18c85982fa27ef373b1f8a3b586b6..a5d9345bdfa5f8bffcddb1c501c6dc12ae9fc19d 100644
--- a/plugins/webapi/spammer/plugin.go
+++ b/plugins/webapi/spammer/plugin.go
@@ -1,50 +1,19 @@
 package spammer
 
 import (
-	"net/http"
-
-	"github.com/iotaledger/goshimmer/packages/transactionspammer"
+	"github.com/iotaledger/goshimmer/packages/binary/spammer"
+	"github.com/iotaledger/goshimmer/plugins/tangle"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
+
 	"github.com/iotaledger/hive.go/node"
-	"github.com/labstack/echo"
 )
 
+var transactionSpammer *spammer.Spammer
+
 var PLUGIN = node.NewPlugin("Spammer", node.Disabled, configure)
 
 func configure(plugin *node.Plugin) {
-	webapi.Server.GET("spammer", WebApiHandler)
-}
-
-func WebApiHandler(c echo.Context) error {
-
-	var request Request
-	if err := c.Bind(&request); err != nil {
-		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
-	}
-
-	switch request.Cmd {
-	case "start":
-		if request.Tps == 0 {
-			request.Tps = 1
-		}
-
-		transactionspammer.Stop()
-		transactionspammer.Start(request.Tps)
-		return c.JSON(http.StatusOK, Response{Message: "started spamming transactions"})
-	case "stop":
-		transactionspammer.Stop()
-		return c.JSON(http.StatusOK, Response{Message: "stopped spamming transactions"})
-	default:
-		return c.JSON(http.StatusBadRequest, Response{Error: "invalid cmd in request"})
-	}
-}
-
-type Response struct {
-	Message string `json:"message"`
-	Error   string `json:"error"`
-}
+	transactionSpammer = spammer.New(tangle.Instance, tangle.TipSelector)
 
-type Request struct {
-	Cmd string `json:"cmd"`
-	Tps uint64 `json:"tps"`
+	webapi.Server.GET("spammer", handleRequest)
 }
diff --git a/plugins/webapi/spammer/webapi.go b/plugins/webapi/spammer/webapi.go
new file mode 100644
index 0000000000000000000000000000000000000000..f85f6e623d9723911ed5e731b64d8d0f707214fb
--- /dev/null
+++ b/plugins/webapi/spammer/webapi.go
@@ -0,0 +1,40 @@
+package spammer
+
+import (
+	"net/http"
+
+	"github.com/labstack/echo"
+)
+
+func handleRequest(c echo.Context) error {
+	var request Request
+	if err := c.Bind(&request); err != nil {
+		return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
+	}
+
+	switch request.Cmd {
+	case "start":
+		if request.Tps == 0 {
+			request.Tps = 1
+		}
+
+		transactionSpammer.Shutdown()
+		transactionSpammer.Start(request.Tps)
+		return c.JSON(http.StatusOK, Response{Message: "started spamming transactions"})
+	case "stop":
+		transactionSpammer.Shutdown()
+		return c.JSON(http.StatusOK, Response{Message: "stopped spamming transactions"})
+	default:
+		return c.JSON(http.StatusBadRequest, Response{Error: "invalid cmd in request"})
+	}
+}
+
+type Response struct {
+	Message string `json:"message"`
+	Error   string `json:"error"`
+}
+
+type Request struct {
+	Cmd string `json:"cmd"`
+	Tps int    `json:"tps"`
+}