diff --git a/CHANGELOG.md b/CHANGELOG.md index 48d2c324b..b06e04389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Improvements +* [#1462](https://github.com/NibiruChain/nibiru/pull/1462) - fix(perp): Add pair to liquidation failed event. * [#1424](https://github.com/NibiruChain/nibiru/pull/1424) - feat(perp): Add change type and exchanged margin to position changed events. * [#1390](https://github.com/NibiruChain/nibiru/pull/1390) - fix(localnet.sh): Fix genesis market initialization + add force exits on failure * [#1340](https://github.com/NibiruChain/nibiru/pull/1340) - feat(wasm): Enforce x/sudo contract permission checks on the shifter contract + integration tests @@ -598,4 +599,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Testing * [#695](https://github.com/NibiruChain/nibiru/pull/695) Add `OpenPosition` integration tests. -* [#692](https://github.com/NibiruChain/nibiru/pull/692) Add test coverage for Perp MsgServer methods. \ No newline at end of file +* [#692](https://github.com/NibiruChain/nibiru/pull/692) Add test coverage for Perp MsgServer methods. diff --git a/proto/nibiru/perp/v2/tx.proto b/proto/nibiru/perp/v2/tx.proto index 273ec0749..924200123 100644 --- a/proto/nibiru/perp/v2/tx.proto +++ b/proto/nibiru/perp/v2/tx.proto @@ -122,6 +122,11 @@ message MsgMultiLiquidateResponse { // nullable since no fee is taken on failed liquidation string trader = 5; + string pair = 6 [ + (gogoproto.customtype) = + "github.com/NibiruChain/nibiru/x/common/asset.Pair", + (gogoproto.nullable) = false + ]; } repeated LiquidationResponse liquidations = 1; @@ -266,4 +271,4 @@ message MsgDonateToEcosystemFund { ]; } -message MsgDonateToEcosystemFundResponse {} \ No newline at end of file +message MsgDonateToEcosystemFundResponse {} diff --git a/x/common/testutil/events.go b/x/common/testutil/events.go index ce98ca540..ce3ac5af8 100644 --- a/x/common/testutil/events.go +++ b/x/common/testutil/events.go @@ -1,10 +1,17 @@ package testutil import ( + "fmt" "reflect" + "strings" + + "encoding/json" "github.com/cosmos/gogoproto/proto" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" @@ -59,3 +66,34 @@ func RequireContainsTypedEvent(t require.TestingT, ctx sdk.Context, event proto. t.Errorf("event not found, event: %+v, found events: %+v", event, foundEvents) } + +// ProtoToJson converts a proto message into a JSON string using the proto codec. +// A codec defines a functionality for serializing other objects. The proto +// codec provides full Protobuf serialization compatibility. +func ProtoToJson(protoMsg proto.Message) (jsonOut string, err error) { + protoCodec := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + var jsonBz json.RawMessage + jsonBz, err = protoCodec.MarshalJSON(protoMsg) + return string(jsonBz), err +} + +// EventHasAttribueValue parses the given ABCI event at a key to see if it +// matches (contains) the wanted value. +// +// Args: +// - abciEvent: The event under test +// - key: The key for which we'll check the value +// - want: The desired value +func EventHasAttribueValue(abciEvent sdk.Event, key string, want string) error { + attr, ok := abciEvent.GetAttribute(key) + if !ok { + return fmt.Errorf("abci event does not contain key: %s", key) + } + + got := attr.Value + if !strings.Contains(got, want) { + return fmt.Errorf("expected %s %s, got %s", key, want, got) + } + + return nil +} diff --git a/x/perp/v2/integration/assertion/event.go b/x/perp/v2/integration/assertion/event.go index 75df3ea43..fd0a79b9d 100644 --- a/x/perp/v2/integration/assertion/event.go +++ b/x/perp/v2/integration/assertion/event.go @@ -10,93 +10,174 @@ import ( "github.com/gogo/protobuf/proto" "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/common/testutil" "github.com/NibiruChain/nibiru/x/common/testutil/action" types "github.com/NibiruChain/nibiru/x/perp/v2/types" ) -type positionChangedEventShouldBeEqual struct { - ExpectedEvent *types.PositionChangedEvent +var _ action.Action = (*containsLiquidateEvent)(nil) +var _ action.Action = (*positionChangedEventShouldBeEqual)(nil) + +// TODO test(perp): Add action for testing the appearance of of successful +// liquidation events. + +// PositionChangedEventShouldBeEqual checks that the position changed event is +// equal to the expected event. +func PositionChangedEventShouldBeEqual( + expectedEvent *types.PositionChangedEvent, +) action.Action { + return positionChangedEventShouldBeEqual{ + ExpectedEvent: expectedEvent, + } } -func (p positionChangedEventShouldBeEqual) Do(_ *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { - for _, abciEvent := range ctx.EventManager().Events() { - if abciEvent.Type != proto.MessageName(p.ExpectedEvent) { - continue - } - typedEvent, err := sdk.ParseTypedEvent(abci.Event{ - Type: abciEvent.Type, - Attributes: abciEvent.Attributes, - }) - if err != nil { - return ctx, err, false - } +// ContainsLiquidateEvent checks if a typed event (proto.Message) is contained in the +// event manager of the app context. +func ContainsLiquidateEvent( + expectedEvent types.LiquidationFailedEvent, +) action.Action { + return containsLiquidateEvent{ + ExpectedEvent: expectedEvent, + } +} - theEvent, ok := typedEvent.(*types.PositionChangedEvent) - if !ok { - return ctx, fmt.Errorf("expected event is not of type PositionChangedEvent"), false - } +// eventEquals exports functions for comparing sdk.Events to concrete typed +// events implemented as proto.Message instances in Nibiru. +var eventEquals = iEventEquals{} - if err := types.PositionsAreEqual(&p.ExpectedEvent.FinalPosition, &theEvent.FinalPosition); err != nil { - return ctx, err, false - } +type iEventEquals struct{} - fieldErrs := []string{} - if !theEvent.PositionNotional.Equal(p.ExpectedEvent.PositionNotional) { - err := fmt.Errorf("expected position notional %s, got %s", p.ExpectedEvent.PositionNotional, theEvent.PositionNotional) - fieldErrs = append(fieldErrs, err.Error()) - } +// -------------------------------------------------- +// -------------------------------------------------- - if !theEvent.TransactionFee.Equal(p.ExpectedEvent.TransactionFee) { - err := fmt.Errorf("expected transaction fee %s, got %s", p.ExpectedEvent.TransactionFee, theEvent.TransactionFee) - fieldErrs = append(fieldErrs, err.Error()) - } +type containsLiquidateEvent struct { + ExpectedEvent types.LiquidationFailedEvent +} - if !theEvent.RealizedPnl.Equal(p.ExpectedEvent.RealizedPnl) { - err := fmt.Errorf("expected realized pnl %s, got %s", p.ExpectedEvent.RealizedPnl, theEvent.RealizedPnl) - fieldErrs = append(fieldErrs, err.Error()) +func (act containsLiquidateEvent) Do(_ *app.NibiruApp, ctx sdk.Context) ( + outCtx sdk.Context, err error, isMandatory bool, +) { + wantEvent := act.ExpectedEvent + isEventContained := false + events := ctx.EventManager().Events() + eventsOfMatchingType := []abci.Event{} + for idx, sdkEvent := range events { + err := eventEquals.LiquidationFailedEvent(sdkEvent, wantEvent, idx) + if err == nil { + isEventContained = true + break + } else if sdkEvent.Type != "nibiru.perp.v2.LiquidationFailedEvent" { + continue + } else if sdkEvent.Type == "nibiru.perp.v2.LiquidationFailedEvent" && err != nil { + abciEvent := abci.Event{ + Type: sdkEvent.Type, + Attributes: sdkEvent.Attributes, + } + eventsOfMatchingType = append(eventsOfMatchingType, abciEvent) } + } + + if isEventContained { + // happy path + return ctx, nil, true + } else { + // Show descriptive error messages if the expected event is missing + wantEventJson, _ := testutil.ProtoToJson(&wantEvent) + var matchingEvents string = sdk.StringifyEvents(eventsOfMatchingType).String() + return ctx, errors.New( + strings.Join([]string{ + fmt.Sprintf("expected the context event manager to contain event: %s.", wantEventJson), + fmt.Sprintf("found %v events:", len(events)), + fmt.Sprintf("events of matching type:\n%v", matchingEvents), + }, "\n"), + ), false + } +} - if !theEvent.BadDebt.Equal(p.ExpectedEvent.BadDebt) { - err := fmt.Errorf("expected bad debt %s, got %s", p.ExpectedEvent.BadDebt, theEvent.BadDebt) +func (ee iEventEquals) LiquidationFailedEvent( + sdkEvent sdk.Event, tevent types.LiquidationFailedEvent, eventIdx int, +) error { + fieldErrs := []string{fmt.Sprintf("[DEBUG eventIdx: %v]", eventIdx)} + + for _, keyWantPair := range []struct { + key string + want string + }{ + {"pair", tevent.Pair.String()}, + {"trader", tevent.Trader}, + {"liquidator", tevent.Liquidator}, + {"reason", tevent.Reason.String()}, + } { + if err := testutil.EventHasAttribueValue(sdkEvent, keyWantPair.key, keyWantPair.want); err != nil { fieldErrs = append(fieldErrs, err.Error()) } + } - if !theEvent.FundingPayment.Equal(p.ExpectedEvent.FundingPayment) { - err := fmt.Errorf("expected funding payment %s, got %s", p.ExpectedEvent.FundingPayment, theEvent.FundingPayment) + if len(fieldErrs) != 1 { + return errors.New(strings.Join(fieldErrs, ". ")) + } + return nil +} + +func (ee iEventEquals) PositionChangedEvent( + sdkEvent sdk.Event, tevent types.PositionChangedEvent, eventIdx int, +) error { + fieldErrs := []string{fmt.Sprintf("[DEBUG eventIdx: %v]", eventIdx)} + + for _, keyWantPair := range []struct { + key string + want string + }{ + {"position_notional", tevent.PositionNotional.String()}, + {"transaction_fee", tevent.TransactionFee.String()}, + {"bad_debt", tevent.BadDebt.String()}, + {"realized_pnl", tevent.RealizedPnl.String()}, + {"funding_payment", tevent.FundingPayment.String()}, + {"block_height", fmt.Sprintf("%v", tevent.BlockHeight)}, + {"margin_to_user", tevent.MarginToUser.String()}, + {"change_reason", string(tevent.ChangeReason)}, + } { + if err := testutil.EventHasAttribueValue(sdkEvent, keyWantPair.key, keyWantPair.want); err != nil { fieldErrs = append(fieldErrs, err.Error()) } + } - if theEvent.BlockHeight != p.ExpectedEvent.BlockHeight { - err := fmt.Errorf("expected block height %d, got %d", p.ExpectedEvent.BlockHeight, theEvent.BlockHeight) - fieldErrs = append(fieldErrs, err.Error()) + if len(fieldErrs) != 1 { + return errors.New(strings.Join(fieldErrs, ". ")) + } + return nil +} + +type positionChangedEventShouldBeEqual struct { + ExpectedEvent *types.PositionChangedEvent +} + +func (p positionChangedEventShouldBeEqual) Do(_ *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) { + for eventIdx, gotSdkEvent := range ctx.EventManager().Events() { + if gotSdkEvent.Type != proto.MessageName(p.ExpectedEvent) { + continue + } + gotProtoMessage, err := sdk.ParseTypedEvent(abci.Event{ + Type: gotSdkEvent.Type, + Attributes: gotSdkEvent.Attributes, + }) + if err != nil { + return ctx, err, false } - if !theEvent.MarginToUser.Equal(p.ExpectedEvent.MarginToUser) { - err := fmt.Errorf("expected exchanged margin %s, got %s", - p.ExpectedEvent.MarginToUser, theEvent.MarginToUser) - fieldErrs = append(fieldErrs, err.Error()) + gotTypedEvent, ok := gotProtoMessage.(*types.PositionChangedEvent) + if !ok { + return ctx, fmt.Errorf("expected event is not of type PositionChangedEvent"), false } - if theEvent.ChangeReason != p.ExpectedEvent.ChangeReason { - err := fmt.Errorf("expected change type %s, got %s", - p.ExpectedEvent.ChangeReason, theEvent.ChangeReason) - fieldErrs = append(fieldErrs, err.Error()) + if err := types.PositionsAreEqual(&p.ExpectedEvent.FinalPosition, &gotTypedEvent.FinalPosition); err != nil { + return ctx, err, false } - if len(fieldErrs) != 0 { - err := strings.Join(fieldErrs, "\n") - return ctx, errors.New(err), false + if err := eventEquals.PositionChangedEvent(gotSdkEvent, *gotTypedEvent, eventIdx); err != nil { + return ctx, err, false } } return ctx, nil, false } - -// PositionChangedEventShouldBeEqual checks that the position changed event is equal to the expected event. -func PositionChangedEventShouldBeEqual( - expectedEvent *types.PositionChangedEvent, -) action.Action { - return positionChangedEventShouldBeEqual{ - ExpectedEvent: expectedEvent, - } -} diff --git a/x/perp/v2/keeper/liquidate.go b/x/perp/v2/keeper/liquidate.go index 58ec18feb..ce55fcafd 100644 --- a/x/perp/v2/keeper/liquidate.go +++ b/x/perp/v2/keeper/liquidate.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/NibiruChain/collections" @@ -18,44 +19,46 @@ import ( func (k Keeper) MultiLiquidate( ctx sdk.Context, liquidator sdk.AccAddress, liquidationRequests []*types.MsgMultiLiquidate_Liquidation, ) ([]*types.MsgMultiLiquidateResponse_LiquidationResponse, error) { - resp := make([]*types.MsgMultiLiquidateResponse_LiquidationResponse, len(liquidationRequests)) + resps := make([]*types.MsgMultiLiquidateResponse_LiquidationResponse, len(liquidationRequests)) var allFailed bool = true - for i, req := range liquidationRequests { - cachedCtx, commit := ctx.CacheContext() + for reqIdx, req := range liquidationRequests { traderAddr, errAccAddress := sdk.AccAddressFromBech32(req.Trader) - liquidatorFee, perpEfFee, err := k.liquidate(cachedCtx, liquidator, req.Pair, traderAddr) + liquidatorFee, perpEfFee, err := k.liquidate( + ctx, liquidator, req.Pair, traderAddr, + ) switch { case errAccAddress != nil: - resp[i] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ + resps[reqIdx] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ Success: false, Error: errAccAddress.Error(), Trader: req.Trader, + Pair: req.Pair, } case err != nil: - resp[i] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ + resps[reqIdx] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ Success: false, Error: err.Error(), Trader: req.Trader, + Pair: req.Pair, } default: + // Success case allFailed = false - resp[i] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ + resps[reqIdx] = &types.MsgMultiLiquidateResponse_LiquidationResponse{ Success: true, LiquidatorFee: &liquidatorFee, PerpEfFee: &perpEfFee, Trader: req.Trader, + Pair: req.Pair, } - - ctx.EventManager().EmitEvents(cachedCtx.EventManager().Events()) - commit() } } if allFailed { - prettyResps, errPrettyResp := PrettyLiquidateResponse(resp) + prettyResps, errPrettyResp := PrettyLiquidateResponse(resps) numLiquidations := len(liquidationRequests) errDescription := strings.Join( @@ -68,10 +71,10 @@ func (k Keeper) MultiLiquidate( if errPrettyResp != nil { errDescription += fmt.Sprintf("\n%s", errPrettyResp.Error()) } - return resp, types.ErrAllLiquidationsFailed.Wrap(errDescription) + return resps, types.ErrAllLiquidationsFailed.Wrap(errDescription) } - return resp, nil + return resps, nil } /* @@ -125,8 +128,7 @@ func PrettyLiquidateResponse( } /* - liquidate allows to liquidate the trader position if the margin is below the - +liquidate allows to liquidate the trader position if the margin is below the required margin maintenance ratio. args: @@ -134,47 +136,57 @@ args: - pair: the asset pair - trader: the trader who owns the position being liquidated -ret: +returns: - liquidatorFee: the amount of coins given to the liquidator - - perpEcosystemFundFee: the amount of coins given to the ecosystem fund + - insuranceFundFee: the amount of coins given to the ecosystem fund - err: error + - event: pointer to a typed event (proto.Message). The 'event' value + exists when the liquidation fails and is nil when the liquidation succeeds. */ func (k Keeper) liquidate( ctx sdk.Context, liquidator sdk.AccAddress, pair asset.Pair, trader sdk.AccAddress, -) (liquidatorFee sdk.Coin, ecosystemFundFee sdk.Coin, err error) { +) (liquidatorFee sdk.Coin, insuranceFundFee sdk.Coin, err error) { + // eventLiqFailed exists when the liquidation fails and is nil when the + // liquidation succeeds. + market, err := k.Markets.Get(ctx, pair) if err != nil { - _ = ctx.EventManager().EmitTypedEvent(&types.LiquidationFailedEvent{ + eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, Trader: trader.String(), Liquidator: liquidator.String(), Reason: types.LiquidationFailedEvent_NONEXISTENT_PAIR, - }) - return sdk.Coin{}, sdk.Coin{}, types.ErrPairNotFound + } + _ = ctx.EventManager().EmitTypedEvent(eventLiqFailed) + err = sdkerrors.Wrapf(types.ErrPairNotFound, "pair: %s", pair) + return } amm, err := k.AMMs.Get(ctx, pair) if err != nil { - _ = ctx.EventManager().EmitTypedEvent(&types.LiquidationFailedEvent{ + eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, Trader: trader.String(), Liquidator: liquidator.String(), Reason: types.LiquidationFailedEvent_NONEXISTENT_PAIR, - }) - return sdk.Coin{}, sdk.Coin{}, types.ErrPairNotFound + } + _ = ctx.EventManager().EmitTypedEvent(eventLiqFailed) + err = sdkerrors.Wrapf(types.ErrPairNotFound, "pair: %s", pair) + return } position, err := k.Positions.Get(ctx, collections.Join(pair, trader)) if err != nil { - _ = ctx.EventManager().EmitTypedEvent(&types.LiquidationFailedEvent{ + eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, Trader: trader.String(), Liquidator: liquidator.String(), Reason: types.LiquidationFailedEvent_NONEXISTENT_POSITION, - }) + } + _ = ctx.EventManager().EmitTypedEvent(eventLiqFailed) return } @@ -197,13 +209,15 @@ func (k Keeper) liquidate( marginRatio := MarginRatio(position, preferredPositionNotional, market.LatestCumulativePremiumFraction) if marginRatio.GTE(market.MaintenanceMarginRatio) { - _ = ctx.EventManager().EmitTypedEvent(&types.LiquidationFailedEvent{ + eventLiqFailed := &types.LiquidationFailedEvent{ Pair: pair, Trader: trader.String(), Liquidator: liquidator.String(), Reason: types.LiquidationFailedEvent_POSITION_HEALTHY, - }) - return sdk.Coin{}, sdk.Coin{}, types.ErrPositionHealthy + } + _ = ctx.EventManager().EmitTypedEvent(eventLiqFailed) + err = types.ErrPositionHealthy + return } spotMarginRatio := MarginRatio(position, spotNotional, market.LatestCumulativePremiumFraction) @@ -222,12 +236,12 @@ func (k Keeper) liquidate( liquidationResponse.FeeToLiquidator, ) - ecosystemFundFee = sdk.NewCoin( + insuranceFundFee = sdk.NewCoin( pair.QuoteDenom(), liquidationResponse.FeeToPerpEcosystemFund, ) - return liquidatorFee, ecosystemFundFee, nil + return liquidatorFee, insuranceFundFee, err } /* diff --git a/x/perp/v2/keeper/liquidate_test.go b/x/perp/v2/keeper/liquidate_test.go index 26423ae9f..7188e695d 100644 --- a/x/perp/v2/keeper/liquidate_test.go +++ b/x/perp/v2/keeper/liquidate_test.go @@ -160,6 +160,12 @@ func TestMultiLiquidate(t *testing.T) { }, ), ), + ContainsLiquidateEvent(types.LiquidationFailedEvent{ + Pair: pairBtcUsdc, + Trader: alice.String(), + Liquidator: liquidator.String(), + Reason: types.LiquidationFailedEvent_POSITION_HEALTHY, + }), ), TC("mixed bag"). @@ -215,6 +221,25 @@ func TestMultiLiquidate(t *testing.T) { }, ), ), + + ContainsLiquidateEvent(types.LiquidationFailedEvent{ + Pair: pairAtomUsdc, + Trader: alice.String(), + Liquidator: liquidator.String(), + Reason: types.LiquidationFailedEvent_POSITION_HEALTHY, + }), + ContainsLiquidateEvent(types.LiquidationFailedEvent{ + Pair: pairSolUsdc, + Trader: alice.String(), + Liquidator: liquidator.String(), + Reason: types.LiquidationFailedEvent_NONEXISTENT_PAIR, + }), + ContainsLiquidateEvent(types.LiquidationFailedEvent{ + Pair: pairBtcUsdc, + Trader: bob.String(), + Liquidator: liquidator.String(), + Reason: types.LiquidationFailedEvent_NONEXISTENT_POSITION, + }), ), } diff --git a/x/perp/v2/types/tx.pb.go b/x/perp/v2/types/tx.pb.go index 371710630..a002a62bb 100644 --- a/x/perp/v2/types/tx.pb.go +++ b/x/perp/v2/types/tx.pb.go @@ -383,11 +383,12 @@ func (m *MsgMultiLiquidateResponse) GetLiquidations() []*MsgMultiLiquidateRespon } type MsgMultiLiquidateResponse_LiquidationResponse struct { - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - LiquidatorFee *types.Coin `protobuf:"bytes,3,opt,name=liquidator_fee,json=liquidatorFee,proto3" json:"liquidator_fee,omitempty"` - PerpEfFee *types.Coin `protobuf:"bytes,4,opt,name=perp_ef_fee,json=perpEfFee,proto3" json:"perp_ef_fee,omitempty"` - Trader string `protobuf:"bytes,5,opt,name=trader,proto3" json:"trader,omitempty"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + LiquidatorFee *types.Coin `protobuf:"bytes,3,opt,name=liquidator_fee,json=liquidatorFee,proto3" json:"liquidator_fee,omitempty"` + PerpEfFee *types.Coin `protobuf:"bytes,4,opt,name=perp_ef_fee,json=perpEfFee,proto3" json:"perp_ef_fee,omitempty"` + Trader string `protobuf:"bytes,5,opt,name=trader,proto3" json:"trader,omitempty"` + Pair github_com_NibiruChain_nibiru_x_common_asset.Pair `protobuf:"bytes,6,opt,name=pair,proto3,customtype=github.com/NibiruChain/nibiru/x/common/asset.Pair" json:"pair"` } func (m *MsgMultiLiquidateResponse_LiquidationResponse) Reset() { @@ -784,83 +785,84 @@ func init() { func init() { proto.RegisterFile("nibiru/perp/v2/tx.proto", fileDescriptor_b95cda40bf0a0f91) } var fileDescriptor_b95cda40bf0a0f91 = []byte{ - // 1209 bytes of a gzipped FileDescriptorProto + // 1218 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0x4d, 0x6f, 0x1b, 0x45, 0x18, 0xce, 0xda, 0xae, 0x9b, 0x4c, 0x52, 0x27, 0x1d, 0xd2, 0xc6, 0xb5, 0x8a, 0x63, 0x56, 0x50, 0x02, 0x52, 0x76, 0x5b, 0x83, 0x84, 0x40, 0x02, 0x94, 0x26, 0x0d, 0x02, 0xc5, 0x69, 0xba, 0x44, 0x01, 0x01, 0xd2, 0x32, 0xf1, 0x8e, 0x37, 0x2b, 0x76, 0x67, 0xdc, 0x9d, 0x59, 0x2b, 0xc9, 0xa5, - 0x52, 0x91, 0x38, 0x23, 0xf1, 0x1b, 0x7a, 0x45, 0x42, 0x5c, 0xf8, 0x09, 0x3d, 0x56, 0xe2, 0x82, - 0x38, 0x44, 0x28, 0xa9, 0x80, 0x73, 0xc5, 0x0f, 0x40, 0x33, 0xfb, 0x61, 0x7b, 0xbb, 0x89, 0x1d, - 0x93, 0x46, 0xe2, 0x64, 0xef, 0xce, 0x3b, 0xcf, 0xf3, 0x3e, 0xef, 0xd7, 0x8c, 0x0d, 0xe6, 0x88, - 0xb3, 0xed, 0xf8, 0x81, 0xde, 0xc6, 0x7e, 0x5b, 0xef, 0xd4, 0x75, 0xbe, 0xab, 0xb5, 0x7d, 0xca, - 0x29, 0x2c, 0x85, 0x0b, 0x9a, 0x58, 0xd0, 0x3a, 0xf5, 0xca, 0x75, 0x9b, 0x52, 0xdb, 0xc5, 0x3a, - 0x6a, 0x3b, 0x3a, 0x22, 0x84, 0x72, 0xc4, 0x1d, 0x4a, 0x58, 0x68, 0x5d, 0xa9, 0x36, 0x29, 0xf3, - 0x28, 0xd3, 0xb7, 0x11, 0xc3, 0x7a, 0xe7, 0xd6, 0x36, 0xe6, 0xe8, 0x96, 0xde, 0xa4, 0x0e, 0x89, - 0xd6, 0x67, 0x6d, 0x6a, 0x53, 0xf9, 0x55, 0x17, 0xdf, 0xa2, 0xb7, 0x95, 0x14, 0x39, 0xe3, 0x88, - 0xe3, 0x70, 0x4d, 0xfd, 0x49, 0x01, 0xd3, 0x0d, 0x66, 0x1b, 0xd8, 0xa3, 0x1d, 0xdc, 0x40, 0xbe, - 0xed, 0x10, 0x78, 0x15, 0x14, 0x19, 0x26, 0x16, 0xf6, 0xcb, 0x4a, 0x4d, 0x59, 0x98, 0x30, 0xa2, - 0x27, 0xd8, 0x00, 0x85, 0x36, 0x72, 0xfc, 0x72, 0x4e, 0xbc, 0xbd, 0xfd, 0xee, 0xe3, 0x83, 0xf9, - 0xb1, 0xdf, 0x0f, 0xe6, 0x6f, 0xd9, 0x0e, 0xdf, 0x09, 0xb6, 0xb5, 0x26, 0xf5, 0xf4, 0x75, 0x49, - 0xb4, 0xbc, 0x83, 0x1c, 0xa2, 0x47, 0xa4, 0xbb, 0x7a, 0x93, 0x7a, 0x1e, 0x25, 0x3a, 0x62, 0x0c, - 0x73, 0x6d, 0x03, 0x39, 0xbe, 0x21, 0x61, 0xe0, 0x3b, 0xa0, 0xe8, 0x49, 0xc2, 0x72, 0xbe, 0xa6, - 0x2c, 0x4c, 0xd6, 0xaf, 0x69, 0xa1, 0x3a, 0x4d, 0xa8, 0xd3, 0x22, 0x75, 0xda, 0x32, 0x75, 0xc8, - 0xed, 0x82, 0xe0, 0x32, 0x22, 0x73, 0xf5, 0x6f, 0x05, 0xcc, 0xa5, 0x7c, 0x36, 0x30, 0x6b, 0x53, - 0xc2, 0x30, 0xfc, 0x00, 0x80, 0xd0, 0xca, 0xa4, 0x01, 0x97, 0xfe, 0x0f, 0x01, 0x3c, 0x11, 0x6e, - 0xb9, 0x1b, 0x70, 0xf8, 0x19, 0x98, 0x6e, 0x05, 0xc4, 0x72, 0x88, 0x6d, 0xb6, 0xd1, 0x9e, 0x87, - 0x09, 0x8f, 0xe4, 0x6a, 0x91, 0xdc, 0x1b, 0x3d, 0x72, 0xa3, 0x6c, 0x84, 0x1f, 0x8b, 0xcc, 0xfa, - 0x46, 0xe7, 0x7b, 0x6d, 0xcc, 0xb4, 0x15, 0xdc, 0x34, 0x4a, 0x11, 0xcc, 0x46, 0x88, 0x02, 0xdf, - 0x06, 0xe3, 0x6d, 0xca, 0x1c, 0x91, 0xcd, 0x48, 0x6f, 0x59, 0xeb, 0xcf, 0xbd, 0xb6, 0x11, 0xad, - 0x1b, 0x89, 0xa5, 0xfa, 0xa3, 0x02, 0xa6, 0x1a, 0xcc, 0x5e, 0xb2, 0xac, 0xff, 0x49, 0x6e, 0x1e, - 0x29, 0x60, 0xb6, 0xd7, 0xe1, 0x24, 0x31, 0x19, 0x81, 0x55, 0xce, 0x3c, 0xb0, 0xb9, 0xa1, 0x03, - 0xfb, 0x8f, 0x02, 0x2e, 0x37, 0x98, 0xdd, 0x08, 0x5c, 0xee, 0xac, 0x39, 0xf7, 0x03, 0xc7, 0x42, - 0x1c, 0x1f, 0x1b, 0xdd, 0x7b, 0x60, 0xca, 0x8d, 0x8c, 0x44, 0x37, 0x96, 0x73, 0xb5, 0xfc, 0xc2, - 0x64, 0x7d, 0x31, 0xcd, 0xf3, 0x1c, 0xa0, 0xb6, 0xd6, 0xdd, 0x65, 0xf4, 0x41, 0x54, 0x38, 0x98, - 0xec, 0x59, 0x4c, 0xf2, 0xa7, 0x9c, 0x4d, 0xfe, 0xae, 0x82, 0x22, 0xf7, 0x91, 0x10, 0x92, 0x0b, - 0x85, 0x84, 0x4f, 0xea, 0x5f, 0x39, 0x70, 0xed, 0x39, 0x2f, 0x93, 0x1c, 0xa1, 0x94, 0x4c, 0x45, - 0xca, 0x7c, 0x7f, 0xa0, 0xcc, 0x18, 0xa0, 0x4f, 0x6e, 0xf4, 0x2e, 0x25, 0xfb, 0x4f, 0x05, 0xbc, - 0x94, 0x61, 0x05, 0xcb, 0xe0, 0x22, 0x0b, 0x9a, 0x4d, 0xcc, 0x98, 0x0c, 0xc1, 0xb8, 0x11, 0x3f, - 0xc2, 0x59, 0x70, 0x01, 0xfb, 0x3e, 0x8d, 0x95, 0x84, 0x0f, 0x70, 0x15, 0x94, 0x62, 0x5c, 0xea, - 0x9b, 0x2d, 0x8c, 0x87, 0x2b, 0x54, 0xc5, 0xb8, 0xd4, 0xdd, 0xb6, 0x8a, 0x31, 0xfc, 0x10, 0x4c, - 0x0a, 0x59, 0x26, 0x6e, 0x49, 0x90, 0xc2, 0x70, 0x20, 0x13, 0x62, 0xcf, 0x9d, 0x96, 0x00, 0xe8, - 0x46, 0xfa, 0x42, 0x5f, 0xa4, 0x7f, 0xc9, 0xcb, 0xc1, 0x7a, 0xb7, 0x8d, 0x49, 0x5c, 0x7e, 0xe7, - 0xd5, 0xbc, 0x8b, 0xa0, 0xc0, 0x1c, 0x2b, 0x8c, 0x48, 0xa9, 0x7e, 0x2d, 0x9d, 0xbe, 0x15, 0xc7, - 0xc7, 0x4d, 0x19, 0x7c, 0x69, 0x06, 0xbf, 0x02, 0xf0, 0x7e, 0x40, 0x39, 0x36, 0x25, 0x90, 0x89, - 0x3c, 0x1a, 0x10, 0x2e, 0x23, 0x71, 0xba, 0xe6, 0xfc, 0x98, 0x70, 0x63, 0x46, 0x22, 0x2d, 0x09, - 0xa0, 0x25, 0x89, 0x03, 0x3f, 0x01, 0xe3, 0x2e, 0xee, 0x60, 0x1f, 0xd9, 0x38, 0x8c, 0xd0, 0xa9, - 0x1b, 0x3e, 0xd9, 0x0f, 0x31, 0x98, 0x13, 0x19, 0xe9, 0x73, 0xd4, 0x74, 0x1d, 0xcf, 0xe1, 0xe5, - 0xe2, 0x48, 0xee, 0xce, 0x0a, 0xb8, 0x1e, 0x6f, 0xd7, 0x04, 0x96, 0xfa, 0xf4, 0x82, 0x3c, 0x5f, - 0x7a, 0x53, 0x97, 0xd4, 0x69, 0xef, 0xb4, 0x51, 0x86, 0x9d, 0x36, 0x70, 0x07, 0x94, 0xf1, 0x6e, - 0x73, 0x07, 0x11, 0x1b, 0x5b, 0x26, 0xa1, 0xe2, 0x1d, 0x72, 0xcd, 0x0e, 0x72, 0x03, 0x3c, 0xe2, - 0xf1, 0x72, 0x35, 0xc1, 0x5b, 0x8f, 0xe0, 0xb6, 0x04, 0x1a, 0x6c, 0x81, 0xb9, 0x2e, 0x53, 0xcc, - 0x6f, 0x32, 0x67, 0x3f, 0x2c, 0x87, 0xd3, 0x13, 0x5d, 0x49, 0xe0, 0x62, 0x5d, 0x9f, 0x3a, 0xfb, - 0x99, 0xe3, 0xbc, 0x70, 0x26, 0xe3, 0xfc, 0x1e, 0x98, 0xf2, 0x31, 0x72, 0x9d, 0x7d, 0xe1, 0x3f, - 0x71, 0x47, 0xac, 0x99, 0xc9, 0x18, 0x63, 0x83, 0xb8, 0xf0, 0x6b, 0x30, 0x1b, 0x90, 0x5e, 0x50, - 0x13, 0xb5, 0x38, 0xf6, 0x47, 0xa8, 0x19, 0x01, 0x0d, 0xbb, 0x58, 0x1b, 0xc4, 0x5d, 0x12, 0x48, - 0x70, 0x0b, 0x4c, 0x47, 0xb7, 0x0e, 0x4e, 0xcd, 0x0e, 0x0a, 0x5c, 0x5e, 0xbe, 0x38, 0x12, 0xf8, - 0xa5, 0x10, 0x66, 0x93, 0x6e, 0x09, 0x10, 0xf8, 0x25, 0xb8, 0x9c, 0xe4, 0x30, 0x2e, 0x9b, 0xf2, - 0xf8, 0x48, 0xc8, 0x33, 0x31, 0x50, 0x5c, 0x2f, 0xea, 0x1e, 0x98, 0x69, 0x30, 0x7b, 0xd9, 0xa5, - 0x0c, 0x9f, 0xf3, 0x84, 0x52, 0x9f, 0xe5, 0x41, 0x39, 0xcd, 0x9d, 0xb4, 0xd8, 0x49, 0xcd, 0xa2, - 0x9c, 0x57, 0xb3, 0xe4, 0x5e, 0x70, 0xb3, 0xe4, 0x5f, 0x48, 0xb3, 0x14, 0xfe, 0x7b, 0xb3, 0x7c, - 0x0e, 0x66, 0xba, 0xa5, 0x1c, 0x9d, 0x6c, 0xa3, 0xd5, 0x72, 0x29, 0xae, 0xe5, 0xcd, 0xf0, 0x44, - 0x7c, 0xa8, 0xc8, 0xa4, 0xaf, 0x50, 0x82, 0x38, 0xde, 0xa4, 0x77, 0x9a, 0x94, 0xed, 0x31, 0x8e, - 0xbd, 0xd5, 0x80, 0x58, 0xc7, 0x16, 0xde, 0x3a, 0x18, 0xb7, 0xc4, 0x86, 0xee, 0xed, 0xee, 0x84, - 0xc3, 0x79, 0x4e, 0x78, 0xf8, 0xec, 0x60, 0x7e, 0x7a, 0x0f, 0x79, 0xee, 0x7b, 0x6a, 0xbc, 0x51, - 0x35, 0x12, 0x0c, 0x55, 0x05, 0xb5, 0xe3, 0x7c, 0x88, 0x0b, 0xb0, 0xfe, 0x73, 0x11, 0xe4, 0x1b, - 0xcc, 0x86, 0x0f, 0xc0, 0x54, 0xdf, 0xef, 0xa2, 0xf9, 0x8c, 0x8b, 0x50, 0xaf, 0x41, 0xe5, 0xf5, - 0x01, 0x06, 0x31, 0x83, 0xfa, 0xda, 0xc3, 0x5f, 0x9f, 0xfe, 0x90, 0x9b, 0x57, 0x5f, 0xd6, 0x53, - 0x3f, 0xcd, 0x7c, 0x69, 0x6d, 0x86, 0x91, 0x83, 0x0c, 0x4c, 0x74, 0x6f, 0xfe, 0xd7, 0x33, 0xc0, - 0x93, 0xd5, 0xca, 0xab, 0x27, 0xad, 0x26, 0xbc, 0xaa, 0xe4, 0xbd, 0xae, 0x56, 0xd2, 0xbc, 0xc8, - 0xb2, 0x62, 0xd2, 0xef, 0x14, 0x50, 0x4a, 0x5d, 0x8b, 0x5f, 0x19, 0x78, 0x03, 0xac, 0xbc, 0x31, - 0xf4, 0x25, 0x51, 0xbd, 0x21, 0x9d, 0xa8, 0xa9, 0xd5, 0xb4, 0x13, 0x9e, 0xb0, 0x77, 0x13, 0xd6, - 0x07, 0x60, 0xaa, 0xef, 0xf6, 0x94, 0x15, 0xfe, 0x5e, 0x83, 0xcc, 0xf0, 0x67, 0x1d, 0xe2, 0xc7, - 0x87, 0x9f, 0xb6, 0x31, 0x49, 0x06, 0x01, 0xfc, 0x56, 0x01, 0x97, 0xfa, 0xc7, 0x63, 0x2d, 0x83, - 0xa1, 0xcf, 0xa2, 0xb2, 0x30, 0xc8, 0x62, 0x70, 0x18, 0x9a, 0xc2, 0xbc, 0xeb, 0xc5, 0x23, 0x05, - 0x5c, 0xc9, 0xee, 0x99, 0x2c, 0xae, 0x4c, 0xcb, 0xca, 0xcd, 0x61, 0x2d, 0x13, 0xef, 0x6e, 0x4a, - 0xef, 0xde, 0x54, 0x17, 0xd2, 0xde, 0xc9, 0x4e, 0xc2, 0x62, 0x38, 0xe0, 0x78, 0xa3, 0x29, 0xa6, - 0xd2, 0xed, 0x8f, 0x1e, 0x1f, 0x56, 0x95, 0x27, 0x87, 0x55, 0xe5, 0x8f, 0xc3, 0xaa, 0xf2, 0xfd, - 0x51, 0x75, 0xec, 0xc9, 0x51, 0x75, 0xec, 0xb7, 0xa3, 0xea, 0xd8, 0x17, 0x8b, 0x83, 0x8e, 0x89, - 0xe4, 0x5f, 0x11, 0x31, 0x3b, 0xb6, 0x8b, 0xf2, 0x9f, 0x89, 0xb7, 0xfe, 0x0d, 0x00, 0x00, 0xff, - 0xff, 0xfc, 0xbc, 0xe4, 0x89, 0x34, 0x11, 0x00, 0x00, + 0x52, 0x91, 0x38, 0x23, 0xf1, 0x1b, 0x7a, 0x45, 0x42, 0x08, 0xc4, 0x4f, 0xe8, 0xb1, 0x12, 0x17, + 0xc4, 0x21, 0x42, 0x49, 0x0f, 0x9c, 0x2b, 0x7e, 0x00, 0x9a, 0xd9, 0x0f, 0xdb, 0xdb, 0x4d, 0xec, + 0x98, 0x34, 0x12, 0xa7, 0x64, 0x77, 0xde, 0x79, 0x9e, 0xf7, 0x79, 0xbf, 0x66, 0xd6, 0x60, 0x8e, + 0x38, 0xdb, 0x8e, 0x1f, 0xe8, 0x6d, 0xec, 0xb7, 0xf5, 0x4e, 0x5d, 0xe7, 0xbb, 0x5a, 0xdb, 0xa7, + 0x9c, 0xc2, 0x52, 0xb8, 0xa0, 0x89, 0x05, 0xad, 0x53, 0xaf, 0x5c, 0xb7, 0x29, 0xb5, 0x5d, 0xac, + 0xa3, 0xb6, 0xa3, 0x23, 0x42, 0x28, 0x47, 0xdc, 0xa1, 0x84, 0x85, 0xd6, 0x95, 0x6a, 0x93, 0x32, + 0x8f, 0x32, 0x7d, 0x1b, 0x31, 0xac, 0x77, 0x6e, 0x6d, 0x63, 0x8e, 0x6e, 0xe9, 0x4d, 0xea, 0x90, + 0x68, 0x7d, 0xd6, 0xa6, 0x36, 0x95, 0xff, 0xea, 0xe2, 0xbf, 0xe8, 0x6d, 0x25, 0x45, 0xce, 0x38, + 0xe2, 0x38, 0x5c, 0x53, 0x7f, 0x52, 0xc0, 0x74, 0x83, 0xd9, 0x06, 0xf6, 0x68, 0x07, 0x37, 0x90, + 0x6f, 0x3b, 0x04, 0x5e, 0x05, 0x45, 0x86, 0x89, 0x85, 0xfd, 0xb2, 0x52, 0x53, 0x16, 0x26, 0x8c, + 0xe8, 0x09, 0x36, 0x40, 0xa1, 0x8d, 0x1c, 0xbf, 0x9c, 0x13, 0x6f, 0x6f, 0xbf, 0xfb, 0xf8, 0x60, + 0x7e, 0xec, 0xcf, 0x83, 0xf9, 0x5b, 0xb6, 0xc3, 0x77, 0x82, 0x6d, 0xad, 0x49, 0x3d, 0x7d, 0x5d, + 0x12, 0x2d, 0xef, 0x20, 0x87, 0xe8, 0x11, 0xe9, 0xae, 0xde, 0xa4, 0x9e, 0x47, 0x89, 0x8e, 0x18, + 0xc3, 0x5c, 0xdb, 0x40, 0x8e, 0x6f, 0x48, 0x18, 0xf8, 0x0e, 0x28, 0x7a, 0x92, 0xb0, 0x9c, 0xaf, + 0x29, 0x0b, 0x93, 0xf5, 0x6b, 0x5a, 0xa8, 0x4e, 0x13, 0xea, 0xb4, 0x48, 0x9d, 0xb6, 0x4c, 0x1d, + 0x72, 0xbb, 0x20, 0xb8, 0x8c, 0xc8, 0x5c, 0xfd, 0x5b, 0x01, 0x73, 0x29, 0x9f, 0x0d, 0xcc, 0xda, + 0x94, 0x30, 0x0c, 0x3f, 0x00, 0x20, 0xb4, 0x32, 0x69, 0xc0, 0xa5, 0xff, 0x43, 0x00, 0x4f, 0x84, + 0x5b, 0xee, 0x06, 0x1c, 0x7e, 0x06, 0xa6, 0x5b, 0x01, 0xb1, 0x1c, 0x62, 0x9b, 0x6d, 0xb4, 0xe7, + 0x61, 0xc2, 0x23, 0xb9, 0x5a, 0x24, 0xf7, 0x46, 0x8f, 0xdc, 0x28, 0x1b, 0xe1, 0x9f, 0x45, 0x66, + 0x7d, 0xa3, 0xf3, 0xbd, 0x36, 0x66, 0xda, 0x0a, 0x6e, 0x1a, 0xa5, 0x08, 0x66, 0x23, 0x44, 0x81, + 0x6f, 0x83, 0xf1, 0x36, 0x65, 0x8e, 0xc8, 0x66, 0xa4, 0xb7, 0xac, 0xf5, 0xe7, 0x5e, 0xdb, 0x88, + 0xd6, 0x8d, 0xc4, 0x52, 0xfd, 0x51, 0x01, 0x53, 0x0d, 0x66, 0x2f, 0x59, 0xd6, 0xff, 0x24, 0x37, + 0x8f, 0x14, 0x30, 0xdb, 0xeb, 0x70, 0x92, 0x98, 0x8c, 0xc0, 0x2a, 0x67, 0x1e, 0xd8, 0xdc, 0xd0, + 0x81, 0xfd, 0x47, 0x01, 0x97, 0x1b, 0xcc, 0x6e, 0x04, 0x2e, 0x77, 0xd6, 0x9c, 0xfb, 0x81, 0x63, + 0x21, 0x8e, 0x8f, 0x8d, 0xee, 0x3d, 0x30, 0xe5, 0x46, 0x46, 0xa2, 0x1b, 0xcb, 0xb9, 0x5a, 0x7e, + 0x61, 0xb2, 0xbe, 0x98, 0xe6, 0x79, 0x0e, 0x50, 0x5b, 0xeb, 0xee, 0x32, 0xfa, 0x20, 0x2a, 0x1c, + 0x4c, 0xf6, 0x2c, 0x26, 0xf9, 0x53, 0xce, 0x26, 0x7f, 0x57, 0x41, 0x91, 0xfb, 0x48, 0x08, 0xc9, + 0x85, 0x42, 0xc2, 0x27, 0xf5, 0xd7, 0x3c, 0xb8, 0xf6, 0x9c, 0x97, 0x49, 0x8e, 0x50, 0x4a, 0xa6, + 0x22, 0x65, 0xbe, 0x3f, 0x50, 0x66, 0x0c, 0xd0, 0x27, 0x37, 0x7a, 0x97, 0x92, 0xfd, 0x4b, 0x0e, + 0xbc, 0x94, 0x61, 0x05, 0xcb, 0xe0, 0x22, 0x0b, 0x9a, 0x4d, 0xcc, 0x98, 0x0c, 0xc1, 0xb8, 0x11, + 0x3f, 0xc2, 0x59, 0x70, 0x01, 0xfb, 0x3e, 0x8d, 0x95, 0x84, 0x0f, 0x70, 0x15, 0x94, 0x62, 0x5c, + 0xea, 0x9b, 0x2d, 0x8c, 0x87, 0x2b, 0x54, 0xc5, 0xb8, 0xd4, 0xdd, 0xb6, 0x8a, 0x31, 0xfc, 0x10, + 0x4c, 0x0a, 0x59, 0x26, 0x6e, 0x49, 0x90, 0xc2, 0x70, 0x20, 0x13, 0x62, 0xcf, 0x9d, 0x96, 0x00, + 0xe8, 0x46, 0xfa, 0x42, 0x6f, 0xa4, 0x93, 0x84, 0x16, 0xcf, 0x24, 0xa1, 0xea, 0x6f, 0x79, 0x39, + 0xa7, 0xef, 0xb6, 0x31, 0x89, 0xab, 0xf9, 0xbc, 0x66, 0xc1, 0x22, 0x28, 0x30, 0xc7, 0x0a, 0x03, + 0x5c, 0xaa, 0x5f, 0x4b, 0x57, 0xc3, 0x8a, 0xe3, 0xe3, 0xa6, 0xcc, 0xa5, 0x34, 0x83, 0x5f, 0x01, + 0x78, 0x3f, 0xa0, 0x1c, 0x9b, 0x12, 0xc8, 0x44, 0x1e, 0x0d, 0x08, 0x97, 0x81, 0x3d, 0x5d, 0xaf, + 0x7f, 0x4c, 0xb8, 0x31, 0x23, 0x91, 0x96, 0x04, 0xd0, 0x92, 0xc4, 0x81, 0x9f, 0x80, 0x71, 0x17, + 0x77, 0xb0, 0x8f, 0x6c, 0x1c, 0x06, 0xfc, 0xd4, 0xf3, 0x23, 0xd9, 0x0f, 0x31, 0x98, 0x13, 0x09, + 0xee, 0x73, 0xd4, 0x74, 0x1d, 0xcf, 0xe1, 0x51, 0xd6, 0x4e, 0xeb, 0xee, 0xac, 0x80, 0xeb, 0xf1, + 0x76, 0x4d, 0x60, 0xa9, 0x4f, 0x2f, 0xc8, 0xe3, 0xaa, 0x37, 0x75, 0x49, 0xd9, 0xf7, 0x0e, 0x2f, + 0x65, 0xd8, 0xe1, 0x05, 0x77, 0x40, 0x19, 0xef, 0x36, 0x77, 0x10, 0xb1, 0xb1, 0x65, 0x12, 0x2a, + 0xde, 0x21, 0xd7, 0xec, 0x20, 0x37, 0xc0, 0x23, 0x9e, 0x56, 0x57, 0x13, 0xbc, 0xf5, 0x08, 0x6e, + 0x4b, 0xa0, 0xc1, 0x16, 0x98, 0xeb, 0x32, 0xc5, 0xfc, 0x26, 0x73, 0xf6, 0xc3, 0x72, 0x38, 0x3d, + 0xd1, 0x95, 0x04, 0x2e, 0xd6, 0xf5, 0xa9, 0xb3, 0x9f, 0x79, 0x3a, 0x14, 0xce, 0xe4, 0x74, 0xb8, + 0x07, 0xa6, 0x7c, 0x8c, 0x5c, 0x67, 0x5f, 0xf8, 0x4f, 0xdc, 0x11, 0x6b, 0x66, 0x32, 0xc6, 0xd8, + 0x20, 0x2e, 0xfc, 0x1a, 0xcc, 0x06, 0xa4, 0x17, 0xd4, 0x44, 0x2d, 0x8e, 0xfd, 0x11, 0x6a, 0x46, + 0x40, 0xc3, 0x2e, 0xd6, 0x06, 0x71, 0x97, 0x04, 0x12, 0xdc, 0x02, 0xd3, 0xd1, 0x25, 0x86, 0x53, + 0xb3, 0x83, 0x02, 0x97, 0x97, 0x2f, 0x8e, 0x04, 0x7e, 0x29, 0x84, 0xd9, 0xa4, 0x5b, 0x02, 0x04, + 0x7e, 0x09, 0x2e, 0x27, 0x39, 0x8c, 0xcb, 0xa6, 0x3c, 0x3e, 0x12, 0xf2, 0x4c, 0x0c, 0x14, 0xd7, + 0x8b, 0xba, 0x07, 0x66, 0x1a, 0xcc, 0x5e, 0x76, 0x29, 0xc3, 0xe7, 0x3c, 0xa1, 0xd4, 0x67, 0x79, + 0x50, 0x4e, 0x73, 0x27, 0x2d, 0x76, 0x52, 0xb3, 0x28, 0xe7, 0xd5, 0x2c, 0xb9, 0x17, 0xdc, 0x2c, + 0xf9, 0x17, 0xd2, 0x2c, 0x85, 0xff, 0xde, 0x2c, 0x9f, 0x83, 0x99, 0x6e, 0x29, 0x47, 0x07, 0xe5, + 0x68, 0xb5, 0x5c, 0x8a, 0x6b, 0x79, 0x33, 0xbc, 0xca, 0x3c, 0x54, 0x64, 0xd2, 0x57, 0x28, 0x41, + 0x1c, 0x6f, 0xd2, 0x3b, 0x4d, 0xca, 0xf6, 0x18, 0xc7, 0xde, 0x6a, 0x40, 0xac, 0x63, 0x0b, 0x6f, + 0x1d, 0x8c, 0x5b, 0x62, 0x43, 0xf7, 0xb2, 0x78, 0xc2, 0x59, 0x3f, 0x27, 0x3c, 0x7c, 0x76, 0x30, + 0x3f, 0xbd, 0x87, 0x3c, 0xf7, 0x3d, 0x35, 0xde, 0xa8, 0x1a, 0x09, 0x86, 0xaa, 0x82, 0xda, 0x71, + 0x3e, 0xc4, 0x05, 0x58, 0xff, 0xb9, 0x08, 0xf2, 0x0d, 0x66, 0xc3, 0x07, 0x60, 0xaa, 0xef, 0x33, + 0x6b, 0x3e, 0xe3, 0x5e, 0xd5, 0x6b, 0x50, 0x79, 0x7d, 0x80, 0x41, 0xcc, 0xa0, 0xbe, 0xf6, 0xf0, + 0xf7, 0xa7, 0x3f, 0xe4, 0xe6, 0xd5, 0x97, 0xf5, 0xd4, 0x97, 0x9e, 0x2f, 0xad, 0xcd, 0x30, 0x72, + 0x90, 0x81, 0x89, 0xee, 0x87, 0xc4, 0xf5, 0x0c, 0xf0, 0x64, 0xb5, 0xf2, 0xea, 0x49, 0xab, 0x09, + 0xaf, 0x2a, 0x79, 0xaf, 0xab, 0x95, 0x34, 0x2f, 0xb2, 0xac, 0x98, 0xf4, 0x3b, 0x05, 0x94, 0x52, + 0xb7, 0xec, 0x57, 0x06, 0x5e, 0x28, 0x2b, 0x6f, 0x0c, 0x7d, 0xe7, 0x54, 0x6f, 0x48, 0x27, 0x6a, + 0x6a, 0x35, 0xed, 0x84, 0x27, 0xec, 0xdd, 0x84, 0xf5, 0x01, 0x98, 0xea, 0xbb, 0x3d, 0x65, 0x85, + 0xbf, 0xd7, 0x20, 0x33, 0xfc, 0x59, 0x87, 0xf8, 0xf1, 0xe1, 0xa7, 0x6d, 0x4c, 0x92, 0x41, 0x00, + 0xbf, 0x55, 0xc0, 0xa5, 0xfe, 0xf1, 0x58, 0xcb, 0x60, 0xe8, 0xb3, 0xa8, 0x2c, 0x0c, 0xb2, 0x18, + 0x1c, 0x86, 0xa6, 0x30, 0xef, 0x7a, 0xf1, 0x48, 0x01, 0x57, 0xb2, 0x7b, 0x26, 0x8b, 0x2b, 0xd3, + 0xb2, 0x72, 0x73, 0x58, 0xcb, 0xc4, 0xbb, 0x9b, 0xd2, 0xbb, 0x37, 0xd5, 0x85, 0xb4, 0x77, 0xb2, + 0x93, 0xb0, 0x18, 0x0e, 0x38, 0xde, 0x68, 0x8a, 0xa9, 0x74, 0xfb, 0xa3, 0xc7, 0x87, 0x55, 0xe5, + 0xc9, 0x61, 0x55, 0xf9, 0xeb, 0xb0, 0xaa, 0x7c, 0x7f, 0x54, 0x1d, 0x7b, 0x72, 0x54, 0x1d, 0xfb, + 0xe3, 0xa8, 0x3a, 0xf6, 0xc5, 0xe2, 0xa0, 0x63, 0x22, 0xf9, 0x91, 0x45, 0xcc, 0x8e, 0xed, 0xa2, + 0xfc, 0xa1, 0xe3, 0xad, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xc0, 0xca, 0xcc, 0x83, 0x11, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1464,6 +1466,16 @@ func (m *MsgMultiLiquidateResponse_LiquidationResponse) MarshalToSizedBuffer(dAt _ = i var l int _ = l + { + size := m.Pair.Size() + i -= size + if _, err := m.Pair.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 if len(m.Trader) > 0 { i -= len(m.Trader) copy(dAtA[i:], m.Trader) @@ -2022,6 +2034,8 @@ func (m *MsgMultiLiquidateResponse_LiquidationResponse) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + l = m.Pair.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -3212,6 +3226,40 @@ func (m *MsgMultiLiquidateResponse_LiquidationResponse) Unmarshal(dAtA []byte) e } m.Trader = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pair", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pair.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:])