-
Notifications
You must be signed in to change notification settings - Fork 3
🚚 Latest type imports, fixed names and policy version #93
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,63 @@ | ||||||||||||||||||||
| package fees | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import ( | ||||||||||||||||||||
| "errors" | ||||||||||||||||||||
| "fmt" | ||||||||||||||||||||
| "strings" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| "github.com/spf13/viper" | ||||||||||||||||||||
| ) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| type PluginConfig struct { | ||||||||||||||||||||
| Type string `mapstructure:"type"` | ||||||||||||||||||||
| Version string `mapstructure:"version"` | ||||||||||||||||||||
| RpcURL string `mapstructure:"rpc_url"` // URL for the RPC endpoint to interact with the ethereum/evm blockchain | ||||||||||||||||||||
| USDCAddress string `mapstructure:"usdc_address"` // If a non-ethereum chain is used, this is the address of the USDC token contract on that chain | ||||||||||||||||||||
| Gas struct { | ||||||||||||||||||||
| LimitMultiplier int `mapstructure:"limit_multiplier"` | ||||||||||||||||||||
| PriceMultiplier int `mapstructure:"price_multiplier"` | ||||||||||||||||||||
| } `mapstructure:"gas"` | ||||||||||||||||||||
| Monitoring struct { | ||||||||||||||||||||
| TimeoutMinutes int `mapstructure:"timeout_minutes"` | ||||||||||||||||||||
| CheckIntervalSeconds int `mapstructure:"check_interval_seconds"` | ||||||||||||||||||||
| } `mapstructure:"monitoring"` | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| func loadPluginConfig(basePath string) (*PluginConfig, error) { | ||||||||||||||||||||
| v := viper.New() | ||||||||||||||||||||
| v.SetConfigName("fees") | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Add config paths in order of precedence | ||||||||||||||||||||
| if basePath != "" { | ||||||||||||||||||||
| v.AddConfigPath(basePath) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| v.AddConfigPath(".") | ||||||||||||||||||||
| v.AddConfigPath("/etc/vultisig") | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Enable environment variable overrides | ||||||||||||||||||||
| v.AutomaticEnv() | ||||||||||||||||||||
| v.SetEnvPrefix("FEES") | ||||||||||||||||||||
| v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if err := v.ReadInConfig(); err != nil { | ||||||||||||||||||||
| return nil, fmt.Errorf("failed to read config: %w", err) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| var config PluginConfig | ||||||||||||||||||||
| if err := v.Unmarshal(&config); err != nil { | ||||||||||||||||||||
| return nil, fmt.Errorf("failed to unmarshal config: %w", err) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Validate configuration | ||||||||||||||||||||
| if config.Type != PLUGIN_TYPE { | ||||||||||||||||||||
| return nil, fmt.Errorf("invalid plugin type: %s", config.Type) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if config.RpcURL == "" { | ||||||||||||||||||||
| return nil, errors.New("rpc_url is required") | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if config.Gas.LimitMultiplier <= 0 { | ||||||||||||||||||||
| return nil, errors.New("gas limit multiplier must be positive") | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
Comment on lines
+58
to
+60
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate
-if config.Gas.LimitMultiplier <= 0 {
- return nil, errors.New("gas limit multiplier must be positive")
+if config.Gas.LimitMultiplier <= 0 {
+ return nil, errors.New("gas limit multiplier must be positive")
+}
+if config.Gas.PriceMultiplier <= 0 {
+ return nil, errors.New("gas price multiplier must be positive")
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| return &config, nil | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package fees | ||
|
|
||
| const PLUGIN_TYPE = "fees" | ||
| const erc20ABI = `[{ | ||
| "name": "transfer", | ||
| "type": "function", | ||
| "inputs": [ | ||
| {"name": "recipient", "type": "address"}, | ||
| {"name": "amount", "type": "uint256"} | ||
| ], | ||
| "outputs": [{"name": "", "type": "bool"}] | ||
| }]` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package fees | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
|
|
||
| "github.com/ethereum/go-ethereum/ethclient" | ||
| "github.com/sirupsen/logrus" | ||
| "github.com/vultisig/mobile-tss-lib/tss" | ||
| "github.com/vultisig/verifier/plugin" | ||
| "github.com/vultisig/verifier/types" | ||
|
|
||
| "github.com/vultisig/plugin/storage" | ||
| rtypes "github.com/vultisig/recipes/types" | ||
| ) | ||
|
|
||
| var _ plugin.Plugin = (*FeePlugin)(nil) | ||
|
|
||
| type FeePlugin struct { | ||
| db storage.DatabaseStorage | ||
| rpcClient *ethclient.Client | ||
| logger logrus.FieldLogger | ||
| config *PluginConfig | ||
| } | ||
|
|
||
| func NewFeePlugin(db storage.DatabaseStorage, baseConfigPath string) (*FeePlugin, error) { | ||
| if db == nil { | ||
| return nil, fmt.Errorf("database storage cannot be nil") | ||
| } | ||
| cfg, err := loadPluginConfig(baseConfigPath) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to load plugin config: %w", err) | ||
| } | ||
|
|
||
| rpcClient, err := ethclient.Dial(cfg.RpcURL) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return &FeePlugin{ | ||
| db: db, | ||
| rpcClient: rpcClient, | ||
| logger: logrus.WithField("plugin", "payroll"), | ||
| config: cfg, | ||
| }, nil | ||
|
Comment on lines
+40
to
+45
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remember to close the
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| func (fp *FeePlugin) GetRecipeSpecification() rtypes.RecipeSchema { | ||
| fp.logger.Debug("Getting recipe specification") | ||
| //TODO garry | ||
| return rtypes.RecipeSchema{ | ||
| PluginId: "vultisig-fees-0000", | ||
| Version: 1, | ||
| } | ||
| } | ||
|
|
||
| func (fp *FeePlugin) ValidatePluginPolicy(policyDoc types.PluginPolicy) error { | ||
| return nil | ||
| } | ||
| func (fp *FeePlugin) ProposeTransactions(policy types.PluginPolicy) ([]types.PluginKeysignRequest, error) { | ||
| return []types.PluginKeysignRequest{}, nil | ||
| } | ||
| func (fp *FeePlugin) ValidateProposedTransactions(policy types.PluginPolicy, txs []types.PluginKeysignRequest) error { | ||
| return nil | ||
| } | ||
| func (fp *FeePlugin) SigningComplete(ctx context.Context, signature tss.KeysignResponse, signRequest types.PluginKeysignRequest, policy types.PluginPolicy) error { | ||
| return nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Differentiate between “file not found” and real config parse errors
v.ReadInConfig()returns an error when the config file is missing.Right now any error aborts startup, even when users intend to rely solely on environment variables. Handle
viper.ConfigFileNotFoundErrorexplicitly so env-only setups still work.📝 Committable suggestion
🤖 Prompt for AI Agents