code.vegaprotocol.io/vega@v0.79.0/core/events/transaction_result.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package events
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"sort"
    22  
    23  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    24  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    25  )
    26  
    27  type TransactionResult struct {
    28  	*Base
    29  	evt *eventspb.TransactionResult
    30  }
    31  
    32  func (tr *TransactionResult) PartyID() string {
    33  	return tr.evt.PartyId
    34  }
    35  
    36  func (tr *TransactionResult) Status() bool {
    37  	return tr.evt.Status
    38  }
    39  
    40  func (tr *TransactionResult) Hash() string {
    41  	return tr.evt.Hash
    42  }
    43  
    44  func NewTransactionResultEventSuccess(
    45  	ctx context.Context,
    46  	hash, party string,
    47  	tx interface{},
    48  ) *TransactionResult {
    49  	evt := &TransactionResult{
    50  		Base: newBase(ctx, TransactionResultEvent),
    51  		evt: &eventspb.TransactionResult{
    52  			PartyId:      party,
    53  			Hash:         hash,
    54  			Status:       true,
    55  			StatusDetail: eventspb.TransactionResult_STATUS_SUCCESS,
    56  		},
    57  	}
    58  
    59  	return evt.setTx(tx)
    60  }
    61  
    62  type RawErrors interface {
    63  	GetRawErrors() map[string][]error
    64  }
    65  
    66  func makeFailureDetails(err error) *eventspb.TransactionResult_FailureDetails {
    67  	if rawErr, isRawErr := err.(RawErrors); isRawErr {
    68  		keyErrors := []*eventspb.TransactionResult_KeyErrors{}
    69  		for k, v := range rawErr.GetRawErrors() {
    70  			e := &eventspb.TransactionResult_KeyErrors{
    71  				Key: k,
    72  			}
    73  
    74  			for _, ve := range v {
    75  				e.Errors = append(e.Errors, ve.Error())
    76  			}
    77  
    78  			keyErrors = append(keyErrors, e)
    79  		}
    80  
    81  		sort.Slice(keyErrors, func(i, j int) bool {
    82  			return keyErrors[i].Key < keyErrors[j].Key
    83  		})
    84  
    85  		return &eventspb.TransactionResult_FailureDetails{
    86  			Errors: keyErrors,
    87  		}
    88  	}
    89  
    90  	return &eventspb.TransactionResult_FailureDetails{
    91  		Error: err.Error(),
    92  	}
    93  }
    94  
    95  type PartialError interface {
    96  	IsPartial() bool
    97  }
    98  
    99  func getErrorStatus(err error) eventspb.TransactionResult_Status {
   100  	if partialErr, isPartialErr := err.(PartialError); isPartialErr {
   101  		if partialErr.IsPartial() {
   102  			return eventspb.TransactionResult_STATUS_PARTIAL_SUCCESS
   103  		}
   104  	}
   105  
   106  	return eventspb.TransactionResult_STATUS_FAILURE
   107  }
   108  
   109  func NewTransactionResultEventFailure(
   110  	ctx context.Context,
   111  	hash, party string,
   112  	err error,
   113  	tx interface{},
   114  ) *TransactionResult {
   115  	evt := &TransactionResult{
   116  		Base: newBase(ctx, TransactionResultEvent),
   117  		evt: &eventspb.TransactionResult{
   118  			PartyId:      party,
   119  			Hash:         hash,
   120  			Status:       false,
   121  			StatusDetail: getErrorStatus(err),
   122  			Extra: &eventspb.TransactionResult_Failure{
   123  				Failure: makeFailureDetails(err),
   124  			},
   125  		},
   126  	}
   127  
   128  	return evt.setTx(tx)
   129  }
   130  
   131  func (t *TransactionResult) setTx(tx interface{}) *TransactionResult {
   132  	switch tv := tx.(type) {
   133  	case *commandspb.DelayedTransactionsWrapper:
   134  		break
   135  	case *commandspb.OrderSubmission:
   136  		t.evt.Transaction = &eventspb.TransactionResult_OrderSubmission{
   137  			OrderSubmission: tv,
   138  		}
   139  	case *commandspb.OrderCancellation:
   140  		t.evt.Transaction = &eventspb.TransactionResult_OrderCancellation{
   141  			OrderCancellation: tv,
   142  		}
   143  	case *commandspb.OrderAmendment:
   144  		t.evt.Transaction = &eventspb.TransactionResult_OrderAmendment{
   145  			OrderAmendment: tv,
   146  		}
   147  	case *commandspb.VoteSubmission:
   148  		t.evt.Transaction = &eventspb.TransactionResult_VoteSubmission{
   149  			VoteSubmission: tv,
   150  		}
   151  	case *commandspb.WithdrawSubmission:
   152  		t.evt.Transaction = &eventspb.TransactionResult_WithdrawSubmission{
   153  			WithdrawSubmission: tv,
   154  		}
   155  	case *commandspb.LiquidityProvisionSubmission:
   156  		t.evt.Transaction = &eventspb.TransactionResult_LiquidityProvisionSubmission{
   157  			LiquidityProvisionSubmission: tv,
   158  		}
   159  	case *commandspb.LiquidityProvisionCancellation:
   160  		t.evt.Transaction = &eventspb.TransactionResult_LiquidityProvisionCancellation{
   161  			LiquidityProvisionCancellation: tv,
   162  		}
   163  	case *commandspb.LiquidityProvisionAmendment:
   164  		t.evt.Transaction = &eventspb.TransactionResult_LiquidityProvisionAmendment{
   165  			LiquidityProvisionAmendment: tv,
   166  		}
   167  	case *commandspb.ProposalSubmission:
   168  		t.evt.Transaction = &eventspb.TransactionResult_Proposal{
   169  			Proposal: tv,
   170  		}
   171  	case *commandspb.DelegateSubmission:
   172  		t.evt.Transaction = &eventspb.TransactionResult_DelegateSubmission{
   173  			DelegateSubmission: tv,
   174  		}
   175  	case *commandspb.UndelegateSubmission:
   176  		t.evt.Transaction = &eventspb.TransactionResult_UndelegateSubmission{
   177  			UndelegateSubmission: tv,
   178  		}
   179  	case *commandspb.Transfer:
   180  		t.evt.Transaction = &eventspb.TransactionResult_Transfer{
   181  			Transfer: tv,
   182  		}
   183  	case *commandspb.CancelTransfer:
   184  		t.evt.Transaction = &eventspb.TransactionResult_CancelTransfer{
   185  			CancelTransfer: tv,
   186  		}
   187  	case *commandspb.AnnounceNode:
   188  		t.evt.Transaction = &eventspb.TransactionResult_AnnounceNode{
   189  			AnnounceNode: tv,
   190  		}
   191  	case *commandspb.OracleDataSubmission:
   192  		t.evt.Transaction = &eventspb.TransactionResult_OracleDataSubmission{
   193  			OracleDataSubmission: tv,
   194  		}
   195  	case *commandspb.ProtocolUpgradeProposal:
   196  		t.evt.Transaction = &eventspb.TransactionResult_ProtocolUpgradeProposal{
   197  			ProtocolUpgradeProposal: tv,
   198  		}
   199  	case *commandspb.IssueSignatures:
   200  		t.evt.Transaction = &eventspb.TransactionResult_IssueSignatures{
   201  			IssueSignatures: tv,
   202  		}
   203  	case *commandspb.BatchMarketInstructions:
   204  		t.evt.Transaction = &eventspb.TransactionResult_BatchMarketInstructions{
   205  			BatchMarketInstructions: tv,
   206  		}
   207  	case *commandspb.KeyRotateSubmission:
   208  		t.evt.Transaction = &eventspb.TransactionResult_KeyRotateSubmission{
   209  			KeyRotateSubmission: tv,
   210  		}
   211  	case *commandspb.EthereumKeyRotateSubmission:
   212  		t.evt.Transaction = &eventspb.TransactionResult_EthereumKeyRotateSubmission{
   213  			EthereumKeyRotateSubmission: tv,
   214  		}
   215  	case *commandspb.StopOrdersSubmission:
   216  		t.evt.Transaction = &eventspb.TransactionResult_StopOrdersSubmission{
   217  			StopOrdersSubmission: tv,
   218  		}
   219  	case *commandspb.StopOrdersCancellation:
   220  		t.evt.Transaction = &eventspb.TransactionResult_StopOrdersCancellation{
   221  			StopOrdersCancellation: tv,
   222  		}
   223  	case *commandspb.CreateReferralSet:
   224  		t.evt.Transaction = &eventspb.TransactionResult_CreateReferralSet{
   225  			CreateReferralSet: tv,
   226  		}
   227  	case *commandspb.UpdateReferralSet:
   228  		t.evt.Transaction = &eventspb.TransactionResult_UpdateReferralSet{
   229  			UpdateReferralSet: tv,
   230  		}
   231  	case *commandspb.ApplyReferralCode:
   232  		t.evt.Transaction = &eventspb.TransactionResult_ApplyReferralCode{
   233  			ApplyReferralCode: tv,
   234  		}
   235  	case *commandspb.UpdateMarginMode:
   236  		t.evt.Transaction = &eventspb.TransactionResult_UpdateMarginMode{
   237  			UpdateMarginMode: tv,
   238  		}
   239  	case *commandspb.JoinTeam:
   240  		t.evt.Transaction = &eventspb.TransactionResult_JoinTeam{
   241  			JoinTeam: tv,
   242  		}
   243  	case *commandspb.BatchProposalSubmission:
   244  		t.evt.Transaction = &eventspb.TransactionResult_BatchProposal{
   245  			BatchProposal: tv,
   246  		}
   247  	case *commandspb.UpdatePartyProfile:
   248  		t.evt.Transaction = &eventspb.TransactionResult_UpdatePartyProfile{
   249  			UpdatePartyProfile: tv,
   250  		}
   251  	case *commandspb.SubmitAMM:
   252  		t.evt.Transaction = &eventspb.TransactionResult_SubmitAmm{
   253  			SubmitAmm: tv,
   254  		}
   255  	case *commandspb.AmendAMM:
   256  		t.evt.Transaction = &eventspb.TransactionResult_AmendAmm{
   257  			AmendAmm: tv,
   258  		}
   259  	case *commandspb.CancelAMM:
   260  		t.evt.Transaction = &eventspb.TransactionResult_CancelAmm{
   261  			CancelAmm: tv,
   262  		}
   263  	default:
   264  		panic(fmt.Sprintf("unsupported command %T", tv))
   265  	}
   266  
   267  	return t
   268  }
   269  
   270  func (t TransactionResult) IsParty(id string) bool {
   271  	return t.evt.PartyId == id
   272  }
   273  
   274  func (t TransactionResult) Proto() eventspb.TransactionResult {
   275  	return *t.evt
   276  }
   277  
   278  func (t TransactionResult) TransactionResult() TransactionResult {
   279  	return t
   280  }
   281  
   282  func (t TransactionResult) StreamMessage() *eventspb.BusEvent {
   283  	busEvent := newBusEventFromBase(t.Base)
   284  	busEvent.Event = &eventspb.BusEvent_TransactionResult{
   285  		TransactionResult: t.evt,
   286  	}
   287  
   288  	return busEvent
   289  }
   290  
   291  func TransactionResultEventFromStream(ctx context.Context, be *eventspb.BusEvent) *TransactionResult {
   292  	return &TransactionResult{
   293  		Base: newBaseFromBusEvent(ctx, TransactionResultEvent, be),
   294  		evt:  be.GetTransactionResult(),
   295  	}
   296  }