Skip to content

Commit

Permalink
feat: add market community tags
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy Letang <me@jeremyletang.com>
  • Loading branch information
jeremyletang committed Aug 9, 2024
1 parent c8af335 commit a001bec
Show file tree
Hide file tree
Showing 22 changed files with 6,110 additions and 5,332 deletions.
1 change: 1 addition & 0 deletions commands/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ var (
ErrInvalidSignature = errors.New("invalid signature")
ErrUnsupportedAlgorithm = errors.New("unsupported algorithm")
ErrEmptyBatchMarketInstructions = errors.New("empty batch market instructions")
ErrIsNotValidVegaID = errors.New("is not a valid vega id")
ErrIsNotValidVegaPubkey = errors.New("is not a valid vega public key")
ErrIsNotValidEthereumAddress = errors.New("is not a valid ethereum address")
ErrEmptyEthereumCallSpec = errors.New("ethereum call spec is required")
Expand Down
22 changes: 22 additions & 0 deletions commands/proposal_submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,35 @@ func checkProposalChanges(terms *protoTypes.ProposalTerms) Errors {
errs.Merge(checkUpdateReferralProgram(terms, c))
case *protoTypes.ProposalTerms_UpdateVolumeDiscountProgram:
errs.Merge(checkVolumeDiscountProgram(terms, c))
case *protoTypes.ProposalTerms_UpdateMarketCommunityTags:
errs.Merge(checkUpdateMarketCommunityTagsChanges(c))
default:
return errs.FinalAddForProperty("proposal_submission.terms.change", ErrIsNotValid)
}

return errs
}

func checkUpdateMarketCommunityTagsChanges(change *protoTypes.ProposalTerms_UpdateMarketCommunityTags) Errors {
errs := NewErrors()

if change.UpdateMarketCommunityTags == nil {
return errs.FinalAddForProperty("proposal_submission.terms.change.update_market_community_tags", ErrIsRequired)
}

if change.UpdateMarketCommunityTags.Changes == nil {
return errs.FinalAddForProperty("proposal_submission.terms.change.update_market_community_tags.changes", ErrIsRequired)
}

c := change.UpdateMarketCommunityTags.Changes

if !crypto.IsValidVegaID(c.MarketId) {
errs.AddForProperty("proposal_submission.terms.change.update_market_community_tags.changes", ErrIsNotValidVegaID)
}

return errs
}

