diff --git a/csv/parsers/accointing/accointing.go b/csv/parsers/accointing/accointing.go index 1eaf81f..103c073 100644 --- a/csv/parsers/accointing/accointing.go +++ b/csv/parsers/accointing/accointing.go @@ -251,7 +251,7 @@ func ParseTx(address string, events []db.TaxableTransaction) (rows []parsers.Csv newRow, err = ParseMsgAcknowledgement(address, event) case ibc.MsgRecvPacket: newRow, err = ParseMsgRecvPacket(address, event) - case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut: + case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut, poolmanager.MsgSplitRouteSwapExactAmountOut: newRow, err = ParsePoolManagerSwap(event) case concentratedliquidity.MsgCollectIncentives, concentratedliquidity.MsgCollectSpreadRewards: newRow, err = ParseConcentratedLiquidityCollection(event) diff --git a/csv/parsers/cointracker/cointracker.go b/csv/parsers/cointracker/cointracker.go index f55a1c6..67f7620 100644 --- a/csv/parsers/cointracker/cointracker.go +++ b/csv/parsers/cointracker/cointracker.go @@ -213,7 +213,7 @@ func ParseTx(address string, events []db.TaxableTransaction, fees []db.Fee) (row newRow, err = ParseMsgAcknowledgement(address, event) case ibc.MsgRecvPacket: newRow, err = ParseMsgRecvPacket(address, event) - case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut: + case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut, poolmanager.MsgSplitRouteSwapExactAmountOut: newRow, err = ParsePoolManagerSwap(event) case concentratedliquidity.MsgCollectIncentives, concentratedliquidity.MsgCollectSpreadRewards: newRow, err = ParseConcentratedLiquidityCollection(event) diff --git a/csv/parsers/cryptotaxcalculator/cryptotaxcalculator.go b/csv/parsers/cryptotaxcalculator/cryptotaxcalculator.go index 9e3d4ef..a14f84e 100644 --- a/csv/parsers/cryptotaxcalculator/cryptotaxcalculator.go +++ b/csv/parsers/cryptotaxcalculator/cryptotaxcalculator.go @@ -214,7 +214,7 @@ func ParseTx(address string, events []db.TaxableTransaction) (rows []parsers.Csv newRow, err = ParseMsgAcknowledgement(address, event) case ibc.MsgRecvPacket: newRow, err = ParseMsgRecvPacket(address, event) - case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut: + case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut, poolmanager.MsgSplitRouteSwapExactAmountOut: newRow, err = ParsePoolManagerSwap(address, event) case concentratedliquidity.MsgCollectIncentives, concentratedliquidity.MsgCollectSpreadRewards: newRow, err = ParseConcentratedLiquidityCollection(event) diff --git a/csv/parsers/koinly/koinly.go b/csv/parsers/koinly/koinly.go index 427052a..3b460b3 100644 --- a/csv/parsers/koinly/koinly.go +++ b/csv/parsers/koinly/koinly.go @@ -317,7 +317,7 @@ func ParseTx(address string, events []db.TaxableTransaction) (rows []parsers.Csv newRow, err = ParseMsgAcknowledgement(address, event) case ibc.MsgRecvPacket: newRow, err = ParseMsgRecvPacket(address, event) - case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut: + case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut, poolmanager.MsgSplitRouteSwapExactAmountOut: newRow, err = ParsePoolManagerSwap(event) case concentratedliquidity.MsgCollectIncentives, concentratedliquidity.MsgCollectSpreadRewards: newRow, err = ParseConcentratedLiquidityCollection(event) diff --git a/csv/parsers/taxbit/taxbit.go b/csv/parsers/taxbit/taxbit.go index 2dfbffe..e3ef1bb 100644 --- a/csv/parsers/taxbit/taxbit.go +++ b/csv/parsers/taxbit/taxbit.go @@ -246,7 +246,7 @@ func ParseTx(address string, events []db.TaxableTransaction) (rows []parsers.Csv newRow, err = ParseMsgTransfer(address, event) case ibc.MsgRecvPacket: newRow, err = ParseMsgTransfer(address, event) - case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut: + case poolmanager.MsgSplitRouteSwapExactAmountIn, poolmanager.MsgSwapExactAmountIn, poolmanager.MsgSwapExactAmountOut, poolmanager.MsgSplitRouteSwapExactAmountOut: newRow, err = ParsePoolManagerSwap(event) case valsetpref.MsgDelegateBondedTokens, valsetpref.MsgUndelegateFromValidatorSet, valsetpref.MsgRedelegateValidatorSet, valsetpref.MsgWithdrawDelegationRewards, valsetpref.MsgDelegateToValidatorSet, valsetpref.MsgUndelegateFromRebalancedValidatorSet: newRow, err = ParseValsetPrefRewards(event) diff --git a/osmosis/handlers.go b/osmosis/handlers.go index 239611d..8b927cd 100644 --- a/osmosis/handlers.go +++ b/osmosis/handlers.go @@ -12,7 +12,7 @@ import ( // MessageTypeHandler is used to unmarshal JSON to a particular type. var MessageTypeHandler = map[string][]func() txTypes.CosmosMessage{ - gamm.MsgSwapExactAmountIn: {func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn2{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn3{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn4{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn5{} }}, + gamm.MsgSwapExactAmountIn: {func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn2{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn3{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn4{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn5{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountIn6{} }}, gamm.MsgSwapExactAmountOut: {func() txTypes.CosmosMessage { return &gamm.WrapperMsgSwapExactAmountOut{} }}, gamm.MsgJoinSwapExternAmountIn: {func() txTypes.CosmosMessage { return &gamm.WrapperMsgJoinSwapExternAmountIn{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgJoinSwapExternAmountIn2{} }}, gamm.MsgJoinSwapShareAmountOut: {func() txTypes.CosmosMessage { return &gamm.WrapperMsgJoinSwapShareAmountOut{} }, func() txTypes.CosmosMessage { return &gamm.WrapperMsgJoinSwapShareAmountOut2{} }}, @@ -27,6 +27,7 @@ var MessageTypeHandler = map[string][]func() txTypes.CosmosMessage{ poolmanager.MsgSwapExactAmountIn: {func() txTypes.CosmosMessage { return &poolmanager.WrapperMsgSwapExactAmountIn{} }}, poolmanager.MsgSwapExactAmountOut: {func() txTypes.CosmosMessage { return &poolmanager.WrapperMsgSwapExactAmountOut{} }}, poolmanager.MsgSplitRouteSwapExactAmountIn: {func() txTypes.CosmosMessage { return &poolmanager.WrapperMsgSplitRouteSwapExactAmountIn{} }}, + poolmanager.MsgSplitRouteSwapExactAmountOut: {func() txTypes.CosmosMessage { return &poolmanager.WrapperMsgSplitRouteSwapExactAmountOut{} }}, concentratedliquidity.MsgCreatePosition: {func() txTypes.CosmosMessage { return &concentratedliquidity.WrapperMsgCreatePosition{} }}, concentratedliquidity.MsgWithdrawPosition: {func() txTypes.CosmosMessage { return &concentratedliquidity.WrapperMsgWithdrawPosition{} }}, concentratedliquidity.MsgCollectSpreadRewards: {func() txTypes.CosmosMessage { return &concentratedliquidity.WrapperMsgCollectSpreadRewards{} }}, diff --git a/osmosis/modules/gamm/swaps.go b/osmosis/modules/gamm/swaps.go index f237e2b..7566205 100644 --- a/osmosis/modules/gamm/swaps.go +++ b/osmosis/modules/gamm/swaps.go @@ -48,6 +48,10 @@ type WrapperMsgSwapExactAmountIn5 struct { WrapperMsgSwapExactAmountIn } +type WrapperMsgSwapExactAmountIn6 struct { + WrapperMsgSwapExactAmountIn +} + type WrapperMsgSwapExactAmountOut struct { txModule.Message OsmosisMsgSwapExactAmountOut *gammTypes.MsgSwapExactAmountOut @@ -86,6 +90,10 @@ func (sf *WrapperMsgSwapExactAmountIn5) String() string { return sf.WrapperMsgSwapExactAmountIn.String() } +func (sf *WrapperMsgSwapExactAmountIn6) String() string { + return sf.WrapperMsgSwapExactAmountIn.String() +} + func (sf *WrapperMsgSwapExactAmountOut) String() string { var tokenSwappedOut string var tokenSwappedIn string @@ -491,6 +499,52 @@ func (sf *WrapperMsgSwapExactAmountOut) HandleMsg(msgType string, msg sdk.Msg, l return nil } +func (sf *WrapperMsgSwapExactAmountIn6) HandleMsg(msgType string, msg sdk.Msg, log *txModule.LogMessage) error { + sf.Type = msgType + sf.OsmosisMsgSwapExactAmountIn = msg.(*gammTypes.MsgSwapExactAmountIn) + + // Confirm that the action listed in the message log matches the Message type + validLog := txModule.IsMessageActionEquals(sf.GetType(), log) + if !validLog { + return util.ReturnInvalidLog(msgType, log) + } + + // get all transfer events + transferEvents := txModule.GetEventsWithType("transfer", log) + + // loop backwards through transfer events + for i := len(transferEvents) - 1; i >= 0; i-- { + transferEvt := transferEvents[i] + + for _, attr := range transferEvt.Attributes { + if attr.Key == "amount" && attr.Value != "" { + amount, err := sdk.ParseCoinNormalized(attr.Value) + if err != nil { + return err + } + + // if the amount denom matches the last route denom, then it is the amount received + if amount.Denom == sf.OsmosisMsgSwapExactAmountIn.Routes[len(sf.OsmosisMsgSwapExactAmountIn.Routes)-1].TokenOutDenom { + sf.TokenOut = amount + break + } + } + } + + if !sf.TokenOut.IsNil() { + break + } + } + + if sf.TokenOut.IsNil() { + return errors.New("no amount received") + } + + sf.TokenIn = sf.OsmosisMsgSwapExactAmountIn.TokenIn + sf.Address = sf.OsmosisMsgSwapExactAmountIn.Sender + return nil +} + func (sf *WrapperMsgSwapExactAmountIn) ParseRelevantData() []parsingTypes.MessageRelevantInformation { relevantData := make([]parsingTypes.MessageRelevantInformation, 1) relevantData[0] = parsingTypes.MessageRelevantInformation{ @@ -520,3 +574,7 @@ func (sf *WrapperMsgSwapExactAmountOut) ParseRelevantData() []parsingTypes.Messa } return relevantData } + +func (sf *WrapperMsgSwapExactAmountIn6) ParseRelevantData() []parsingTypes.MessageRelevantInformation { + return sf.WrapperMsgSwapExactAmountIn.ParseRelevantData() +} diff --git a/osmosis/modules/poolmanager/types.go b/osmosis/modules/poolmanager/types.go index 45d6cb4..079cde3 100644 --- a/osmosis/modules/poolmanager/types.go +++ b/osmosis/modules/poolmanager/types.go @@ -13,9 +13,10 @@ import ( ) const ( - MsgSwapExactAmountIn = "/osmosis.poolmanager.v1beta1.MsgSwapExactAmountIn" - MsgSwapExactAmountOut = "/osmosis.poolmanager.v1beta1.MsgSwapExactAmountOut" - MsgSplitRouteSwapExactAmountIn = "/osmosis.poolmanager.v1beta1.MsgSplitRouteSwapExactAmountIn" + MsgSwapExactAmountIn = "/osmosis.poolmanager.v1beta1.MsgSwapExactAmountIn" + MsgSwapExactAmountOut = "/osmosis.poolmanager.v1beta1.MsgSwapExactAmountOut" + MsgSplitRouteSwapExactAmountIn = "/osmosis.poolmanager.v1beta1.MsgSplitRouteSwapExactAmountIn" + MsgSplitRouteSwapExactAmountOut = "/osmosis.poolmanager.v1beta1.MsgSplitRouteSwapExactAmountOut" ) type WrapperMsgSwapExactAmountIn struct { @@ -42,6 +43,14 @@ type WrapperMsgSplitRouteSwapExactAmountIn struct { TokenIn sdk.Coin } +type WrapperMsgSplitRouteSwapExactAmountOut struct { + txModule.Message + OsmosisMsgSplitRouteSwapExactAmountOut *poolManagerTypes.MsgSplitRouteSwapExactAmountOut + Address string + TokenOut sdk.Coin + TokenIn sdk.Coin +} + func (sf *WrapperMsgSwapExactAmountIn) String() string { var tokenSwappedOut string var tokenSwappedIn string @@ -82,6 +91,19 @@ func (sf *WrapperMsgSplitRouteSwapExactAmountIn) String() string { sf.Address, tokenSwappedIn, tokenSwappedOut) } +func (sf *WrapperMsgSplitRouteSwapExactAmountOut) String() string { + var tokenSwappedOut string + var tokenSwappedIn string + if !sf.TokenOut.IsNil() { + tokenSwappedOut = sf.TokenOut.String() + } + if !sf.TokenIn.IsNil() { + tokenSwappedIn = sf.TokenIn.String() + } + return fmt.Sprintf("MsgSplitRouteSwapExactAmountOut (pool-manager): %s swapped in %s and received %s", + sf.Address, tokenSwappedIn, tokenSwappedOut) +} + func (sf *WrapperMsgSwapExactAmountIn) HandleMsg(msgType string, msg sdk.Msg, log *txModule.LogMessage) error { sf.Type = msgType sf.OsmosisMsgSwapExactAmountIn = msg.(*poolManagerTypes.MsgSwapExactAmountIn) @@ -267,6 +289,60 @@ func (sf *WrapperMsgSplitRouteSwapExactAmountIn) HandleMsg(msgType string, msg s return nil } +func (sf *WrapperMsgSplitRouteSwapExactAmountOut) HandleMsg(msgType string, msg sdk.Msg, log *txModule.LogMessage) error { + sf.Type = msgType + sf.OsmosisMsgSplitRouteSwapExactAmountOut = msg.(*poolManagerTypes.MsgSplitRouteSwapExactAmountOut) + + sf.Address = sf.OsmosisMsgSplitRouteSwapExactAmountOut.Sender + + denomOut := sf.OsmosisMsgSplitRouteSwapExactAmountOut.TokenOutDenom + + // Contains the addition of all tokens swapped in by the user + splitRouteFinalEvent := txModule.GetEventWithType("split_route_swap_exact_amount_out", log) + + if splitRouteFinalEvent == nil { + return &txModule.MessageLogFormatError{MessageType: msgType, Log: fmt.Sprintf("%+v", log)} + } + + // Mislabled event + tokensOutString, err := txModule.GetValueForAttribute("tokens_out", splitRouteFinalEvent) + if err != nil { + return err + } + + tokenInAmount, ok := sdk.NewIntFromString(tokensOutString) + if !ok { + return &txModule.MessageLogFormatError{MessageType: msgType, Log: fmt.Sprintf("%+v", log)} + } + + tokenInDenom := "" + tokenOutAmount := sdk.NewInt(0) + + for _, routes := range sf.OsmosisMsgSplitRouteSwapExactAmountOut.Routes { + if len(routes.Pools) == 0 { + continue + } + + firstPool := routes.Pools[0] + if tokenInDenom == "" { + tokenInDenom = firstPool.TokenInDenom + } else if tokenInDenom != firstPool.TokenInDenom { + return errors.New("token in denom does not match across routes first pool") + } + + tokenOutAmount = tokenOutAmount.Add(routes.TokenOutAmount) + + } + + finalTokensIn := sdk.NewCoin(tokenInDenom, tokenInAmount) + finalTokensOut := sdk.NewCoin(denomOut, tokenOutAmount) + + sf.TokenIn = finalTokensIn + sf.TokenOut = finalTokensOut + + return nil +} + func (sf *WrapperMsgSwapExactAmountIn) ParseRelevantData() []parsingTypes.MessageRelevantInformation { relevantData := make([]parsingTypes.MessageRelevantInformation, 1) relevantData[0] = parsingTypes.MessageRelevantInformation{ @@ -305,3 +381,16 @@ func (sf *WrapperMsgSplitRouteSwapExactAmountIn) ParseRelevantData() []parsingTy } return relevantData } + +func (sf *WrapperMsgSplitRouteSwapExactAmountOut) ParseRelevantData() []parsingTypes.MessageRelevantInformation { + relevantData := make([]parsingTypes.MessageRelevantInformation, 1) + relevantData[0] = parsingTypes.MessageRelevantInformation{ + AmountSent: sf.TokenIn.Amount.BigInt(), + DenominationSent: sf.TokenIn.Denom, + AmountReceived: sf.TokenOut.Amount.BigInt(), + DenominationReceived: sf.TokenOut.Denom, + SenderAddress: sf.Address, + ReceiverAddress: sf.Address, + } + return relevantData +}