Skip to content

Commit 9ac2c1b

Browse files
authored
Merge pull request #93 from fystack/fix/cosmos-txn-parser
feat: enhance Cosmos transaction parsing to handle fees and tips as ancillary transactions
2 parents 8380aaf + b41deef commit 9ac2c1b

2 files changed

Lines changed: 541 additions & 62 deletions

File tree

internal/indexer/cosmos.go

Lines changed: 113 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,15 @@ func (c *CosmosIndexer) extractTransferTransactions(
290290

291291
fee := extractCosmosFee(txResult.Events, nativeDenom)
292292
transfers := extractCosmosTransfers(txResult.Events)
293+
if ancillaryCoin, ok := extractCosmosAncillaryNativeCoin(txResult.Events, nativeDenom); ok {
294+
transfers = stripCosmosFeeTransfers(transfers, ancillaryCoin)
295+
}
296+
if feeCoin, ok := extractCosmosFeeCoin(txResult.Events, nativeDenom); ok {
297+
transfers = stripCosmosFeeTransfers(transfers, feeCoin)
298+
}
299+
if tipCoin, ok := extractCosmosTipCoin(txResult.Events, nativeDenom); ok {
300+
transfers = stripCosmosFeeTransfers(transfers, tipCoin)
301+
}
293302

294303
feeAssigned := false
295304
for transferIndex, transfer := range transfers {
@@ -330,11 +339,12 @@ func (c *CosmosIndexer) extractTransferTransactions(
330339
}
331340

332341
type cosmosTransfer struct {
333-
sender string
334-
recipient string
335-
amount string
336-
denom string
337-
source cosmosTransferSource
342+
sender string
343+
recipient string
344+
amount string
345+
denom string
346+
source cosmosTransferSource
347+
hasMsgIndex bool
338348
}
339349

340350
type cosmosTransferSource uint8
@@ -422,11 +432,12 @@ func extractCosmosBankTransfers(
422432
continue
423433
}
424434
transfers = append(transfers, cosmosTransfer{
425-
sender: senders[i],
426-
recipient: recipients[i],
427-
amount: coin.Amount,
428-
denom: coin.Denom,
429-
source: cosmosTransferSourceBank,
435+
sender: senders[i],
436+
recipient: recipients[i],
437+
amount: coin.Amount,
438+
denom: coin.Denom,
439+
source: cosmosTransferSourceBank,
440+
hasMsgIndex: len(msgIndexes) > 0,
430441
})
431442
}
432443
}
@@ -435,6 +446,28 @@ func extractCosmosBankTransfers(
435446
return transfers
436447
}
437448

449+
func stripCosmosFeeTransfers(transfers []cosmosTransfer, feeCoin cosmosCoin) []cosmosTransfer {
450+
if feeCoin.Amount == "" || feeCoin.Denom == "" {
451+
return transfers
452+
}
453+
454+
filtered := make([]cosmosTransfer, 0, len(transfers))
455+
removed := false
456+
for _, transfer := range transfers {
457+
if !removed &&
458+
transfer.source == cosmosTransferSourceBank &&
459+
!transfer.hasMsgIndex &&
460+
transfer.amount == feeCoin.Amount &&
461+
normalizeCosmosDenom(transfer.denom) == normalizeCosmosDenom(feeCoin.Denom) {
462+
removed = true
463+
continue
464+
}
465+
filtered = append(filtered, transfer)
466+
}
467+
468+
return filtered
469+
}
470+
438471
type cosmosPacketData struct {
439472
Amount string `json:"amount"`
440473
Denom string `json:"denom"`
@@ -1000,6 +1033,76 @@ func extractCosmosFee(events []cosmos.Event, nativeDenom string) decimal.Decimal
10001033
return decimal.Zero
10011034
}
10021035

1036+
func extractCosmosFeeCoin(events []cosmos.Event, nativeDenom string) (cosmosCoin, bool) {
1037+
if feeCoin, ok := extractCosmosCoinFromEvent(events, "tx", "fee", nativeDenom); ok {
1038+
return feeCoin, true
1039+
}
1040+
if feeCoin, ok := extractCosmosCoinFromEvent(events, "fee_pay", "fee", nativeDenom); ok {
1041+
return feeCoin, true
1042+
}
1043+
return cosmosCoin{}, false
1044+
}
1045+
1046+
func extractCosmosTipCoin(events []cosmos.Event, nativeDenom string) (cosmosCoin, bool) {
1047+
return extractCosmosCoinFromEvent(events, "tip_pay", "tip", nativeDenom)
1048+
}
1049+
1050+
func extractCosmosAncillaryNativeCoin(events []cosmos.Event, nativeDenom string) (cosmosCoin, bool) {
1051+
feeCoin, hasFee := extractCosmosFeeCoin(events, nativeDenom)
1052+
tipCoin, hasTip := extractCosmosTipCoin(events, nativeDenom)
1053+
1054+
switch {
1055+
case hasFee && hasTip:
1056+
if normalizeCosmosDenom(feeCoin.Denom) != normalizeCosmosDenom(tipCoin.Denom) {
1057+
return cosmosCoin{}, false
1058+
}
1059+
feeAmount, err := decimal.NewFromString(feeCoin.Amount)
1060+
if err != nil {
1061+
return cosmosCoin{}, false
1062+
}
1063+
tipAmount, err := decimal.NewFromString(tipCoin.Amount)
1064+
if err != nil {
1065+
return cosmosCoin{}, false
1066+
}
1067+
return cosmosCoin{
1068+
Amount: feeAmount.Add(tipAmount).String(),
1069+
Denom: feeCoin.Denom,
1070+
}, true
1071+
case hasFee:
1072+
return feeCoin, true
1073+
case hasTip:
1074+
return tipCoin, true
1075+
default:
1076+
return cosmosCoin{}, false
1077+
}
1078+
}
1079+
1080+
func extractCosmosCoinFromEvent(events []cosmos.Event, eventType, keyName, nativeDenom string) (cosmosCoin, bool) {
1081+
for _, event := range events {
1082+
if event.Type != eventType {
1083+
continue
1084+
}
1085+
for _, attr := range event.Attributes {
1086+
key := strings.ToLower(strings.TrimSpace(decodeCosmosEventValue(attr.Key)))
1087+
if key != keyName {
1088+
continue
1089+
}
1090+
1091+
value := strings.TrimSpace(decodeCosmosEventValue(attr.Value))
1092+
if value == "" {
1093+
continue
1094+
}
1095+
1096+
coins := parseCosmosCoins(value)
1097+
if len(coins) == 0 {
1098+
continue
1099+
}
1100+
return pickCosmosFeeCoin(coins, nativeDenom), true
1101+
}
1102+
}
1103+
return cosmosCoin{}, false
1104+
}
1105+
10031106
func extractCosmosFeeFromEvent(events []cosmos.Event, eventType, feeKey, nativeDenom string) (decimal.Decimal, bool) {
10041107
for _, event := range events {
10051108
if event.Type != eventType {

0 commit comments

Comments
 (0)