Skip to content

Conversation

@caveman-eth
Copy link
Collaborator

@caveman-eth caveman-eth commented Oct 31, 2025

Adds support for fetching and managing Ethereum Follow Protocol (EFP) followings in the wallet service

Relating to: status-im/status-desktop#18686
and status-desktop PR: status-im/status-desktop#19195

Screenshot:
efp

Complete video demo:
https://streamable.com/3y4s1f

Changes:

New EFP Client (services/wallet/thirdparty/efp/):

  • HTTP client for api.ethfollow.xyz
  • Pagination support (limit/offset parameters)
  • Server-side search via /searchFollowing endpoint
  • Stats endpoint for total following count
  • ENS name and avatar resolution included in responses

Following Manager (services/wallet/following/):

  • Provider coordination layer
  • Support for multiple data providers (extensible)
  • Error handling and logging

RPC API (services/wallet/api.go):

  • wallet_GetFollowingAddresses(userAddress, search, limit, offset) - fetch following addresses with optional search and pagination
  • wallet_GetFollowingStats(userAddress) - get total following count

Tests:

  • client_test.go - 6 unit tests for HTTP client (pagination, search, stats, error handling)
  • manager_test.go - 5 unit tests for manager (success cases, provider errors, edge cases)
  • Mock generation via gomock for testing

API Endpoints Used

  • GET /users/{address}/following?include=ens&limit={limit}&offset={offset}&sort=latest
  • GET /users/{address}/searchFollowing?include=ens&sort=latest&term={search}
  • GET /users/{address}/stats

@caveman-eth caveman-eth changed the title feat: add basic EFP (Ethereum Follow Protocol) integration for wallet feat: add EFP (Ethereum Follow Protocol) integration for wallet Oct 31, 2025
@caveman-eth caveman-eth marked this pull request as ready for review October 31, 2025 21:49
@caveman-eth
Copy link
Collaborator Author

Copy link
Member

@jrainville jrainville left a comment

Choose a reason for hiding this comment

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

Awesome work! Looks very good.

You'll have to rebase and fix some lint issues I think

@jrainville
Copy link
Member

ah, also commits need to follow conventional commit format, eg feat: add EFP following address support

@igor-sirotin
Copy link
Collaborator

@caveman-eth I have sent you an Github invite for collaborator. Please accept and rebase to trigger the CI 🙂

@status-im-auto
Copy link
Member

status-im-auto commented Nov 7, 2025

Jenkins Builds

