Skip to content
This repository was archived by the owner on Feb 8, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion etc/vultisig/fee.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ collector_whitelist_addresses:
- 0x5BB06B9C5e4f7624Df7100Badb2F5AA1C86d8498
collector_address: 0x7d760c17d798a7A9a4c4AcAf311A02dC95972503
usdc_address: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
verifier_token: localhost-fee-key
verifier_token: localhost-fee-apikey
62 changes: 1 addition & 61 deletions internal/verifierapi/fees.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,8 @@ type FeeHistoryDto struct {
FeesPendingCollection int `json:"fees_pending_collection" validate:"required"` // Total fees pending collection in the smallest unit, e.g., "1000000" for 0.01 VULTI
}

// TODO add auth
func (v *VerifierApi) GetPluginPolicyFees(policyId uuid.UUID) (*FeeHistoryDto, error) {
url := fmt.Sprintf("/fees/policy/%s", policyId.String())
response, err := v.get(url)
if err != nil {
return nil, fmt.Errorf("failed to get plugin policy fees: %w", err)
}
defer func() {
if err := response.Body.Close(); err != nil {
v.logger.WithError(err).Error("Failed to close response body")
}
}()
if response.StatusCode == http.StatusNotFound {
return nil, fmt.Errorf("policy not found")
}

if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get plugin policy fees, status code: %d", response.StatusCode)
}

var feeHistory APIResponse[FeeHistoryDto]
if err := json.NewDecoder(response.Body).Decode(&feeHistory); err != nil {
return nil, fmt.Errorf("failed to decode plugin policy fees response: %w", err)
}

if feeHistory.Error.Message != "" {
return nil, fmt.Errorf("failed to get plugin policy fees, error: %s, details: %s", feeHistory.Error.Message, feeHistory.Error.DetailedResponse)
}

return &feeHistory.Data, nil
}

// TODO add auth
func (v *VerifierApi) GetPublicKeysFees(ecdsaPublicKey string) (*FeeHistoryDto, error) {
url := fmt.Sprintf("/fees/publickey/%s", ecdsaPublicKey)
response, err := v.get(url)
response, err := v.getAuth(fmt.Sprintf("/fees/publickey/%s", ecdsaPublicKey))

Copilot AI Jul 24, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ecdsaPublicKey parameter is directly interpolated into the URL without validation or encoding. This could potentially lead to path traversal or injection attacks if the public key contains unexpected characters. Consider validating the input format or using URL encoding.

Copilot uses AI. Check for mistakes.
if err != nil {
return nil, fmt.Errorf("failed to get public key fees: %w", err)
}
Expand Down Expand Up @@ -89,29 +55,3 @@ func (v *VerifierApi) GetPublicKeysFees(ecdsaPublicKey string) (*FeeHistoryDto,

return &feeHistory.Data, nil
}

func (v *VerifierApi) GetAllPublicKeysFees() (map[string]FeeHistoryDto, error) {
url := "/fees/all"
response, err := v.get(url)
if err != nil {
return nil, fmt.Errorf("failed to get all public key fees: %w", err)
}
defer func() {
if err := response.Body.Close(); err != nil {
v.logger.WithError(err).Error("Failed to close response body")
}
}()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get all public key fees, status code: %d", response.StatusCode)
}
var apiResponse APIResponse[map[string]FeeHistoryDto]
if err := json.NewDecoder(response.Body).Decode(&apiResponse); err != nil {
return nil, fmt.Errorf("failed to decode all public key fees response: %w", err)
}

if apiResponse.Error.Message != "" {
return nil, fmt.Errorf("failed to get all public key fees, error: %s, details: %s", apiResponse.Error.Message, apiResponse.Error.DetailedResponse)
}

return apiResponse.Data, nil
}
22 changes: 12 additions & 10 deletions internal/verifierapi/verifierapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,28 @@ type ErrorResponse struct {
type VerifierApi struct {
url string
logger *logrus.Logger
token string // api key
client *http.Client
}

func NewVerifierApi(url string, logger *logrus.Logger) *VerifierApi {
func NewVerifierApi(url string, token string, logger *logrus.Logger) *VerifierApi {
return &VerifierApi{
url: url,
logger: logger,
token: token,
client: &http.Client{},
}
}

func (v *VerifierApi) get(endpoint string) (*http.Response, error) {
r, err := http.Get(v.url + endpoint)
return http.Get(v.url + endpoint)
Comment thread
garry-sharp marked this conversation as resolved.

Copilot AI Jul 24, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplified get() method removes error logging that was present in the original implementation. This could make debugging network issues more difficult. Consider either removing this method entirely if it's no longer used, or maintaining the error logging functionality.

Suggested change
return http.Get(v.url + endpoint)
req, err := http.NewRequest(http.MethodGet, v.url+endpoint, nil)
if err != nil {
v.logger.Errorf("Failed to create GET request for endpoint %s: %v", endpoint, err)
return nil, err
}
resp, err := v.client.Do(req)
if err != nil {
v.logger.Errorf("GET request to endpoint %s failed: %v", endpoint, err)
return nil, err
}
return resp, nil

Copilot uses AI. Check for mistakes.
}

func (v *VerifierApi) getAuth(endpoint string) (*http.Response, error) {
r, err := http.NewRequest(http.MethodGet, v.url+endpoint, nil)
if err != nil {
if v.logger != nil {
v.logger.WithFields(logrus.Fields{
"method": http.MethodGet,
"url": v.url,
"endpoint": endpoint,
}).WithError(err).Error("Failed to make GET request")
}
return nil, err
}
return r, nil
r.Header.Set("Authorization", "Bearer "+v.token)
return v.client.Do(r)
}
4 changes: 4 additions & 0 deletions plugin/fees/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ func NewFeeConfig(fns ...ConfigOption) (*FeeConfig, error) {
return c, fmt.Errorf("collector_address must be in the whitelist: %s, whitelist: %v", c.CollectorAddress, c.CollectorWhitelistAddresses)
}

if c.VerifierToken == "" {
return c, errors.New("verifier_token is required")
}

return c, nil
}

Expand Down
2 changes: 2 additions & 0 deletions plugin/fees/fees.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ func NewFeePlugin(db storage.DatabaseStorage,

verifierApi := verifierapi.NewVerifierApi(
verifierUrl,
feeConfig.VerifierToken,
logger.(*logrus.Logger),
)

if verifierApi == nil {
return nil, fmt.Errorf("failed to create verifier api")
}
Expand Down