Skip to content

Commit 6e0530d

Browse files
Karthik/p23 sac event support (#5710)
* initial commit for sac event parsing * break out code for parsing SAC v3 and v4 * Add unit tests for all stellar asset contract parsing * Update horizon processors code and unit tests to read from the new horizon/internal/support/contractevents package * Initial change to separate V3 events into their own function * Rework the receiver function GetDiagnosticEvents on TransactionMeta to NOT return an error * Rework diagnostic events completely. WIll fix failing tests later * Unit tests for the new events functions * Fix unit test fixtures to account for changes in getXXXEvents functionality in horizon and processors/ * make destinationMemo public * Address code review comments
1 parent 53d703e commit 6e0530d

File tree

16 files changed

+1949
-379
lines changed

16 files changed

+1949
-379
lines changed

ingest/ledger_transaction.go

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ type LedgerTransaction struct {
3131
Hash xdr.Hash
3232
}
3333

34+
type TransactionEvents struct {
35+
TransactionEvents []xdr.TransactionEvent
36+
OperationEvents [][]xdr.ContractEvent
37+
DiagnosticEvents []xdr.DiagnosticEvent
38+
}
39+
3440
func (t *LedgerTransaction) txInternalError() bool {
3541
return t.Result.Result.Result.Code == xdr.TransactionResultCodeTxInternalError
3642
}
@@ -236,15 +242,76 @@ func (t *LedgerTransaction) operationChanges(ops operationsMeta, index uint32) [
236242
return changes
237243
}
238244

245+
func (t *LedgerTransaction) GetContractEventsForOperation(opIndex uint32) ([]xdr.ContractEvent, error) {
246+
return t.UnsafeMeta.GetContractEventsForOperation(opIndex)
247+
}
248+
249+
// GetContractEvents returns a []xdr.ContractEvent for pnly smart contract transaction.
250+
// If it is not a smart contract transaction, it throws an error
251+
// For getting events from classic operations/transaction, use GetContractEventsForOperation
252+
// For getting soroban smart contract events,we rely on the fact that there will only be one operation present in the transaction
239253
func (t *LedgerTransaction) GetContractEvents() ([]xdr.ContractEvent, error) {
240-
return t.UnsafeMeta.GetContractEvents()
254+
if !t.IsSorobanTx() {
255+
return nil, errors.New("not a soroban transaction")
256+
}
257+
return t.GetContractEventsForOperation(0)
241258
}
242259

243-
// GetDiagnosticEvents returns all contract events emitted by a given operation.
260+
// GetDiagnosticEvents returns strictly diagnostic events emitted by a given transaction.
261+
// Please note that, depending on the configuration with which txMeta may be generated,
262+
// it is possible that, for smart contract transactions, the list of generated diagnostic events MAY include contract events as well
263+
// Users of this function (horizon, rpc, etc) should be careful not to double count diagnostic events and contract events in that case
244264
func (t *LedgerTransaction) GetDiagnosticEvents() ([]xdr.DiagnosticEvent, error) {
245265
return t.UnsafeMeta.GetDiagnosticEvents()
246266
}
247267

268+
// GetTransactionEvents gives the breakdown of xdr.ContractEvent, xdr.TransactionEvent, xdr.Disgnostic event as they appea in the TxMeta
269+
// In TransactionMetaV3, for soroban transactions, contract events and diagnostic events appear in the SorobanMeta struct in TransactionMetaV3, i.e. at the transaction level
270+
// In TransactionMetaV4 and onwards, there is a more granular breakdown, because of CAP-67 unified events
271+
// - Classic operations will also have contract events.
272+
// - Contract events will now be present in the "operation []OperationMetaV2" in the TransactionMetaV4 structure, instead of at the transaction level as in TxMetaV3.
273+
// This is true for soroban transactions as well, which will only have one operation and thus contract events will appear at index 0 in the []OperationMetaV2 structure
274+
// - Additionally, if its a soroban transaction, the diagnostic events will also be included in the "DiagnosticEvents []DiagnosticEvent" structure
275+
// - Non soroban transactions will have an empty list for DiagnosticEvents
276+
//
277+
// It is preferred to use this function in horizon and rpc
278+
func (t *LedgerTransaction) GetTransactionEvents() (TransactionEvents, error) {
279+
txEvents := TransactionEvents{}
280+
switch t.UnsafeMeta.V {
281+
case 1, 2:
282+
return txEvents, nil
283+
case 3:
284+
// There wont be any events for classic operations in TxMetaV3
285+
if !t.IsSorobanTx() {
286+
return txEvents, nil
287+
}
288+
contractEvents, err := t.GetContractEvents()
289+
if err != nil {
290+
return txEvents, err
291+
}
292+
diagnosticEvents, err := t.GetDiagnosticEvents()
293+
if err != nil {
294+
return txEvents, err
295+
}
296+
// There will only ever be 1 smart contract operation per tx.
297+
txEvents.OperationEvents = make([][]xdr.ContractEvent, 1)
298+
txEvents.OperationEvents[0] = contractEvents
299+
txEvents.DiagnosticEvents = diagnosticEvents
300+
case 4:
301+
txMeta := t.UnsafeMeta.MustV4()
302+
txEvents.TransactionEvents = txMeta.Events
303+
txEvents.DiagnosticEvents = txMeta.DiagnosticEvents
304+
txEvents.OperationEvents = make([][]xdr.ContractEvent, len(txMeta.Operations))
305+
for i, op := range txMeta.Operations {
306+
txEvents.OperationEvents[i] = op.Events
307+
}
308+
default:
309+
return txEvents, fmt.Errorf("unsupported TransactionMeta version: %v", t.UnsafeMeta.V)
310+
}
311+
return txEvents, nil
312+
313+
}
314+
248315
func (t *LedgerTransaction) ID() int64 {
249316
return toid.New(int32(t.Ledger.LedgerSequence()), int32(t.Index), 0).ToInt64()
250317
}

0 commit comments

Comments
 (0)