func checkNetworkParameterUpdateChanges(change *protoTypes.ProposalTerms_UpdateNetworkParameter) Errors {
errs := NewErrors()

Expand Down
5 changes: 4 additions & 1 deletion core/events/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ const (
VolumeRebateProgramEndedEvent
VolumeRebateProgramUpdatedEvent
VolumeRebateStatsUpdatedEvent
MarketCommunityTagsEvent
)

var (
Expand Down Expand Up @@ -285,6 +286,7 @@ var (
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_ENDED: VolumeRebateProgramEndedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_UPDATED: VolumeRebateProgramUpdatedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_STATS_UPDATED: VolumeRebateStatsUpdatedEvent,
eventspb.BusEventType_BUS_EVENT_TYPE_MARKET_COMMUNITY_TAG: MarketCommunityTagsEvent,
// If adding a type here, please also add it to datanode/broker/convert.go
}

Expand Down Expand Up @@ -383,7 +385,7 @@ var (
VolumeRebateProgramEndedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_ENDED,
VolumeRebateProgramUpdatedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_PROGRAM_UPDATED,
VolumeRebateStatsUpdatedEvent: eventspb.BusEventType_BUS_EVENT_TYPE_VOLUME_REBATE_STATS_UPDATED,

MarketCommunityTagsEvent: eventspb.BusEventType_BUS_EVENT_TYPE_MARKET_COMMUNITY_TAG,
// If adding a type here, please also add it to datanode/broker/convert.go
}

Expand Down Expand Up @@ -481,6 +483,7 @@ var (
VolumeRebateProgramEndedEvent: "VolumeRebateProgramEndedEvent",
VolumeRebateProgramUpdatedEvent: "VolumeRebateProgramUpdatedEvent",
VolumeRebateStatsUpdatedEvent: "VolumeRebateStatsUpdatedEvent",
MarketCommunityTagsEvent: "MarketCommunityTagsEvent",
}
)

Expand Down
57 changes: 57 additions & 0 deletions core/events/market_community_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2023 Gobalsky Labs Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package events

import (
"context"

eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
)

type MarketCommunityTags struct {
*Base
a eventspb.MarketCommunityTags
}

func NewMarketCommunityTagsEvent(ctx context.Context, e eventspb.MarketCommunityTags) *MarketCommunityTags {
return &MarketCommunityTags{
Base: newBase(ctx, MarketCommunityTagsEvent),
a: e,
}
}

func (a *MarketCommunityTags) MarketCommunityTags() eventspb.MarketCommunityTags {
return a.a
}

func (a MarketCommunityTags) Proto() eventspb.MarketCommunityTags {
return a.a
}

func (a MarketCommunityTags) StreamMessage() *eventspb.BusEvent {
busEvent := newBusEventFromBase(a.Base)
busEvent.Event = &eventspb.BusEvent_MarketCommunityTags{
MarketCommunityTags: &a.a,
}
return busEvent
}

func MarketCommunityTagsEventFromStream(ctx context.Context, be *eventspb.BusEvent) *MarketCommunityTags {
return &MarketCommunityTags{
Base: newBaseFromBusEvent(ctx, MarketCommunityTagsEvent, be),
a: *be.GetMarketCommunityTags(),
}
}
9 changes: 5 additions & 4 deletions core/execution/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type Engine struct {
allMarkets map[string]common.CommonMarket
allMarketsCpy []common.CommonMarket

communityTags *MarketCommunityTags
collateral common.Collateral
assets common.Assets
referralDiscountRewardService fee.ReferralDiscountRewardService
Expand Down Expand Up @@ -169,10 +170,10 @@ func NewEngine(
referralDiscountRewardService: referralDiscountRewardService,
volumeDiscountService: volumeDiscountService,
volumeRebateService: volumeRebateService,

banking: banking,
parties: parties,
delayTransactionsTarget: delayTransactionsTarget,
banking: banking,
parties: parties,
delayTransactionsTarget: delayTransactionsTarget,
communityTags: NewMarketCommunityTags(broker),
}

// set the eligibility for proposer bonus checker
Expand Down
16 changes: 11 additions & 5 deletions core/execution/engine_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,17 @@ func (e *Engine) serialise() (snapshot []byte, providers []types.StateProvider,
allMarketIDs = append(allMarketIDs, cm.GetID())
}

tags := e.communityTags.serialize()

pl := types.Payload{
Data: &types.PayloadExecutionMarkets{
ExecutionMarkets: &types.ExecutionMarkets{
Markets: mkts,
SpotMarkets: spotMkts,
SettledMarkets: cpStates,
Successors: successors,
AllMarketIDs: allMarketIDs,
Markets: mkts,
SpotMarkets: spotMkts,
SettledMarkets: cpStates,
Successors: successors,
AllMarketIDs: allMarketIDs,
MarketCommunityTags: tags,
},
},
}
Expand Down Expand Up @@ -383,6 +386,9 @@ func (e *Engine) LoadState(ctx context.Context, payload *types.Payload) ([]types
e.allMarketsCpy = append(e.allMarketsCpy, mkt)
}
}

e.communityTags = NewMarketCommunityTagFromProto(e.broker, pl.ExecutionMarkets.MarketCommunityTags)

return append(providers, spotProviders...), err
default:
return nil, types.ErrUnknownSnapshotType
Expand Down
107 changes: 107 additions & 0 deletions core/execution/market_community_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (C) 2023 Gobalsky Labs Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package execution

import (
"context"
"sort"

"code.vegaprotocol.io/vega/core/events"
"code.vegaprotocol.io/vega/core/execution/common"
eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"

"golang.org/x/exp/maps"
)

type MarketCommunityTags struct {
// market id -> set of tags
tags map[string]map[string]struct{}
broker common.Broker
}

func NewMarketCommunityTags(broker common.Broker) *MarketCommunityTags {
return &MarketCommunityTags{
tags: map[string]map[string]struct{}{},
broker: broker,
}
}

func NewMarketCommunityTagFromProto(
broker common.Broker,
state []*eventspb.MarketCommunityTags,
) *MarketCommunityTags {
m := NewMarketCommunityTags(broker)

for _, v := range state {
m.tags[v.MarketId] = map[string]struct{}{}
for _, t := range v.Tags {
m.tags[v.MarketId][t] = struct{}{}
}
}

return m
}

func (m *MarketCommunityTags) serialize() []*eventspb.MarketCommunityTags {
out := make([]*eventspb.MarketCommunityTags, 0, len(m.tags))

for mkt, tags := range m.tags {
mct := &eventspb.MarketCommunityTags{
MarketId: mkt,
Tags: make([]string, 0, len(tags)),
}

for tag := range tags {
mct.Tags = append(mct.Tags, tag)
}

sort.Strings(mct.Tags)
}

sort.Slice(out, func(i, j int) bool { return out[i].MarketId < out[j].MarketId })

return out
}

// UpdateTags by that point the tags have been validated in length,
// so no need to do that again.
func (m *MarketCommunityTags) UpdateTags(
ctx context.Context,
market string,
addTags []string,
removeTags []string,
) {
tags, ok := m.tags[market]
if !ok {
tags = map[string]struct{}{}
}

for _, t := range addTags {
tags[t] = struct{}{}
}

for _, t := range removeTags {
delete(tags, t)
}

evt := eventspb.MarketCommunityTags{
MarketId: market,
Tags: maps.Keys(tags),
}

sort.Strings(evt.Tags)
m.broker.Send(events.NewMarketCommunityTagsEvent(ctx, evt))
}
15 changes: 15 additions & 0 deletions core/governance/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ var (
ErrParentMarketAlreadySucceeded = errors.New("the parent market was already succeeded by a prior proposal")
ErrParentMarketSucceededByCompeting = errors.New("the parent market has been succeeded by a competing propsal")
ErrSettlementDataOutOfRange = errors.New("the settlement data is invalid")
ErrUnknownMarketID = func(id string) error {
return fmt.Errorf("unknown market id %v", id)
}
)

//go:generate go run github.com/golang/mock/mockgen -destination mocks/mocks.go -package mocks code.vegaprotocol.io/vega/core/governance Markets,StakingAccounts,Assets,TimeService,Witness,NetParams,Banking
Expand Down Expand Up @@ -745,6 +748,8 @@ func (e *Engine) getProposalParams(proposalTerm types.ProposalTerm) (*types.Prop
return e.getVolumeDiscountProgramNetworkParameters(), nil
case types.ProposalTermsTypeUpdateVolumeRebateProgram:
return e.getVolumeRebateProgramNetworkParameters(), nil
case types.ProposalTermsTypeUpdateMarketCommunityTags:
return e.getUpdateMarketCommunityTagsParameters(), nil
default:
return nil, ErrUnsupportedProposalType
}
Expand Down Expand Up @@ -1097,11 +1102,21 @@ func (e *Engine) validateChange(terms *types.ProposalTerms) (types.ProposalError
return validateUpdateVolumeDiscountProgram(e.netp, terms.GetUpdateVolumeDiscountProgram())
case types.ProposalTermsTypeUpdateVolumeRebateProgram:
return validateUpdateVolumeRebateProgram(e.netp, terms.GetUpdateVolumeRebateProgram())
case types.ProposalTermsTypeUpdateMarketCommunityTags:
return validateUpdateMarketCommunityTags(terms.GetUpdateMarketCommunityTags(), e.markets)
default:
return types.ProposalErrorUnspecified, nil
}
}

