diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9371498b..d9854273 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
 
 ### Improvements
 
+* [#79](https://github.com/babylonlabs-io/vigilante/pull/79) handle no change output when building tx
+
 * [#77](https://github.com/babylonlabs-io/vigilante/pull/77) add arm64 static build
 
 * [#76](https://github.com/babylonlabs-io/vigilante/pull/76) add goreleaser 
diff --git a/cmd/vigilante/cmd/submitter.go b/cmd/vigilante/cmd/submitter.go
index b90acd6f..a734578d 100644
--- a/cmd/vigilante/cmd/submitter.go
+++ b/cmd/vigilante/cmd/submitter.go
@@ -79,6 +79,7 @@ func GetSubmitterCmd() *cobra.Command {
 				cfg.Common.MaxRetryTimes,
 				submitterMetrics,
 				dbBackend,
+				cfg.BTC.WalletName,
 			)
 			if err != nil {
 				panic(fmt.Errorf("failed to create vigilante submitter: %w", err))
diff --git a/e2etest/monitor_e2e_test.go b/e2etest/monitor_e2e_test.go
index bd4f1cdb..844a89cb 100644
--- a/e2etest/monitor_e2e_test.go
+++ b/e2etest/monitor_e2e_test.go
@@ -63,6 +63,7 @@ func TestMonitorBootstrap(t *testing.T) {
 		tm.Config.Common.MaxRetryTimes,
 		metrics.NewSubmitterMetrics(),
 		testutil.MakeTestBackend(t),
+		tm.Config.BTC.WalletName,
 	)
 
 	vigilantSubmitter.Start()
diff --git a/e2etest/submitter_e2e_test.go b/e2etest/submitter_e2e_test.go
index 6ec647b4..81dc0242 100644
--- a/e2etest/submitter_e2e_test.go
+++ b/e2etest/submitter_e2e_test.go
@@ -68,6 +68,7 @@ func TestSubmitterSubmission(t *testing.T) {
 		tm.Config.Common.MaxRetryTimes,
 		metrics.NewSubmitterMetrics(),
 		testutil.MakeTestBackend(t),
+		tm.Config.BTC.WalletName,
 	)
 
 	vigilantSubmitter.Start()
@@ -144,6 +145,7 @@ func TestSubmitterSubmissionReplace(t *testing.T) {
 		tm.Config.Common.MaxRetryTimes,
 		metrics.NewSubmitterMetrics(),
 		testutil.MakeTestBackend(t),
+		tm.Config.BTC.WalletName,
 	)
 
 	vigilantSubmitter.Start()
diff --git a/submitter/relayer/change_address_test.go b/submitter/relayer/change_address_test.go
index fb7e772e..591a8c6d 100644
--- a/submitter/relayer/change_address_test.go
+++ b/submitter/relayer/change_address_test.go
@@ -49,7 +49,7 @@ func TestGetChangeAddress(t *testing.T) {
 	cfg := config.DefaultSubmitterConfig()
 	logger, err := config.NewRootLogger("auto", "debug")
 	require.NoError(t, err)
-	testRelayer := relayer.New(wallet, []byte("bbnt"), btctxformatter.CurrentVersion, submitterAddr,
+	testRelayer := relayer.New(wallet, btcConfig.WalletName, []byte("bbnt"), btctxformatter.CurrentVersion, submitterAddr,
 		submitterMetrics.RelayerMetrics, nil, &cfg, logger, testutil.MakeTestBackend(t))
 
 	// 1. only SegWit Bech32 addresses
diff --git a/submitter/relayer/relayer.go b/submitter/relayer/relayer.go
index 4481d45a..d6301eb5 100644
--- a/submitter/relayer/relayer.go
+++ b/submitter/relayer/relayer.go
@@ -52,10 +52,12 @@ type Relayer struct {
 	metrics                 *metrics.RelayerMetrics
 	config                  *config.SubmitterConfig
 	logger                  *zap.SugaredLogger
+	walletName              string
 }
 
 func New(
 	wallet btcclient.BTCWallet,
+	walletName string,
 	tag btctxformatter.BabylonTag,
 	version btctxformatter.FormatVersion,
 	submitterAddress sdk.AccAddress,
@@ -74,6 +76,7 @@ func New(
 	return &Relayer{
 		Estimator:               est,
 		BTCWallet:               wallet,
+		walletName:              walletName,
 		store:                   subStore,
 		tag:                     tag,
 		version:                 version,
@@ -487,7 +490,9 @@ func (rl *Relayer) ChainTwoTxAndSend(data1 []byte, data2 []byte) (*types.BtcTxIn
 func (rl *Relayer) buildTxWithData(data []byte, firstTx *wire.MsgTx) (*types.BtcTxInfo, error) {
 	tx := wire.NewMsgTx(wire.TxVersion)
 
-	if firstTx != nil {
+	isSecondTx := firstTx != nil
+
+	if isSecondTx {
 		txID := firstTx.TxHash()
 		outPoint := wire.NewOutPoint(&txID, changePosition)
 		txIn := wire.NewTxIn(outPoint, nil, nil)
@@ -514,33 +519,56 @@ func (rl *Relayer) buildTxWithData(data []byte, firstTx *wire.MsgTx) (*types.Btc
 		return nil, err
 	}
 
-	rl.logger.Debugf("Building a BTC tx using %s with data %x", rawTxResult.Transaction.TxID(), data)
+	// we want to ensure that firstTx has change output, but for the second transaction we can ignore this
+	hasChange := len(rawTxResult.Transaction.TxOut) > changePosition
+	// let's manually add a change output with 546 satoshis
+	if !isSecondTx && !hasChange {
+		changeAddr, err := rl.BTCWallet.GetRawChangeAddress(rl.walletName)
+		if err != nil {
+			return nil, fmt.Errorf("err getting raw change address %w", err)
+		}
 
-	_, addresses, _, err := txscript.ExtractPkScriptAddrs(
-		rawTxResult.Transaction.TxOut[changePosition].PkScript,
-		rl.GetNetParams(),
-	)
+		changePkScript, err := txscript.PayToAddrScript(changeAddr)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create script for change address: %s err %w", changeAddr, err)
+		}
 
-	if err != nil {
-		return nil, err
+		changeOutput := wire.NewTxOut(int64(dustThreshold), changePkScript)
+		rawTxResult.Transaction.AddTxOut(changeOutput)
 	}
 
-	if len(addresses) == 0 {
-		return nil, errors.New("no change address found")
-	}
+	rl.logger.Debugf("Building a BTC tx using %s with data %x", rawTxResult.Transaction.TxID(), data)
 
-	changeAddr := addresses[0]
-	rl.logger.Debugf("Got a change address %v", changeAddr.String())
+	if hasChange {
+		_, addresses, _, err := txscript.ExtractPkScriptAddrs(
+			rawTxResult.Transaction.TxOut[changePosition].PkScript,
+			rl.GetNetParams(),
+		)
+
+		if err != nil {
+			return nil, err
+		}
+
+		if len(addresses) == 0 {
+			return nil, errors.New("no change address found")
+		}
+
+		rl.logger.Debugf("Got a change address %v", addresses[0].String())
+	}
 
 	txSize, err := calculateTxVirtualSize(rawTxResult.Transaction)
 	if err != nil {
 		return nil, err
 	}
 
-	changeAmount := btcutil.Amount(rawTxResult.Transaction.TxOut[changePosition].Value)
+	var changeAmount btcutil.Amount
+	if hasChange {
+		changeAmount = btcutil.Amount(rawTxResult.Transaction.TxOut[changePosition].Value)
+	}
+
 	minRelayFee := rl.calcMinRelayFee(txSize)
 
-	if changeAmount < minRelayFee {
+	if hasChange && changeAmount < minRelayFee {
 		return nil, fmt.Errorf("the value of the utxo is not sufficient for relaying the tx. Require: %v. Have: %v", minRelayFee, changeAmount)
 	}
 
@@ -550,7 +578,7 @@ func (rl *Relayer) buildTxWithData(data []byte, firstTx *wire.MsgTx) (*types.Btc
 		txFee = minRelayFee
 	}
 	// ensuring the tx fee is not higher than the utxo value
-	if changeAmount < txFee {
+	if hasChange && changeAmount < txFee {
 		return nil, fmt.Errorf("the value of the utxo is not sufficient for paying the calculated fee of the tx. Calculated: %v. Have: %v", txFee, changeAmount)
 	}
 
@@ -568,7 +596,7 @@ func (rl *Relayer) buildTxWithData(data []byte, firstTx *wire.MsgTx) (*types.Btc
 
 	change := changeAmount - txFee
 
-	if change < dustThreshold {
+	if hasChange && change < dustThreshold {
 		return nil, fmt.Errorf("change amount is %v less then dust treshold %v", change, dustThreshold)
 	}
 
@@ -576,10 +604,9 @@ func (rl *Relayer) buildTxWithData(data []byte, firstTx *wire.MsgTx) (*types.Btc
 		txFee, changeAmount, txSize, hex.EncodeToString(signedTxBytes.Bytes()))
 
 	return &types.BtcTxInfo{
-		Tx:            tx,
-		ChangeAddress: changeAddr,
-		Size:          txSize,
-		Fee:           txFee,
+		Tx:   tx,
+		Size: txSize,
+		Fee:  txFee,
 	}, nil
 }
 
diff --git a/submitter/submitter.go b/submitter/submitter.go
index 86fbb7b4..d72e8fbd 100644
--- a/submitter/submitter.go
+++ b/submitter/submitter.go
@@ -45,6 +45,7 @@ func New(
 	retrySleepTime, maxRetrySleepTime time.Duration, maxRetryTimes uint,
 	submitterMetrics *metrics.SubmitterMetrics,
 	db kvdb.Backend,
+	walletName string,
 ) (*Submitter, error) {
 	logger := parentLogger.With(zap.String("module", "submitter"))
 	var (
@@ -80,6 +81,7 @@ func New(
 
 	r := relayer.New(
 		btcWallet,
+		walletName,
 		checkpointTag,
 		btctxformatter.CurrentVersion,
 		submitterAddr,
diff --git a/types/ckpt_info.go b/types/ckpt_info.go
index 5d64c6b0..0e87b890 100644
--- a/types/ckpt_info.go
+++ b/types/ckpt_info.go
@@ -18,9 +18,8 @@ type CheckpointInfo struct {
 
 // BtcTxInfo stores information of a BTC tx as part of a checkpoint
 type BtcTxInfo struct {
-	TxId          *chainhash.Hash
-	Tx            *wire.MsgTx
-	ChangeAddress btcutil.Address
-	Size          int64          // the size of the BTC tx
-	Fee           btcutil.Amount // tx fee cost by the BTC tx
+	TxId *chainhash.Hash
+	Tx   *wire.MsgTx
+	Size int64          // the size of the BTC tx
+	Fee  btcutil.Amount // tx fee cost by the BTC tx
 }