Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(farcaster): enable offchain resolver to farcaster names #194 #203

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

developerfred
Copy link
Contributor

#194

This script provides functionality to interact with the Farcaster network by resolving user details based on Ethereum addresses and usernames. It utilizes two primary functions: lookupAddresses and resolveNames. The lookupAddresses function fetches Farcaster user details, including usernames, verified Ethereum and Solana addresses, and profile picture URLs, based on a list of Ethereum addresses. The resolveNames function does similarly, but it resolves these details based on Farcaster usernames or domain names.

Key Components:

  • fetchData: A helper function that performs API requests to the Farcaster network, handling headers and errors.
  • lookupAddresses: Takes an array of Ethereum addresses, queries the Farcaster user details for each, and returns a structured result with user information.
  • resolveNames: Accepts an array of Farcaster handles (usernames or .fcast.id domains), fetches their details, and returns their information, similar to lookupAddresses.

Example Usage:

async function example() {
  // Example Ethereum addresses and Farcaster handles
  const addresses = ['0xd1a8dd23e356b9fae27df5def9ea025a602ec81e'];
  const handles = ['codingsh', 'codingsh.fcast.id'];

  try {
    const addressResults = await lookupAddresses(addresses);
    console.log('Address Results:', addressResults);

    const nameResults = await resolveNames(handles);
    console.log('Name Results:', nameResults);
  } catch (error) {
    console.error('Error:', error);
  }
}

example();

Output:

This will output user details for each provided Ethereum address and Farcaster handle, including their usernames, verified addresses on Ethereum and Solana, and profile picture URLs, if available.

@bonustrack bonustrack requested a review from wa0x6e April 10, 2024 00:27
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
@developerfred
Copy link
Contributor Author

Thanks @wa0x6e, I will jump now

@developerfred
Copy link
Contributor Author

image

@developerfred developerfred requested a review from wa0x6e April 10, 2024 20:10
@wa0x6e
Copy link
Contributor

wa0x6e commented Apr 10, 2024

image

Tests are still failing

 FAIL  test/integration/addressResolvers/farcaster.test.ts (7.212 s)
  Farcaster address resolver
    lookupAddresses()
      when the address is associated to a domain
        ✕ returns the domain associated to the address (1012 ms)
      when the address is not associated to a domain
        ✓ returns an empty object (798 ms)
      when mix of addresses with and without associated domains
        ✕ returns an object with only addresses associated to a domain (309 ms)
    resolveNames()
      when the domain is associated to an address
        ✕ returns an address (1432 ms)
      when the domain is not associated to an address
        ✕ returns undefined (870 ms)
      when mix of domains with and without associated address
        ✕ returns an object with only handles associated to an address (1687 ms)

  ● Farcaster address resolver › lookupAddresses() › when the address is associated to a domain › returns the domain associated to the address

    expect(received).resolves.toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 8

      Object {
    -   "0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e": "codingsh.fcast.id",
    +   "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e": Object {
    +     "eth_addresses": Array [
    +       "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e",
    +     ],
    +     "pfp_url": "https://i.imgur.com/5HxmC1P.jpg",
    +     "sol_addresses": Array [],
    +     "username": "codingsh",
    +   },
      }

      12 |       describe('when the address is associated to a domain', () => {
      13 |         it('returns the domain associated to the address', async () => {
    > 14 |           return expect(lookupAddresses([validAddress])).resolves.toEqual({
         |                                                                   ^
      15 |             [validAddress]: validDomain
      16 |           });
      17 |         }, 10e3);

      at Object.toEqual (node_modules/expect/build/index.js:194:22)
      at Object.<anonymous> (test/integration/addressResolvers/helper.ts:14:67)

  ● Farcaster address resolver › lookupAddresses() › when mix of addresses with and without associated domains › returns an object with only addresses associated to a domain

    expect(received).resolves.toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 8

      Object {
    -   "0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e": "codingsh.fcast.id",
    +   "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e": Object {
    +     "eth_addresses": Array [
    +       "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e",
    +     ],
    +     "pfp_url": "https://i.imgur.com/5HxmC1P.jpg",
    +     "sol_addresses": Array [],
    +     "username": "codingsh",
    +   },
      }

      26 |       describe('when mix of addresses with and without associated domains', () => {
      27 |         it('returns an object with only addresses associated to a domain', () => {
    > 28 |           return expect(lookupAddresses([validAddress, blankAddress])).resolves.toEqual({
         |                                                                                 ^
      29 |             [validAddress]: validDomain
      30 |           });
      31 |         }, 10e3);

      at Object.toEqual (node_modules/expect/build/index.js:194:22)
      at Object.<anonymous> (test/integration/addressResolvers/helper.ts:28:81)

  ● Farcaster address resolver › resolveNames() › when the domain is associated to an address › returns an address

    expect(received).resolves.toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 6

      Object {
    -   "codingsh.fcast.id": "0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e",
    +   "codingsh.fcast.id": Object {
    +     "eth_addresses": Array [
    +       "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e",
    +     ],
    +     "username": "codingsh",
    +   },
      }

      36 |       describe('when the domain is associated to an address', () => {
      37 |         it('returns an address', () => {
    > 38 |           return expect(resolveNames([validDomain])).resolves.toEqual({
         |                                                               ^
      39 |             [validDomain]: validAddress
      40 |           });
      41 |         }, 10e3);

      at Object.toEqual (node_modules/expect/build/index.js:194:22)
      at Object.<anonymous> (test/integration/addressResolvers/helper.ts:38:63)

  ● Farcaster address resolver › resolveNames() › when the domain is not associated to an address › returns undefined

    expect(received).resolves.toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 3

    - Object {}
    + Object {
    +   "test.snapshotdomain": "User not found or error searching for details.",
    + }

      44 |       describe('when the domain is not associated to an address', () => {
      45 |         it('returns undefined', () => {
    > 46 |           return expect(resolveNames(['test.snapshotdomain'])).resolves.toEqual({});
         |                                                                         ^
      47 |         }, 10e3);
      48 |       });
      49 |

      at Object.toEqual (node_modules/expect/build/index.js:194:22)
      at Object.<anonymous> (test/integration/addressResolvers/helper.ts:46:73)

  ● Farcaster address resolver › resolveNames() › when mix of domains with and without associated address › returns an object with only handles associated to an address

    expect(received).resolves.toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 9

      Object {
    -   "codingsh.fcast.id": "0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e",
    +   "codingsh.fcast.id": Object {
    +     "eth_addresses": Array [
    +       "0xd1a8dd23e356b9fae27df5def9ea025a602ec81e",
    +     ],
    +     "username": "codingsh",
    +   },
    +   "domain.com": "User not found or error searching for details.",
    +   "domain.crypto": "User not found or error searching for details.",
    +   "domain.eth": "User not found or error searching for details.",
      }

      50 |       describe('when mix of domains with and without associated address', () => {
      51 |         it('returns an object with only handles associated to an address', () => {
    > 52 |           return expect(resolveNames([...invalidDomains, validDomain])).resolves.toEqual({
         |                                                                                  ^
      53 |             [validDomain]: validAddress
      54 |           });
      55 |         }, 10e3);

      at Object.toEqual (node_modules/expect/build/index.js:194:22)
      at Object.<anonymous> (test/integration/addressResolvers/helper.ts:52:82)

------------------------|---------|----------|---------|---------|-------------------------
File                    | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------------
All files               |    6.35 |     23.8 |    12.9 |    6.35 |
 src                    |       0 |        0 |       0 |       0 |
  api.ts                |       0 |        0 |       0 |       0 | 1-125
  aws.ts                |       0 |        0 |       0 |       0 | 1-74
  index.ts              |       0 |        0 |       0 |       0 | 1-34
  utils.ts              |       0 |        0 |       0 |       0 | 1-142
 src/addressResolvers   |   14.58 |    45.45 |   36.36 |   14.58 |
  cache.ts              |       0 |        0 |       0 |       0 | 1-46
  ens.ts                |       0 |        0 |       0 |       0 | 1-99
  farcaster.ts          |   90.65 |    66.66 |     100 |   90.65 | 38-39,61-62,65-67,87-89
  index.ts              |       0 |        0 |       0 |       0 | 1-76
  lens.ts               |       0 |        0 |       0 |       0 | 1-80
  starknet.ts           |       0 |        0 |       0 |       0 | 1-84
  unstoppableDomains.ts |       0 |        0 |       0 |       0 | 1-87
  utils.ts              |       0 |        0 |       0 |       0 | 1-86
 src/helpers            |       0 |        0 |       0 |       0 |
  metrics.ts            |       0 |        0 |       0 |       0 | 1-33
  redis.ts              |       0 |        0 |       0 |       0 | 1-18
  utils.ts              |       0 |        0 |       0 |       0 | 1-19
 src/resolvers          |       0 |        0 |       0 |       0 |
  blockie.ts            |       0 |        0 |       0 |       0 | 1-11
  ens.ts                |       0 |        0 |       0 |       0 | 1-37
  index.ts              |       0 |        0 |       0 |       0 | 1-26
  jazzicon.ts           |       0 |        0 |       0 |       0 | 1-19
  lens.ts               |       0 |        0 |       0 |       0 | 1-62
  selfid.ts             |       0 |        0 |       0 |       0 | 1-23
  snapshot.ts           |       0 |        0 |       0 |       0 | 1-28
  space-sx.ts           |       0 |        0 |       0 |       0 | 1-57
  space.ts              |       0 |        0 |       0 |       0 | 1-27
  starknet.ts           |       0 |        0 |       0 |       0 | 1-58
  trustwallet.ts        |       0 |        0 |       0 |       0 | 1-24
  utils.ts              |       0 |        0 |       0 |       0 | 1-21
  zapper.ts             |       0 |        0 |       0 |       0 | 1-24
------------------------|---------|----------|---------|---------|-------------------------
Test Suites: 1 failed, 1 total
Tests:       5 failed, 1 passed, 6 total
Snapshots:   0 total
Time:        7.38 s

@wa0x6e
Copy link
Contributor

wa0x6e commented Apr 10, 2024

Can you also run yarn lint and fix all the warnings

@wa0x6e
Copy link
Contributor

wa0x6e commented Apr 10, 2024

And in src/addressResolvers/index.ts, you should import the new farcaster module and add it to the RESOLVERS constant

@wa0x6e
Copy link
Contributor

wa0x6e commented Apr 10, 2024

You can test the code manuall by sending the curl command

curl --location 'http://localhost:3008' \
--header 'Content-Type: application/json' \
--data '{
    "method": "resolve_names",
    "params": ["codingsh.fcast.id"]
}'

It should return

{"jsonrpc":"2.0","result":{"codingsh.fcast.id":"0xd1a8Dd23e356B9fAE27dF5DeF9ea025A602EC81e"},"id":null}

src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
@developerfred developerfred requested a review from wa0x6e April 10, 2024 22:39
src/addressResolvers/farcaster.ts Show resolved Hide resolved
tsconfig.json Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
src/addressResolvers/farcaster.ts Outdated Show resolved Hide resolved
@developerfred developerfred requested a review from wa0x6e April 15, 2024 01:39
package.json Outdated Show resolved Hide resolved
tsconfig.json Outdated Show resolved Hide resolved
package.json Outdated Show resolved Hide resolved
Copy link
Contributor Author

@developerfred developerfred left a comment

Choose a reason for hiding this comment

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

chore(farcaster): fix tscofing and package.json

@developerfred developerfred requested a review from wa0x6e April 16, 2024 07:23
package.json Outdated Show resolved Hide resolved
tsconfig.json Outdated Show resolved Hide resolved
@developerfred developerfred force-pushed the feat/farcaster-resolver-offchain branch from 2b70bef to b24f960 Compare April 18, 2024 02:07
@developerfred developerfred requested a review from wa0x6e April 18, 2024 12:31
@wa0x6e
Copy link
Contributor

wa0x6e commented Apr 25, 2024

Results from resolve_names are wrong:

curl -X POST http://localhost:3008/ -H "Content-Type: application/json" -d '{"method": "resolve_names", "params": [ "farcaster.fcast.id"] }'

// output
{"jsonrpc":"2.0","result":{"farcaster.fcast.id":"0xbf74483DB914192bb0a9577f3d8Fb29a6d4c08eE"},"id":null}

The address 0xbf74483DB914192bb0a9577f3d8Fb29a6d4c08eE is associated to farcasteradmin.eth.fcast.id and not farcaster.fcast.id

@bonustrack
Copy link
Contributor

Maybe that's something you can takeover @mktcode, ideally we would like to use the Farcaster profile name instead of Farcaster username.

@mktcode
Copy link
Contributor

mktcode commented Jul 30, 2024

Will be continued here: #271

@mktcode mktcode closed this Jul 30, 2024
@mktcode mktcode reopened this Aug 7, 2024
@mktcode mktcode removed their assignment Aug 7, 2024
@wa0x6e wa0x6e removed their request for review January 11, 2025 14:26
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.

4 participants