func validateUpdateMarketCommunityTags(p *types.UpdateMarketCommunityTags, markets Markets) (types.ProposalError, error) {
if !markets.MarketExists(p.MarketID) {
return types.ProposalErrorUnknownMarketID, ErrUnknownMarketID(p.MarketID)
}

return types.ProposalErrorUnspecified, nil
}

func (e *Engine) validateGovernanceTransfer(newTransfer *types.NewTransfer) (types.ProposalError, error) {
if err := e.banking.VerifyGovernanceTransfer(newTransfer.Changes); err != nil {
return types.ProporsalErrorInvalidGovernanceTransfer, err
Expand Down
16 changes: 16 additions & 0 deletions core/governance/netparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,22 @@ func (e *Engine) getVolumeRebateProgramNetworkParameters() *types.ProposalParame
)
}

func (e *Engine) getUpdateMarketCommunityTagsParameters() *types.ProposalParameters {
return e.getProposalParametersFromNetParams(
netparams.GovernanceProposalUpdateCommunityTagsMinClose,
netparams.GovernanceProposalUpdateCommunityTagsMaxClose,
netparams.GovernanceProposalUpdateCommunityTagsMinEnact,
netparams.GovernanceProposalUpdateCommunityTagsMaxEnact,
netparams.GovernanceProposalUpdateCommunityTagsRequiredParticipation,
netparams.GovernanceProposalUpdateCommunityTagsRequiredMajority,
netparams.GovernanceProposalUpdateCommunityTagsMinProposerBalance,
netparams.GovernanceProposalUpdateCommunityTagsMinVoterBalance,
"0",
"0",
"0",
)
}

func (e *Engine) getNewAssetProposalParameters() *types.ProposalParameters {
return e.getProposalParametersFromNetParams(
netparams.GovernanceProposalAssetMinClose,
Expand Down
10 changes: 10 additions & 0 deletions core/netparams/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ func defaultNetParams() map[string]value {
MarketLiquidityProvidersFeeCalculationTimeStep: NewDuration(gte1s, lte255h).Mutable(true).MustUpdate("1m"),
MarketLiquidityEquityLikeShareFeeFraction: NewDecimal(gteD0, lteD1).Mutable(true).MustUpdate("1"),

// updateCommunityTags proposal parameters.
GovernanceProposalUpdateCommunityTagsMinClose: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("24h0m0s"),
GovernanceProposalUpdateCommunityTagsMaxClose: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("8760h0m0s"),
GovernanceProposalUpdateCommunityTagsMinEnact: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("24h0m0s"),
GovernanceProposalUpdateCommunityTagsMaxEnact: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("8760h0m0s"),
GovernanceProposalUpdateCommunityTagsRequiredParticipation: NewDecimal(gteD0, lteD1).Mutable(true).MustUpdate("0.025"),
GovernanceProposalUpdateCommunityTagsRequiredMajority: NewDecimal(gteD0, lteD1).Mutable(true).MustUpdate("0.66"),
GovernanceProposalUpdateCommunityTagsMinProposerBalance: NewUint(gteU1, ltMaxU).Mutable(true).MustUpdate("1000000000000000000"),
GovernanceProposalUpdateCommunityTagsMinVoterBalance: NewUint(gteU1, ltMaxU).Mutable(true).MustUpdate("1000000000000000000"),

// governance market proposal
GovernanceProposalMarketMinClose: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("48h0m0s"),
GovernanceProposalMarketMaxClose: NewDuration(gte1s, lte1y).Mutable(true).MustUpdate("8760h0m0s"),
Expand Down
Loading

0 comments on commit a001bec

Please sign in to comment.