Click to see older builds (47)
Commit #️⃣ Finished (UTC) Duration Platform Result
01b5993 #1 2025-11-07 17:18:15 ~1 min macos/status-go 📄log
✔️ 01b5993 #1 2025-11-07 17:25:11 ~7 min windows/status-go 📦zip
01b5993 #1 2025-11-07 17:49:33 ~32 min linux/status-go 📄log
01b5993 #1 2025-11-07 17:49:40 ~32 min linux/nwaku 📄log
✖️ 01b5993 #1 2025-11-07 17:50:46 ~33 min tests-rpc 📄log
✖️ 01b5993 #1 2025-11-07 17:51:05 ~33 min tests 📄log
c00dcd6 #2 2025-11-07 17:19:56 ~58 sec macos/status-go 📄log
✔️ c00dcd6 #2 2025-11-07 17:35:27 ~10 min windows/status-go 📦zip
c00dcd6 #2 2025-11-07 18:01:05 ~11 min linux/status-go 📄log
c00dcd6 #2 2025-11-07 18:01:34 ~11 min linux/nwaku 📄log
✖️ c00dcd6 #2 2025-11-07 18:02:02 ~11 min tests-rpc 📄log
✖️ c00dcd6 #2 2025-11-07 18:02:46 ~11 min tests 📄log
84ee4b3 #3 2025-11-07 18:14:24 ~1 min macos/status-go 📄log
84ee4b3 #3 2025-11-07 18:14:26 ~1 min linux/nwaku 📄log
84ee4b3 #3 2025-11-07 18:14:27 ~1 min linux/status-go 📄log
✖️ 84ee4b3 #3 2025-11-07 18:14:36 ~1 min tests-rpc 📄log
✖️ 84ee4b3 #3 2025-11-07 18:14:41 ~1 min tests 📄log
f957022 #4 2025-11-07 18:15:34 ~1 min macos/status-go 📄log
f957022 #4 2025-11-07 18:15:41 ~1 min linux/nwaku 📄log
✖️ f957022 #4 2025-11-07 18:15:43 ~58 sec tests-rpc 📄log
f957022 #4 2025-11-07 18:15:46 ~1 min linux/status-go 📄log
✖️ f957022 #4 2025-11-07 18:15:51 ~1 min tests 📄log
✔️ f957022 #4 2025-11-07 18:20:43 ~6 min windows/status-go 📦zip
✔️ 286a3ab #5 2025-11-07 18:42:03 ~3 min linux/status-go 📦zip
✔️ 286a3ab #5 2025-11-07 18:42:09 ~3 min macos/status-go 📦zip
✔️ 286a3ab #5 2025-11-07 18:46:10 ~7 min windows/status-go 📦zip
✔️ 286a3ab #5 2025-11-07 18:49:12 ~10 min linux/nwaku 📦zip
✔️ 286a3ab #5 2025-11-07 18:51:21 ~12 min tests-rpc 📄log
✔️ 286a3ab #5 2025-11-07 19:08:17 ~29 min tests 📄log
✔️ 0242326 #6 2025-11-12 23:51:44 ~3 min linux/status-go 📦zip
✔️ 0242326 #6 2025-11-12 23:52:14 ~3 min macos/status-go 📦zip
✖️ 0242326 #6 2025-11-12 23:54:13 ~5 min tests 📄log
✔️ 0242326 #6 2025-11-12 23:55:33 ~7 min windows/status-go 📦zip
✔️ 0242326 #6 2025-11-12 23:59:07 ~10 min linux/nwaku 📦zip
✔️ 0242326 #6 2025-11-13 00:00:44 ~12 min tests-rpc 📄log
✔️ f714813 #7 2025-11-12 23:59:49 ~3 min linux/status-go 📦zip
✔️ f714813 #7 2025-11-13 00:00:26 ~3 min macos/status-go 📦zip
✔️ f714813 #7 2025-11-13 00:03:38 ~7 min windows/status-go 📦zip
✔️ f714813 #7 2025-11-13 00:10:14 ~10 min linux/nwaku 📦zip
✔️ f714813 #7 2025-11-13 00:14:01 ~13 min tests-rpc 📄log
✔️ f714813 #7 2025-11-13 00:24:45 ~28 min tests 📄log
✔️ 3b3c0f8 #8 2025-11-19 09:57:55 ~3 min linux/status-go 📦zip
✔️ 3b3c0f8 #8 2025-11-19 09:58:18 ~4 min macos/status-go 📦zip
✔️ 3b3c0f8 #8 2025-11-19 10:01:38 ~7 min windows/status-go 📦zip
✔️ 3b3c0f8 #8 2025-11-19 10:05:20 ~11 min linux/nwaku 📦zip
✔️ 3b3c0f8 #8 2025-11-19 10:06:58 ~12 min tests-rpc 📄log
✔️ 3b3c0f8 #8 2025-11-19 10:21:12 ~26 min tests 📄log
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 3d463fe #9 2025-11-21 17:36:56 ~4 min macos/status-go 📦zip
✔️ 3d463fe #9 2025-11-21 17:39:09 ~6 min windows/status-go 📦zip
✔️ 3d463fe #9 2025-11-21 17:52:18 ~19 min linux/status-go 📦zip
✔️ ba85edd #10 2025-11-21 17:54:00 ~4 min macos/status-go 📦zip
✔️ ba85edd #10 2025-11-21 17:56:28 ~3 min linux/status-go 📦zip
✔️ ba85edd #10 2025-11-21 17:58:11 ~8 min windows/status-go 📦zip
✔️ ba85edd #10 2025-11-21 18:01:54 ~12 min linux/nwaku 📦zip
✔️ ba85edd #10 2025-11-21 18:04:26 ~14 min tests-rpc 📄log
✔️ ba85edd #10 2025-11-21 18:16:59 ~27 min tests 📄log

@caveman-eth caveman-eth force-pushed the develop branch 2 times, most recently from 84ee4b3 to f957022 Compare November 7, 2025 18:13
@codecov
Copy link

codecov bot commented Nov 7, 2025

Codecov Report

❌ Patch coverage is 69.59064% with 52 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.79%. Comparing base (8848411) to head (ba85edd).

Files with missing lines Patch % Lines
services/wallet/thirdparty/efp/client.go 70.66% 14 Missing and 8 partials ⚠️
services/wallet/api.go 0.00% 19 Missing ⚠️
services/wallet/following/manager.go 81.35% 8 Missing and 3 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #7052      +/-   ##
===========================================
- Coverage    59.92%   59.79%   -0.13%     
===========================================
  Files          813      815       +2     
  Lines       113989   114160     +171     
