Skip to content
This repository was archived by the owner on Feb 8, 2026. It is now read-only.

Commit e8df976

Browse files
authored
Merge pull request #98 from vultisig/fees4
Introduces features releated to fee collection are part of a broader ongoing piece of work
2 parents a8235b5 + cfa1025 commit e8df976

24 files changed

Lines changed: 1319 additions & 78 deletions

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.vscode/
12
.idea/
23
*.DS_Store
34
*.dat
@@ -14,4 +15,9 @@ localconfig*
1415
worker/worker
1516
vultisigner
1617
cmd/payroll/server/server
17-
cmd/dca/server/server
18+
cmd/dca/server/server
19+
20+
tmp/
21+
test/vaults/*
22+
.air.*.toml
23+
fee_config.json

Dockerfile.postgres

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Use a specific version if you prefer, e.g. postgres:15
2-
FROM postgres:latest
2+
FROM postgres:17
33

44
COPY init-scripts/ /docker-entrypoint-initdb.d/

api/plugin.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ func (s *Server) GetPluginPolicyTransactionHistory(c echo.Context) error {
321321
}
322322

323323
func (s *Server) verifyPolicySignature(policy vtypes.PluginPolicy) bool {
324-
msgBytes, err := policyToMessageHex(policy)
324+
msgBytes, err := common.PolicyToMessageHex(policy)
325325
if err != nil {
326326
s.logger.WithError(err).Error("Failed to convert policy to message hex")
327327
return false
@@ -369,22 +369,6 @@ func (s *Server) getVault(publicKeyECDSA, pluginId string) (*v1.Vault, error) {
369369
return v, nil
370370
}
371371

372-
func policyToMessageHex(policy vtypes.PluginPolicy) ([]byte, error) {
373-
delimiter := "*#*"
374-
fields := []string{
375-
policy.Recipe,
376-
policy.PublicKey,
377-
fmt.Sprintf("%d", policy.PolicyVersion),
378-
policy.PluginVersion}
379-
for _, item := range fields {
380-
if strings.Contains(item, delimiter) {
381-
return nil, fmt.Errorf("invalid policy signature")
382-
}
383-
}
384-
result := strings.Join(fields, delimiter)
385-
return []byte(result), nil
386-
}
387-
388372
func calculateTransactionHash(txData string) (string, error) {
389373
tx := &gtypes.Transaction{}
390374
rawTx, err := hex.DecodeString(txData)

api/server_config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ type ServerConfig struct {
1010
Host string `mapstructure:"host" json:"host,omitempty"`
1111
Port int64 `mapstructure:"port" json:"port,omitempty"`
1212
EncryptionSecret string `mapstructure:"encryption_secret" json:"encryption_secret,omitempty"`
13+
VerifierUrl string `mapstructure:"verifier_url" json:"verifier_url,omitempty"` //The url of the verifier (i.e. the counter party to sign transactions).
14+
VaultsFilePath string `mapstructure:"vaults_file_path" json:"vaults_file_path,omitempty"` //This is just for testing locally
1315
}

cmd/fees/server/config.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/spf13/viper"
8+
"github.com/vultisig/verifier/vault_config"
9+
10+
"github.com/vultisig/plugin/api"
11+
"github.com/vultisig/plugin/storage"
12+
)
13+
14+
type CoreConfig struct {
15+
Server api.ServerConfig `mapstructure:"server" json:"server"`
16+
Database struct {
17+
DSN string `mapstructure:"dsn" json:"dsn,omitempty"`
18+
} `mapstructure:"database" json:"database,omitempty"`
19+
BaseConfigPath string `mapstructure:"base_config_path" json:"base_config_path,omitempty"`
20+
Redis storage.RedisConfig `mapstructure:"redis" json:"redis,omitempty"`
21+
BlockStorage vault_config.BlockStorageConfig `mapstructure:"block_storage" json:"block_storage,omitempty"`
22+
Datadog struct {
23+
Host string `mapstructure:"host" json:"host,omitempty"`
24+
Port string `mapstructure:"port" json:"port,omitempty"`
25+
} `mapstructure:"datadog" json:"datadog"`
26+
}
27+
28+
func GetConfigure() (*CoreConfig, error) {
29+
configName := os.Getenv("VS_CONFIG_NAME")
30+
if configName == "" {
31+
configName = "config"
32+
}
33+
34+
return ReadConfig(configName)
35+
}
36+
37+
func ReadConfig(configName string) (*CoreConfig, error) {
38+
viper.SetConfigName(configName)
39+
viper.AddConfigPath(".")
40+
viper.AutomaticEnv()
41+
42+
viper.SetDefault("Server.VaultsFilePath", "vaults")
43+
44+
if err := viper.ReadInConfig(); err != nil {
45+
return nil, fmt.Errorf("fail to reading config file, %w", err)
46+
}
47+
var cfg CoreConfig
48+
err := viper.Unmarshal(&cfg)
49+
if err != nil {
50+
return nil, fmt.Errorf("unable to decode into struct, %w", err)
51+
}
52+
return &cfg, nil
53+
}

cmd/fees/server/main.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
8+
"github.com/DataDog/datadog-go/statsd"
9+
"github.com/hibiken/asynq"
10+
"github.com/sirupsen/logrus"
11+
"github.com/vultisig/verifier/tx_indexer"
12+
tx_indexer_storage "github.com/vultisig/verifier/tx_indexer/pkg/storage"
13+
"github.com/vultisig/verifier/vault"
14+
15+
"github.com/vultisig/plugin/api"
16+
"github.com/vultisig/plugin/plugin/fees"
17+
"github.com/vultisig/plugin/storage"
18+
"github.com/vultisig/plugin/storage/postgres"
19+
)
20+
21+
func main() {
22+
ctx := context.Background()
23+
24+
cfg, err := GetConfigure()
25+
if err != nil {
26+
panic(err)
27+
}
28+
29+
logger := logrus.New()
30+
sdClient, err := statsd.New(net.JoinHostPort(cfg.Datadog.Host, cfg.Datadog.Port))
31+
if err != nil {
32+
panic(err)
33+
}
34+
redisStorage, err := storage.NewRedisStorage(cfg.Redis)
35+
if err != nil {
36+
panic(err)
37+
}
38+
redisOptions := asynq.RedisClientOpt{
39+
Addr: net.JoinHostPort(cfg.Redis.Host, cfg.Redis.Port),
40+
Username: cfg.Redis.User,
41+
Password: cfg.Redis.Password,
42+
DB: cfg.Redis.DB,
43+
}
44+
45+
client := asynq.NewClient(redisOptions)
46+
defer func() {
47+
if err := client.Close(); err != nil {
48+
fmt.Println("fail to close asynq client,", err)
49+
}
50+
}()
51+
52+
inspector := asynq.NewInspector(redisOptions)
53+
54+
vaultStorage, err := vault.NewBlockStorageImp(cfg.BlockStorage)
55+
if err != nil {
56+
panic(err)
57+
}
58+
59+
txIndexerStore, err := tx_indexer_storage.NewPostgresTxIndexStore(ctx, cfg.Database.DSN)
60+
if err != nil {
61+
panic(fmt.Errorf("tx_indexer_storage.NewPostgresTxIndexStore: %w", err))
62+
}
63+
64+
_ = tx_indexer.NewService(
65+
logger,
66+
txIndexerStore,
67+
tx_indexer.Chains(),
68+
)
69+
70+
db, err := postgres.NewPostgresBackend(cfg.Database.DSN, nil)
71+
if err != nil {
72+
logger.Fatalf("Failed to connect to database: %v", err)
73+
}
74+
75+
//base config path
76+
feesConfig, err := fees.NewFeeConfig(
77+
fees.WithVerifierUrl(cfg.Server.VerifierUrl),
78+
)
79+
80+
if err != nil {
81+
logger.Fatalf("failed to create fees config,err: %s", err)
82+
}
83+
84+
feePlugin, err := fees.NewFeePlugin(db, logger, cfg.BaseConfigPath, feesConfig)
85+
if err != nil {
86+
logger.Fatalf("failed to create DCA plugin,err: %s", err)
87+
}
88+
server := api.NewServer(
89+
cfg.Server,
90+
db,
91+
redisStorage,
92+
vaultStorage,
93+
redisOptions,
94+
client,
95+
inspector,
96+
sdClient,
97+
feePlugin,
98+
)
99+
if err := server.StartServer(); err != nil {
100+
panic(err)
101+
}
102+
}

cmd/fees/worker/config.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/spf13/viper"
8+
"github.com/vultisig/verifier/vault_config"
9+
10+
"github.com/vultisig/plugin/api"
11+
"github.com/vultisig/plugin/storage"
12+
)
13+
14+
type CoreConfig struct {
15+
Server api.ServerConfig `mapstructure:"server" json:"server"`
16+
Database struct {
17+
DSN string `mapstructure:"dsn" json:"dsn,omitempty"`
18+
} `mapstructure:"database" json:"database,omitempty"`
19+
BaseConfigPath string `mapstructure:"base_config_path" json:"base_config_path,omitempty"`
20+
Redis storage.RedisConfig `mapstructure:"redis" json:"redis,omitempty"`
21+
BlockStorage vault_config.BlockStorageConfig `mapstructure:"block_storage" json:"block_storage,omitempty"`
22+
VaultServiceConfig vault_config.Config `mapstructure:"vault_service" json:"vault_service,omitempty"`
23+
Datadog struct {
24+
Host string `mapstructure:"host" json:"host,omitempty"`
25+
Port string `mapstructure:"port" json:"port,omitempty"`
26+
} `mapstructure:"datadog" json:"datadog"`
27+
}
28+
29+
func GetConfigure() (*CoreConfig, error) {
30+
configName := os.Getenv("VS_CONFIG_NAME")
31+
if configName == "" {
32+
configName = "config"
33+
}
34+
35+
return ReadConfig(configName)
36+
}
37+
38+
func ReadConfig(configName string) (*CoreConfig, error) {
39+
viper.SetConfigName(configName)
40+
viper.AddConfigPath(".")
41+
viper.AutomaticEnv()
42+
43+
if err := viper.ReadInConfig(); err != nil {
44+
return nil, fmt.Errorf("fail to reading config file, %w", err)
45+
}
46+
var cfg CoreConfig
47+
err := viper.Unmarshal(&cfg)
48+
if err != nil {
49+
return nil, fmt.Errorf("unable to decode into struct, %w", err)
50+
}
51+
return &cfg, nil
52+
}

0 commit comments

Comments
 (0)