===========================================
- Hits         68306    68261      -45     
- Misses       38754    38924     +170     
- Partials      6929     6975      +46     
Flag Coverage Δ
functional 34.92% <15.20%> (-0.11%) ⬇️
unit 55.46% <69.59%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
services/wallet/service.go 77.34% <100.00%> (+0.97%) ⬆️
services/wallet/following/manager.go 81.35% <81.35%> (ø)
services/wallet/api.go 28.21% <0.00%> (-1.09%) ⬇️
services/wallet/thirdparty/efp/client.go 70.66% <70.66%> (ø)

... and 37 files with indirect coverage changes

@caveman-eth
Copy link
Collaborator Author

caveman-eth commented Nov 7, 2025

@caveman-eth I have sent you an Github invite for collaborator. Please accept and rebase to trigger the CI 🙂

Great, looks like everything is passing now

Awesome work! Looks very good.

You'll have to rebase and fix some lint issues I think

@igor-sirotin I think everything is right now :)


// Manager handles following address operations using EFP providers
type Manager struct {
providers []efp.FollowingDataProvider
Copy link
Contributor

Choose a reason for hiding this comment

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

we use a slice of providers for cases where multiple providers can be used to fetch the same type of data. I'm not super well versed in EFP, but it doesn't look like that's something we expect to happen, right?
Moreover, we're just using m.providers[0] in all methods, so making this a slice is misleading, better just make it provider efp.FollowingDataProvider

)

if len(m.providers) == 0 {
return []efp.FollowingAddress{}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

feels like we should return an error if the provider is not set and we make a request, otherwise we can't distinguish this from a "true" empty FollowingAddresses result.


// EFP (Ethereum Follow Protocol) providers
efpClient := efp.NewClient()
followingProviders := []efp.FollowingDataProvider{
Copy link
Contributor

Choose a reason for hiding this comment

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

Check how we conditionally populate the other provider lists https://github.com/status-im/status-go/blob/develop/services/wallet/service.go#L119
Please do the same thing here, we don't want accesses to the provider if thirdpartyServicesEnabled is false

func NewClient() *Client {
httpClient := thirdparty.NewHTTPClient(
thirdparty.WithDetailedTimeouts(
5*time.Second, // dialTimeout
Copy link
Contributor

Choose a reason for hiding this comment

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

these seem to be opinionated default values without any way of overriding them. Perhaps pass the httpClient as a constructor parameter instead?

const baseURL = "https://api.ethfollow.xyz/api/v1"

const (
requestDelay = 100 * time.Millisecond
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this used anywhere?

Copy link
Contributor

@dlipicar dlipicar left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution! A couple minor remarks added

Copy link
Collaborator

@igor-sirotin igor-sirotin left a comment

Choose a reason for hiding this comment

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

I agree with comments from @dlipicar, otherwise looks good! Thanks for your contribution!
I've left some minor suggestions, no blockers from my side.

Comment on lines +16 to +28
func setupTest(t *testing.T, response []byte) (*httptest.Server, func()) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
_, err := w.Write(response)
if err != nil {
return
}
}))

return srv, func() {
srv.Close()
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe implement a test suite, not to repeat this call in every test?

type EFPClientTestSuite struct {
    suite.Suite
}

func (s *EFPClientTestSuite) SetupTest() {
     // setup
}

func (s *EFPClientTestSuite) TeardownTest() {
    // cleanup
}

@caveman-eth
Copy link
Collaborator Author

@dlipicar and @igor-sirotin thanks for reviewing.
@dlipicar I have now implemented all of your suggestions, thanks for pointing out.
@igor-sirotin I have added all of your suggestions, aside from adding test suite. I could still do it, but didn't put it as high priority.

Copy link
Collaborator

@igor-sirotin igor-sirotin left a comment

Choose a reason for hiding this comment

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

Thanks for the fixes 👍

@caveman-eth
Copy link
Collaborator Author

I have updated the branch with latest upstream commits, and resolved a status-go conflict.

@igor-sirotin
Copy link
Collaborator

@caveman-eth let's make sure status-im/status-desktop#19195 is green and approved, I'll merge this one then

Introduces Ethereum Follow Protocol (EFP) integration for fetching following addresses and stats. Adds a following manager, EFP client, and related API endpoints, along with tests for both manager and client functionality.
Changed the go:generate directive to explicitly use 'go tool mockgen' instead of just 'mockgen' for generating mocks. This may improve compatibility or clarity in environments where the tool is not globally installed.
Refactored the following.Manager to accept a single EFP provider and logger instead of a slice of providers. Updated initialization in service.go and all related tests. Adjusted EFP client to require an HTTP client on construction, improving dependency injection and testability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants