├── .eslintrc.js
├── .gitignore
├── .husky
└── pre-commit
├── .npmignore
├── .prettierrc.json
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── assets
│ └── abi
│ │ ├── follow-nft.json
│ │ └── lenshub.json
├── context
│ └── LensContext.tsx
├── hooks
│ ├── api
│ │ ├── broadcast.ts
│ │ ├── collect.ts
│ │ ├── comment.ts
│ │ ├── follow.ts
│ │ ├── indexer.ts
│ │ ├── login.ts
│ │ ├── mirror.ts
│ │ ├── post.ts
│ │ ├── profile.ts
│ │ ├── publication.ts
│ │ └── search.ts
│ ├── combined
│ │ ├── collect.ts
│ │ ├── comment.ts
│ │ ├── follow.ts
│ │ ├── mirror.ts
│ │ └── post.ts
│ ├── contract
│ │ ├── collect.ts
│ │ ├── comment.ts
│ │ ├── follow.ts
│ │ ├── index.ts
│ │ ├── mirror.ts
│ │ ├── post.ts
│ │ └── profile.ts
│ └── utils
│ │ ├── broadcast.ts
│ │ ├── contract.ts
│ │ └── sign.ts
├── index.ts
├── types
│ ├── error.ts
│ ├── lens.ts
│ ├── metadata.ts
│ ├── modules.ts
│ └── on.ts
└── utils
│ ├── omit-deep.ts
│ └── tx.ts
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true,
5 | },
6 | extends: ["eslint:recommended", "plugin:react/recommended", "standard-with-typescript", "prettier"],
7 | overrides: [],
8 | parserOptions: {
9 | ecmaVersion: "latest",
10 | sourceType: "module",
11 | project: "tsconfig.json",
12 | },
13 | plugins: ["simple-import-sort", "react"],
14 | rules: {
15 | "react/react-in-jsx-scope": ["off"],
16 | "@typescript-eslint/strict-boolean-expressions": ["off"],
17 | "simple-import-sort/imports": "error",
18 | "simple-import-sort/exports": "error",
19 | "react/no-unescaped-entities": ["off"],
20 | },
21 | settings: {
22 | react: { version: "detect" },
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .husky
2 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "trailingComma": "all",
4 | "singleQuote": false,
5 | "printWidth": 120,
6 | "tabWidth": 2,
7 | "bracketSameLine": true,
8 | "endOfLine": "auto"
9 | }
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 memester
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
lens-use 🌱
2 |
3 | Deprecation Notice
4 |
5 |
6 | Lens Protocol is working on their own React SDK which should be used instead of this library.
7 |
8 |
9 | React Hooks for Lens Protocol
10 |
11 |
12 |
13 | React 🤝 Lens Protocol
14 |
15 |
16 | **Standing on the shoulders of these chads (aka, dependencies):**
17 |
18 | - [Apollo GraphQL](https://www.apollographql.com/docs/)
19 | - [wagmi](https://wagmi.sh/)
20 | - [ethers](https://docs.ethers.io/v5/)
21 |
22 | **Jump straight to the [Hooks Reference](#hooks-reference)**
23 |
24 | # Example
25 |
26 | ```typescript
27 | const { data: profileResponse } = useProfile("stani.lens");
28 |
29 | const { data: publicationsResponse } = usePublications(profileResponse?.profile?.id);
30 |
31 | const { collect } = useCollect(publicationsResponse?.publications?.items[0].id);
32 |
33 | const onClick = () => {
34 | collect();
35 | };
36 | ```
37 |
38 | # Installation
39 |
40 | ```bash
41 | # npm
42 | npm install --save @memester-xyz/lens-use
43 |
44 | # yarn
45 | yarn add @memester-xyz/lens-use
46 |
47 | # pnpm
48 | pnpm add @memester-xyz/lens-use
49 | ```
50 |
51 | # Usage
52 |
53 | ## Basic
54 |
55 | 1. Your app must first be wrapped in a Wagmi context and a Apollo context (connected to the Lens API). e.g.:
56 |
57 | ```typescript
58 | function App() {
59 | return (
60 |
61 |
62 |
63 |
64 |
65 | );
66 | }
67 | ```
68 |
69 | 2. You can then use the Lens hooks in any components inside of your DApp component:
70 |
71 | ```typescript
72 | import { useProfile } from "@memester-xyz/lens-use";
73 |
74 | // ...
75 |
76 | const { data } = useProfile("stani.lens");
77 | ```
78 |
79 | 3. The return value of any API hook (e.g. `useProfile`, `useChallenge`) is a typed Apollo GraphQL return value. i.e.
80 |
81 | - [`QueryResult`](https://www.apollographql.com/docs/react/api/react/hooks/#result) for queries
82 | - [`MutationTuple`](https://www.apollographql.com/docs/react/api/react/hooks/#mutationtupletdata-tvariables-result-tuple) for mutations.
83 |
84 | 4. The return value of any contract hook (e.g. `useContractProfile`, `useContractCollect`) is a modification of a normal Wagmi [`useContractRead`](https://wagmi.sh/docs/hooks/useContractRead#return-value) or [`useContractWrite`](https://wagmi.sh/docs/hooks/useContractWrite#return-value).
85 |
86 | 5. The return value of any action hook (e.g. `useCollect`) is an object containing:
87 | - a write method with the same name as the hook action (e.g. `collect()`)
88 | - a loading boolean when the request is in flight `loading`
89 | - an Error object or undefined `error`
90 |
91 | Full API specification is below in the [hooks](#hooks) section.
92 |
93 | ## Advanced
94 |
95 | By default we use the currently known Polygon Mainnet Lens Hub Proxy address. There are two ways to override this but both require adding our `LensProvider` context to your app.
96 |
97 | 1. You can use the currently known Mumbai (testnet) address:
98 |
99 | ```typescript
100 | function App() {
101 | return (
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | );
110 | }
111 | ```
112 |
113 | 2. You can pass a custom Lens Hub contract address:
114 |
115 | ```typescript
116 | function App() {
117 | return (
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | );
126 | }
127 | ```
128 |
129 | # Hooks Reference
130 |
131 | - [Login](#login)
132 | - [useChallenge](#useChallenge)
133 | - [useAuthenticate](#useAuthenticate)
134 | - [useRefresh](#useRefresh)
135 | - [Query](#query)
136 | - [useProfile](#useProfile)
137 | - [useProfiles](#useProfiles)
138 | - [useDefaultProfile](#useDefaultProfile)
139 | - [useProfilePicture](#useProfilePicture)
140 | - [useProfileHasDispatcher](#useProfileHasDispatcher)
141 | - [usePublication](#usePublication)
142 | - [usePublications](#usePublications)
143 | - [usePublicationComments](#usePublicationComments)
144 | - [useSearch](#useSearch)
145 | - [Write](#write)
146 | - [useCollect](#useCollect)
147 | - [useComment](#useComment)
148 | - [useFollow](#useFollow)
149 | - [useUnfollow](#useUnfollow)
150 | - [useMirror](#useMirror)
151 | - [usePost](#usePost)
152 | - [Contract](#contract)
153 | - [useContractCollect](#useContractCollect)
154 | - [useContractComment](#useContractComment)
155 | - [useContractFollow](#useContractFollow)
156 | - [useContractUnfollow](#useContractUnfollow)
157 | - [useContractMirror](#useContractMirror)
158 | - [useContractPost](#useContractPost)
159 | - [useContractProfile](#useContractProfile)
160 |
161 | ## Login
162 |
163 | Hooks to help with authenticating against the Lens API.
164 |
165 | ### useChallenge
166 |
167 | _[Lens Reference](https://docs.lens.xyz/docs/login#challenge)_
168 |
169 | Get a challenge to be signed by the user
170 |
171 | ```typescript
172 | const { data: challengeData } = useChallenge(address);
173 |
174 | // challengeData.challenge.text must be signed by the user's wallet
175 | ```
176 |
177 | ### useAuthenticate
178 |
179 | _[Lens Reference](https://docs.lens.xyz/docs/login#authenticate)_
180 |
181 | Authenticate the signed challenge
182 |
183 | ```typescript
184 | const [authenticate, { data: authenticateData }] = useAuthenticate(address, signedChallenge);
185 |
186 | // Call this method to start the authentication request
187 | authenticate();
188 |
189 | // After the request is complete
190 | // authenticateData.authenticate.accessToken has access token
191 | // authenticateData.authenticate.refreshToken has refresh token
192 | ```
193 |
194 | ### useRefresh
195 |
196 | _[Lens Reference](https://docs.lens.xyz/docs/refresh-jwt)_
197 |
198 | Refresh the JWT
199 |
200 | ```typescript
201 | const [refresh, { data: refreshData }] = useRefresh(refreshToken);
202 |
203 | // Call this method to start the refresh request
204 | refresh();
205 |
206 | // After the request is complete
207 | // refreshData.refresh.accessToken has access token
208 | // refreshData.refresh.refreshToken has refresh token
209 | ```
210 |
211 | ## Query
212 |
213 | Hooks to query the Lens API. Note, some of these require authentication, check the Lens Reference.
214 |
215 | ### useProfile
216 |
217 | _[Lens Reference](https://docs.lens.xyz/docs/get-profile#get-by-handle)_
218 |
219 | Get a profile by handle
220 |
221 | ```typescript
222 | const { data } = useProfile(handle);
223 | ```
224 |
225 | ### useProfiles
226 |
227 | _[Lens Reference](https://docs.lens.xyz/docs/get-profiles#get-by-owned-by)_
228 |
229 | Get all profiles owned by an address
230 |
231 | ```typescript
232 | const { data } = useProfiles(address);
233 | ```
234 |
235 | ### useDefaultProfile
236 |
237 | _[Lens Reference](https://docs.lens.xyz/docs/get-default-profile)_
238 |
239 | Get default profile by address
240 |
241 | ```typescript
242 | const defaultProfile = useDefaultProfile(address);
243 | ```
244 |
245 | ### useProfilePicture
246 |
247 | The response body from `useProfile` and `useDefaultProfile` is slightly different, so this method helps to pull out the profile picture from one of those.
248 |
249 | ```typescript
250 | const defaultProfile = useDefaultProfile(address);
251 | const pfpURL = useProfilePicture(defaultProfile);
252 | ```
253 |
254 | ### useProfileHasDispatcher
255 |
256 | A simple utility which returns `true` if the profile has the dispatcher enabled.
257 |
258 | ```typescript
259 | const dispatch = useProfileHasDispatcher(profileId);
260 | ```
261 |
262 | ### usePublication
263 |
264 | _[Lens Reference](https://docs.lens.xyz/docs/get-publication)_
265 |
266 | Retrieve details for a specific publication
267 |
268 | ```typescript
269 | const { data } = usePublication(publicationId);
270 |
271 | // Pass in profileId to get the mirrored status in your publication results
272 | const { data } = usePublication(publicationId, profileId);
273 | ```
274 |
275 | ### usePublications
276 |
277 | _[Lens Reference](https://docs.lens.xyz/docs/get-publications)_
278 |
279 | Retrieve publications based on various parameters
280 |
281 | ```typescript
282 | // Get posts from a specific profile
283 | const { data } = usePublications(profileId);
284 |
285 | // Get posts and comments from a specific profile
286 | const { data } = usePublications(profileId, [PublicationType.POST, PublicationType.COMMENT]);
287 |
288 | // Get posts from a specific profile and source
289 | const { data } = usePublications(profileId, [PublicationType.POST], ["memester"]);
290 | ```
291 |
292 | ### usePublicationComments
293 |
294 | _[Lens Reference](https://docs.lens.xyz/docs/get-publications)_
295 |
296 | Retrieve publications based on various parameters
297 |
298 | ```typescript
299 | // Get comments for a specific publication
300 | const { data } = usePublicationComments(publicationId);
301 | ```
302 |
303 | ### useSearch
304 |
305 | _[Lens Reference](https://docs.lens.xyz/docs/search-profiles-and-publications#search-across-profiles)_
306 |
307 | Search profiles
308 |
309 | ```typescript
310 | const { data } = useSearch("stani");
311 | ```
312 |
313 | ## Write
314 |
315 | Hooks to write to Lens using the [dispatcher](https://docs.lens.xyz/docs/dispatcher) if enabled or the [broadcaster](https://docs.lens.xyz/docs/broadcast-transaction) if not. Note, your Apollo GraphQL client must be [authenticated](https://docs.lens.xyz/docs/authentication-quickstart)!
316 |
317 | All write hooks take an optional final parameter which allows you to specify callback functions. An example is given for `useCollect` but the same applies to all hooks in this section.
318 |
319 | ### useCollect
320 |
321 | Collect a publication using the API
322 |
323 | ```typescript
324 | const { collect, loading, error } = useCollect(publicationId);
325 |
326 | // Call this method to start the collect request
327 | collect();
328 |
329 | // You can also pass in callback functions
330 | const { collect, loading, error } = useCollect(publicationId, {
331 | onBroadcasted(receipt) {
332 | // ...
333 | },
334 | onCompleted(receipt) {
335 | // receipt will be undefined if the request errored for some reason
336 | },
337 | });
338 | ```
339 |
340 | ### useComment
341 |
342 | Comment on a publication. Requires a URL with the comment metadata already uploaded
343 |
344 | ```typescript
345 | const { collect, loading, error } = useComment(profileId, publicationId, commentURL);
346 |
347 | // Call this method to start the comment request
348 | comment();
349 | ```
350 |
351 | ### useFollow
352 |
353 | Follow a profile
354 |
355 | ```typescript
356 | const { follow, loading, error } = useFollow(profileIdToFollow);
357 |
358 | // Call this method to start the follow request
359 | follow();
360 | ```
361 |
362 | ### useUnfollow
363 |
364 | Unfollow a profile
365 |
366 | ```typescript
367 | const { unfollow, loading, error } = useUnfollow(profileIdToUnfollow);
368 |
369 | // Call this method to start the unfollow request
370 | unfollow();
371 | ```
372 |
373 | ### useMirror
374 |
375 | Mirror a publication
376 |
377 | ```typescript
378 | const { mirror, loading, error } = useMirror(profileId, publicationId);
379 |
380 | // Call this method to start the mirror request
381 | mirror();
382 | ```
383 |
384 | ### usePost
385 |
386 | Post. Requires a URL with the post metadata already uploaded
387 |
388 | ```typescript
389 | const { post, loading, error } = usePost(profileId, postURL);
390 |
391 | // Call this method to start the post request
392 | post();
393 | ```
394 |
395 | ## Contract
396 |
397 | ### useContractCollect
398 |
399 | _[Lens Reference](https://docs.lens.xyz/docs/functions#collect)_
400 |
401 | Collect a publication using the Lens Hub Contract
402 |
403 | ```typescript
404 | const { write, data, prepareError, writeError, status } = useContractCollect(profileId, publicationId);
405 |
406 | // Call this method to invoke the users connected wallet
407 | write();
408 | ```
409 |
410 | ### useContractComment
411 |
412 | _[Lens Reference](https://docs.lens.xyz/docs/functions#comment)_
413 |
414 | Comment on a publication using the Lens Hub Contract
415 |
416 | ```typescript
417 | const { write, data, prepareError, writeError, status } = useContractCollect(
418 | profileId,
419 | contentURI,
420 | profileIdPointed,
421 | pubIdPointed,
422 | collectModule,
423 | collectModuleInitData,
424 | referenceModule,
425 | referenceModuleInitData,
426 | referenceModuleData,
427 | );
428 |
429 | // Call this method to invoke the users connected wallet
430 | write();
431 | ```
432 |
433 | ### useContractFollow
434 |
435 | _[Lens Reference](https://docs.lens.xyz/docs/functions#follow)_
436 |
437 | Follow profiles using the Lens Hub Contract
438 |
439 | ```typescript
440 | const { write, data, prepareError, writeError, status } = useContractFollow(profileIds);
441 |
442 | // Call this method to invoke the users connected wallet
443 | write();
444 | ```
445 |
446 | ### useContractUnfollow
447 |
448 | _[Lens Reference](https://docs.lens.xyz/docs/follow)_
449 |
450 | Unfollow a profile by burning the specific Follow NFT. You must pass in the relevant follow NFT address and tokenId
451 |
452 | ```typescript
453 | const { write, data, prepareError, writeError, status } = useContractUnfollow(followNFTAddress, tokenId);
454 |
455 | // Call this method to invoke the users connected wallet
456 | write();
457 | ```
458 |
459 | ### useContractMirror
460 |
461 | _[Lens Reference](https://docs.lens.xyz/docs/functions#mirror)_
462 |
463 | Mirror a publication using the Lens Hub Contract
464 |
465 | ```typescript
466 | const { write, data, prepareError, writeError, status } = useContractMirror(
467 | profileId,
468 | profileIdPointed,
469 | pubIdPointed,
470 | referenceModuleData,
471 | referenceModule,
472 | referenceModuleInitData,
473 | );
474 |
475 | // Call this method to invoke the users connected wallet
476 | write();
477 | ```
478 |
479 | ### useContractPost
480 |
481 | _[Lens Reference](https://docs.lens.xyz/docs/functions#post)_
482 |
483 | Post using the Lens Hub Contract
484 |
485 | ```typescript
486 | const { write, data, prepareError, writeError, status } = useContractPost(
487 | profileId?,
488 | contentURI,
489 | collectModule,
490 | collectModuleInitData,
491 | referenceModule,
492 | referenceModuleInitData,
493 | );
494 |
495 | // Call this method to invoke the users connected wallet
496 | write();
497 | ```
498 |
499 | ### useContractProfile
500 |
501 | _[Lens Reference](https://docs.lens.xyz/docs/view-functions#getprofile)_
502 |
503 | Read profile from the Lens Hub Contract
504 |
505 | ```typescript
506 | const { data } = useContractProfile(profileId);
507 | ```
508 |
509 | ---
510 |
511 | _Made with 🫡 by [memester.xyz](https://memester.xyz)_
512 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@memester-xyz/lens-use",
3 | "version": "0.1.1",
4 | "description": "React hooks for Lens Protocol",
5 | "main": "dist/index.js",
6 | "types": "dist/index.d.ts",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/memester-xyz/lens-use.git"
10 | },
11 | "scripts": {
12 | "prepublish": "tsc",
13 | "format": "prettier --check 'src/**/*.ts*'",
14 | "format:write": "prettier --write 'src/**/*.ts*'",
15 | "lint": "eslint 'src/**/*.ts*'",
16 | "lint:fix": "eslint --fix 'src/**/*.ts*'",
17 | "prepare": "husky install"
18 | },
19 | "lint-staged": {
20 | "*.ts*": [
21 | "eslint --fix",
22 | "prettier --write"
23 | ]
24 | },
25 | "dependencies": {
26 | "@apollo/client": "^3.7.1",
27 | "ethers": "^5.7.0",
28 | "wagmi": "^0.6.4"
29 | },
30 | "devDependencies": {
31 | "@types/react": "^18.0.17",
32 | "@typescript-eslint/eslint-plugin": "^5.36.2",
33 | "eslint": "^8.23.0",
34 | "eslint-config-prettier": "^8.5.0",
35 | "eslint-config-standard-with-typescript": "^22.0.0",
36 | "eslint-plugin-import": "^2.26.0",
37 | "eslint-plugin-n": "^15.2.5",
38 | "eslint-plugin-promise": "^6.0.1",
39 | "eslint-plugin-react": "^7.31.8",
40 | "eslint-plugin-simple-import-sort": "^8.0.0",
41 | "husky": "^8.0.1",
42 | "lint-staged": "^13.0.3",
43 | "prettier": "^2.7.1",
44 | "typescript": "^4.8.3"
45 | },
46 | "author": "Devan Non ",
47 | "license": "MIT"
48 | }
49 |
--------------------------------------------------------------------------------
/src/assets/abi/follow-nft.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "hub",
7 | "type": "address"
8 | }
9 | ],
10 | "stateMutability": "nonpayable",
11 | "type": "constructor"
12 | },
13 | {
14 | "inputs": [],
15 | "name": "BlockNumberInvalid",
16 | "type": "error"
17 | },
18 | {
19 | "inputs": [],
20 | "name": "InitParamsInvalid",
21 | "type": "error"
22 | },
23 | {
24 | "inputs": [],
25 | "name": "Initialized",
26 | "type": "error"
27 | },
28 | {
29 | "inputs": [],
30 | "name": "NotHub",
31 | "type": "error"
32 | },
33 | {
34 | "inputs": [],
35 | "name": "NotOwnerOrApproved",
36 | "type": "error"
37 | },
38 | {
39 | "inputs": [],
40 | "name": "SignatureExpired",
41 | "type": "error"
42 | },
43 | {
44 | "inputs": [],
45 | "name": "SignatureInvalid",
46 | "type": "error"
47 | },
48 | {
49 | "inputs": [],
50 | "name": "TokenDoesNotExist",
51 | "type": "error"
52 | },
53 | {
54 | "inputs": [],
55 | "name": "ZeroSpender",
56 | "type": "error"
57 | },
58 | {
59 | "anonymous": false,
60 | "inputs": [
61 | {
62 | "indexed": true,
63 | "internalType": "address",
64 | "name": "owner",
65 | "type": "address"
66 | },
67 | {
68 | "indexed": true,
69 | "internalType": "address",
70 | "name": "approved",
71 | "type": "address"
72 | },
73 | {
74 | "indexed": true,
75 | "internalType": "uint256",
76 | "name": "tokenId",
77 | "type": "uint256"
78 | }
79 | ],
80 | "name": "Approval",
81 | "type": "event"
82 | },
83 | {
84 | "anonymous": false,
85 | "inputs": [
86 | {
87 | "indexed": true,
88 | "internalType": "address",
89 | "name": "owner",
90 | "type": "address"
91 | },
92 | {
93 | "indexed": true,
94 | "internalType": "address",
95 | "name": "operator",
96 | "type": "address"
97 | },
98 | {
99 | "indexed": false,
100 | "internalType": "bool",
101 | "name": "approved",
102 | "type": "bool"
103 | }
104 | ],
105 | "name": "ApprovalForAll",
106 | "type": "event"
107 | },
108 | {
109 | "anonymous": false,
110 | "inputs": [
111 | {
112 | "indexed": true,
113 | "internalType": "address",
114 | "name": "from",
115 | "type": "address"
116 | },
117 | {
118 | "indexed": true,
119 | "internalType": "address",
120 | "name": "to",
121 | "type": "address"
122 | },
123 | {
124 | "indexed": true,
125 | "internalType": "uint256",
126 | "name": "tokenId",
127 | "type": "uint256"
128 | }
129 | ],
130 | "name": "Transfer",
131 | "type": "event"
132 | },
133 | {
134 | "inputs": [],
135 | "name": "HUB",
136 | "outputs": [
137 | {
138 | "internalType": "address",
139 | "name": "",
140 | "type": "address"
141 | }
142 | ],
143 | "stateMutability": "view",
144 | "type": "function"
145 | },
146 | {
147 | "inputs": [
148 | {
149 | "internalType": "address",
150 | "name": "to",
151 | "type": "address"
152 | },
153 | {
154 | "internalType": "uint256",
155 | "name": "tokenId",
156 | "type": "uint256"
157 | }
158 | ],
159 | "name": "approve",
160 | "outputs": [],
161 | "stateMutability": "nonpayable",
162 | "type": "function"
163 | },
164 | {
165 | "inputs": [
166 | {
167 | "internalType": "address",
168 | "name": "owner",
169 | "type": "address"
170 | }
171 | ],
172 | "name": "balanceOf",
173 | "outputs": [
174 | {
175 | "internalType": "uint256",
176 | "name": "",
177 | "type": "uint256"
178 | }
179 | ],
180 | "stateMutability": "view",
181 | "type": "function"
182 | },
183 | {
184 | "inputs": [
185 | {
186 | "internalType": "uint256",
187 | "name": "tokenId",
188 | "type": "uint256"
189 | }
190 | ],
191 | "name": "burn",
192 | "outputs": [],
193 | "stateMutability": "nonpayable",
194 | "type": "function"
195 | },
196 | {
197 | "inputs": [
198 | {
199 | "internalType": "uint256",
200 | "name": "tokenId",
201 | "type": "uint256"
202 | },
203 | {
204 | "components": [
205 | {
206 | "internalType": "uint8",
207 | "name": "v",
208 | "type": "uint8"
209 | },
210 | {
211 | "internalType": "bytes32",
212 | "name": "r",
213 | "type": "bytes32"
214 | },
215 | {
216 | "internalType": "bytes32",
217 | "name": "s",
218 | "type": "bytes32"
219 | },
220 | {
221 | "internalType": "uint256",
222 | "name": "deadline",
223 | "type": "uint256"
224 | }
225 | ],
226 | "internalType": "struct DataTypes.EIP712Signature",
227 | "name": "sig",
228 | "type": "tuple"
229 | }
230 | ],
231 | "name": "burnWithSig",
232 | "outputs": [],
233 | "stateMutability": "nonpayable",
234 | "type": "function"
235 | },
236 | {
237 | "inputs": [
238 | {
239 | "internalType": "address",
240 | "name": "delegatee",
241 | "type": "address"
242 | }
243 | ],
244 | "name": "delegate",
245 | "outputs": [],
246 | "stateMutability": "nonpayable",
247 | "type": "function"
248 | },
249 | {
250 | "inputs": [
251 | {
252 | "internalType": "address",
253 | "name": "delegator",
254 | "type": "address"
255 | },
256 | {
257 | "internalType": "address",
258 | "name": "delegatee",
259 | "type": "address"
260 | },
261 | {
262 | "components": [
263 | {
264 | "internalType": "uint8",
265 | "name": "v",
266 | "type": "uint8"
267 | },
268 | {
269 | "internalType": "bytes32",
270 | "name": "r",
271 | "type": "bytes32"
272 | },
273 | {
274 | "internalType": "bytes32",
275 | "name": "s",
276 | "type": "bytes32"
277 | },
278 | {
279 | "internalType": "uint256",
280 | "name": "deadline",
281 | "type": "uint256"
282 | }
283 | ],
284 | "internalType": "struct DataTypes.EIP712Signature",
285 | "name": "sig",
286 | "type": "tuple"
287 | }
288 | ],
289 | "name": "delegateBySig",
290 | "outputs": [],
291 | "stateMutability": "nonpayable",
292 | "type": "function"
293 | },
294 | {
295 | "inputs": [
296 | {
297 | "internalType": "uint256",
298 | "name": "tokenId",
299 | "type": "uint256"
300 | }
301 | ],
302 | "name": "exists",
303 | "outputs": [
304 | {
305 | "internalType": "bool",
306 | "name": "",
307 | "type": "bool"
308 | }
309 | ],
310 | "stateMutability": "view",
311 | "type": "function"
312 | },
313 | {
314 | "inputs": [
315 | {
316 | "internalType": "uint256",
317 | "name": "tokenId",
318 | "type": "uint256"
319 | }
320 | ],
321 | "name": "getApproved",
322 | "outputs": [
323 | {
324 | "internalType": "address",
325 | "name": "",
326 | "type": "address"
327 | }
328 | ],
329 | "stateMutability": "view",
330 | "type": "function"
331 | },
332 | {
333 | "inputs": [
334 | {
335 | "internalType": "uint256",
336 | "name": "blockNumber",
337 | "type": "uint256"
338 | }
339 | ],
340 | "name": "getDelegatedSupplyByBlockNumber",
341 | "outputs": [
342 | {
343 | "internalType": "uint256",
344 | "name": "",
345 | "type": "uint256"
346 | }
347 | ],
348 | "stateMutability": "view",
349 | "type": "function"
350 | },
351 | {
352 | "inputs": [],
353 | "name": "getDomainSeparator",
354 | "outputs": [
355 | {
356 | "internalType": "bytes32",
357 | "name": "",
358 | "type": "bytes32"
359 | }
360 | ],
361 | "stateMutability": "view",
362 | "type": "function"
363 | },
364 | {
365 | "inputs": [
366 | {
367 | "internalType": "address",
368 | "name": "user",
369 | "type": "address"
370 | },
371 | {
372 | "internalType": "uint256",
373 | "name": "blockNumber",
374 | "type": "uint256"
375 | }
376 | ],
377 | "name": "getPowerByBlockNumber",
378 | "outputs": [
379 | {
380 | "internalType": "uint256",
381 | "name": "",
382 | "type": "uint256"
383 | }
384 | ],
385 | "stateMutability": "view",
386 | "type": "function"
387 | },
388 | {
389 | "inputs": [
390 | {
391 | "internalType": "uint256",
392 | "name": "profileId",
393 | "type": "uint256"
394 | }
395 | ],
396 | "name": "initialize",
397 | "outputs": [],
398 | "stateMutability": "nonpayable",
399 | "type": "function"
400 | },
401 | {
402 | "inputs": [
403 | {
404 | "internalType": "address",
405 | "name": "owner",
406 | "type": "address"
407 | },
408 | {
409 | "internalType": "address",
410 | "name": "operator",
411 | "type": "address"
412 | }
413 | ],
414 | "name": "isApprovedForAll",
415 | "outputs": [
416 | {
417 | "internalType": "bool",
418 | "name": "",
419 | "type": "bool"
420 | }
421 | ],
422 | "stateMutability": "view",
423 | "type": "function"
424 | },
425 | {
426 | "inputs": [
427 | {
428 | "internalType": "address",
429 | "name": "to",
430 | "type": "address"
431 | }
432 | ],
433 | "name": "mint",
434 | "outputs": [
435 | {
436 | "internalType": "uint256",
437 | "name": "",
438 | "type": "uint256"
439 | }
440 | ],
441 | "stateMutability": "nonpayable",
442 | "type": "function"
443 | },
444 | {
445 | "inputs": [
446 | {
447 | "internalType": "uint256",
448 | "name": "tokenId",
449 | "type": "uint256"
450 | }
451 | ],
452 | "name": "mintTimestampOf",
453 | "outputs": [
454 | {
455 | "internalType": "uint256",
456 | "name": "",
457 | "type": "uint256"
458 | }
459 | ],
460 | "stateMutability": "view",
461 | "type": "function"
462 | },
463 | {
464 | "inputs": [],
465 | "name": "name",
466 | "outputs": [
467 | {
468 | "internalType": "string",
469 | "name": "",
470 | "type": "string"
471 | }
472 | ],
473 | "stateMutability": "view",
474 | "type": "function"
475 | },
476 | {
477 | "inputs": [
478 | {
479 | "internalType": "uint256",
480 | "name": "tokenId",
481 | "type": "uint256"
482 | }
483 | ],
484 | "name": "ownerOf",
485 | "outputs": [
486 | {
487 | "internalType": "address",
488 | "name": "",
489 | "type": "address"
490 | }
491 | ],
492 | "stateMutability": "view",
493 | "type": "function"
494 | },
495 | {
496 | "inputs": [
497 | {
498 | "internalType": "address",
499 | "name": "spender",
500 | "type": "address"
501 | },
502 | {
503 | "internalType": "uint256",
504 | "name": "tokenId",
505 | "type": "uint256"
506 | },
507 | {
508 | "components": [
509 | {
510 | "internalType": "uint8",
511 | "name": "v",
512 | "type": "uint8"
513 | },
514 | {
515 | "internalType": "bytes32",
516 | "name": "r",
517 | "type": "bytes32"
518 | },
519 | {
520 | "internalType": "bytes32",
521 | "name": "s",
522 | "type": "bytes32"
523 | },
524 | {
525 | "internalType": "uint256",
526 | "name": "deadline",
527 | "type": "uint256"
528 | }
529 | ],
530 | "internalType": "struct DataTypes.EIP712Signature",
531 | "name": "sig",
532 | "type": "tuple"
533 | }
534 | ],
535 | "name": "permit",
536 | "outputs": [],
537 | "stateMutability": "nonpayable",
538 | "type": "function"
539 | },
540 | {
541 | "inputs": [
542 | {
543 | "internalType": "address",
544 | "name": "owner",
545 | "type": "address"
546 | },
547 | {
548 | "internalType": "address",
549 | "name": "operator",
550 | "type": "address"
551 | },
552 | {
553 | "internalType": "bool",
554 | "name": "approved",
555 | "type": "bool"
556 | },
557 | {
558 | "components": [
559 | {
560 | "internalType": "uint8",
561 | "name": "v",
562 | "type": "uint8"
563 | },
564 | {
565 | "internalType": "bytes32",
566 | "name": "r",
567 | "type": "bytes32"
568 | },
569 | {
570 | "internalType": "bytes32",
571 | "name": "s",
572 | "type": "bytes32"
573 | },
574 | {
575 | "internalType": "uint256",
576 | "name": "deadline",
577 | "type": "uint256"
578 | }
579 | ],
580 | "internalType": "struct DataTypes.EIP712Signature",
581 | "name": "sig",
582 | "type": "tuple"
583 | }
584 | ],
585 | "name": "permitForAll",
586 | "outputs": [],
587 | "stateMutability": "nonpayable",
588 | "type": "function"
589 | },
590 | {
591 | "inputs": [
592 | {
593 | "internalType": "address",
594 | "name": "from",
595 | "type": "address"
596 | },
597 | {
598 | "internalType": "address",
599 | "name": "to",
600 | "type": "address"
601 | },
602 | {
603 | "internalType": "uint256",
604 | "name": "tokenId",
605 | "type": "uint256"
606 | }
607 | ],
608 | "name": "safeTransferFrom",
609 | "outputs": [],
610 | "stateMutability": "nonpayable",
611 | "type": "function"
612 | },
613 | {
614 | "inputs": [
615 | {
616 | "internalType": "address",
617 | "name": "from",
618 | "type": "address"
619 | },
620 | {
621 | "internalType": "address",
622 | "name": "to",
623 | "type": "address"
624 | },
625 | {
626 | "internalType": "uint256",
627 | "name": "tokenId",
628 | "type": "uint256"
629 | },
630 | {
631 | "internalType": "bytes",
632 | "name": "_data",
633 | "type": "bytes"
634 | }
635 | ],
636 | "name": "safeTransferFrom",
637 | "outputs": [],
638 | "stateMutability": "nonpayable",
639 | "type": "function"
640 | },
641 | {
642 | "inputs": [
643 | {
644 | "internalType": "address",
645 | "name": "operator",
646 | "type": "address"
647 | },
648 | {
649 | "internalType": "bool",
650 | "name": "approved",
651 | "type": "bool"
652 | }
653 | ],
654 | "name": "setApprovalForAll",
655 | "outputs": [],
656 | "stateMutability": "nonpayable",
657 | "type": "function"
658 | },
659 | {
660 | "inputs": [
661 | {
662 | "internalType": "address",
663 | "name": "",
664 | "type": "address"
665 | }
666 | ],
667 | "name": "sigNonces",
668 | "outputs": [
669 | {
670 | "internalType": "uint256",
671 | "name": "",
672 | "type": "uint256"
673 | }
674 | ],
675 | "stateMutability": "view",
676 | "type": "function"
677 | },
678 | {
679 | "inputs": [
680 | {
681 | "internalType": "bytes4",
682 | "name": "interfaceId",
683 | "type": "bytes4"
684 | }
685 | ],
686 | "name": "supportsInterface",
687 | "outputs": [
688 | {
689 | "internalType": "bool",
690 | "name": "",
691 | "type": "bool"
692 | }
693 | ],
694 | "stateMutability": "view",
695 | "type": "function"
696 | },
697 | {
698 | "inputs": [],
699 | "name": "symbol",
700 | "outputs": [
701 | {
702 | "internalType": "string",
703 | "name": "",
704 | "type": "string"
705 | }
706 | ],
707 | "stateMutability": "view",
708 | "type": "function"
709 | },
710 | {
711 | "inputs": [
712 | {
713 | "internalType": "uint256",
714 | "name": "index",
715 | "type": "uint256"
716 | }
717 | ],
718 | "name": "tokenByIndex",
719 | "outputs": [
720 | {
721 | "internalType": "uint256",
722 | "name": "",
723 | "type": "uint256"
724 | }
725 | ],
726 | "stateMutability": "view",
727 | "type": "function"
728 | },
729 | {
730 | "inputs": [
731 | {
732 | "internalType": "uint256",
733 | "name": "tokenId",
734 | "type": "uint256"
735 | }
736 | ],
737 | "name": "tokenDataOf",
738 | "outputs": [
739 | {
740 | "components": [
741 | {
742 | "internalType": "address",
743 | "name": "owner",
744 | "type": "address"
745 | },
746 | {
747 | "internalType": "uint96",
748 | "name": "mintTimestamp",
749 | "type": "uint96"
750 | }
751 | ],
752 | "internalType": "struct IERC721Time.TokenData",
753 | "name": "",
754 | "type": "tuple"
755 | }
756 | ],
757 | "stateMutability": "view",
758 | "type": "function"
759 | },
760 | {
761 | "inputs": [
762 | {
763 | "internalType": "address",
764 | "name": "owner",
765 | "type": "address"
766 | },
767 | {
768 | "internalType": "uint256",
769 | "name": "index",
770 | "type": "uint256"
771 | }
772 | ],
773 | "name": "tokenOfOwnerByIndex",
774 | "outputs": [
775 | {
776 | "internalType": "uint256",
777 | "name": "",
778 | "type": "uint256"
779 | }
780 | ],
781 | "stateMutability": "view",
782 | "type": "function"
783 | },
784 | {
785 | "inputs": [
786 | {
787 | "internalType": "uint256",
788 | "name": "tokenId",
789 | "type": "uint256"
790 | }
791 | ],
792 | "name": "tokenURI",
793 | "outputs": [
794 | {
795 | "internalType": "string",
796 | "name": "",
797 | "type": "string"
798 | }
799 | ],
800 | "stateMutability": "view",
801 | "type": "function"
802 | },
803 | {
804 | "inputs": [],
805 | "name": "totalSupply",
806 | "outputs": [
807 | {
808 | "internalType": "uint256",
809 | "name": "",
810 | "type": "uint256"
811 | }
812 | ],
813 | "stateMutability": "view",
814 | "type": "function"
815 | },
816 | {
817 | "inputs": [
818 | {
819 | "internalType": "address",
820 | "name": "from",
821 | "type": "address"
822 | },
823 | {
824 | "internalType": "address",
825 | "name": "to",
826 | "type": "address"
827 | },
828 | {
829 | "internalType": "uint256",
830 | "name": "tokenId",
831 | "type": "uint256"
832 | }
833 | ],
834 | "name": "transferFrom",
835 | "outputs": [],
836 | "stateMutability": "nonpayable",
837 | "type": "function"
838 | }
839 | ]
840 |
--------------------------------------------------------------------------------
/src/assets/abi/lenshub.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | { "internalType": "address", "name": "followNFTImpl", "type": "address" },
5 | { "internalType": "address", "name": "collectNFTImpl", "type": "address" }
6 | ],
7 | "stateMutability": "nonpayable",
8 | "type": "constructor"
9 | },
10 | { "inputs": [], "name": "CallerNotCollectNFT", "type": "error" },
11 | { "inputs": [], "name": "CallerNotFollowNFT", "type": "error" },
12 | { "inputs": [], "name": "CannotInitImplementation", "type": "error" },
13 | { "inputs": [], "name": "EmergencyAdminCannotUnpause", "type": "error" },
14 | { "inputs": [], "name": "InitParamsInvalid", "type": "error" },
15 | { "inputs": [], "name": "Initialized", "type": "error" },
16 | { "inputs": [], "name": "NotGovernance", "type": "error" },
17 | { "inputs": [], "name": "NotGovernanceOrEmergencyAdmin", "type": "error" },
18 | { "inputs": [], "name": "NotOwnerOrApproved", "type": "error" },
19 | { "inputs": [], "name": "NotProfileOwner", "type": "error" },
20 | { "inputs": [], "name": "NotProfileOwnerOrDispatcher", "type": "error" },
21 | { "inputs": [], "name": "Paused", "type": "error" },
22 | { "inputs": [], "name": "ProfileCreatorNotWhitelisted", "type": "error" },
23 | { "inputs": [], "name": "ProfileImageURILengthInvalid", "type": "error" },
24 | { "inputs": [], "name": "PublicationDoesNotExist", "type": "error" },
25 | { "inputs": [], "name": "PublishingPaused", "type": "error" },
26 | { "inputs": [], "name": "SignatureExpired", "type": "error" },
27 | { "inputs": [], "name": "SignatureInvalid", "type": "error" },
28 | { "inputs": [], "name": "ZeroSpender", "type": "error" },
29 | {
30 | "anonymous": false,
31 | "inputs": [
32 | { "indexed": true, "internalType": "address", "name": "owner", "type": "address" },
33 | { "indexed": true, "internalType": "address", "name": "approved", "type": "address" },
34 | { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }
35 | ],
36 | "name": "Approval",
37 | "type": "event"
38 | },
39 | {
40 | "anonymous": false,
41 | "inputs": [
42 | { "indexed": true, "internalType": "address", "name": "owner", "type": "address" },
43 | { "indexed": true, "internalType": "address", "name": "operator", "type": "address" },
44 | { "indexed": false, "internalType": "bool", "name": "approved", "type": "bool" }
45 | ],
46 | "name": "ApprovalForAll",
47 | "type": "event"
48 | },
49 | {
50 | "anonymous": false,
51 | "inputs": [
52 | { "indexed": true, "internalType": "address", "name": "from", "type": "address" },
53 | { "indexed": true, "internalType": "address", "name": "to", "type": "address" },
54 | { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }
55 | ],
56 | "name": "Transfer",
57 | "type": "event"
58 | },
59 | {
60 | "inputs": [
61 | { "internalType": "address", "name": "to", "type": "address" },
62 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
63 | ],
64 | "name": "approve",
65 | "outputs": [],
66 | "stateMutability": "nonpayable",
67 | "type": "function"
68 | },
69 | {
70 | "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }],
71 | "name": "balanceOf",
72 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
73 | "stateMutability": "view",
74 | "type": "function"
75 | },
76 | {
77 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
78 | "name": "burn",
79 | "outputs": [],
80 | "stateMutability": "nonpayable",
81 | "type": "function"
82 | },
83 | {
84 | "inputs": [
85 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
86 | {
87 | "components": [
88 | { "internalType": "uint8", "name": "v", "type": "uint8" },
89 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
90 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
91 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
92 | ],
93 | "internalType": "struct DataTypes.EIP712Signature",
94 | "name": "sig",
95 | "type": "tuple"
96 | }
97 | ],
98 | "name": "burnWithSig",
99 | "outputs": [],
100 | "stateMutability": "nonpayable",
101 | "type": "function"
102 | },
103 | {
104 | "inputs": [
105 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
106 | { "internalType": "uint256", "name": "pubId", "type": "uint256" },
107 | { "internalType": "bytes", "name": "data", "type": "bytes" }
108 | ],
109 | "name": "collect",
110 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
111 | "stateMutability": "nonpayable",
112 | "type": "function"
113 | },
114 | {
115 | "inputs": [
116 | {
117 | "components": [
118 | { "internalType": "address", "name": "collector", "type": "address" },
119 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
120 | { "internalType": "uint256", "name": "pubId", "type": "uint256" },
121 | { "internalType": "bytes", "name": "data", "type": "bytes" },
122 | {
123 | "components": [
124 | { "internalType": "uint8", "name": "v", "type": "uint8" },
125 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
126 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
127 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
128 | ],
129 | "internalType": "struct DataTypes.EIP712Signature",
130 | "name": "sig",
131 | "type": "tuple"
132 | }
133 | ],
134 | "internalType": "struct DataTypes.CollectWithSigData",
135 | "name": "vars",
136 | "type": "tuple"
137 | }
138 | ],
139 | "name": "collectWithSig",
140 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
141 | "stateMutability": "nonpayable",
142 | "type": "function"
143 | },
144 | {
145 | "inputs": [
146 | {
147 | "components": [
148 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
149 | { "internalType": "string", "name": "contentURI", "type": "string" },
150 | { "internalType": "uint256", "name": "profileIdPointed", "type": "uint256" },
151 | { "internalType": "uint256", "name": "pubIdPointed", "type": "uint256" },
152 | { "internalType": "bytes", "name": "referenceModuleData", "type": "bytes" },
153 | { "internalType": "address", "name": "collectModule", "type": "address" },
154 | { "internalType": "bytes", "name": "collectModuleInitData", "type": "bytes" },
155 | { "internalType": "address", "name": "referenceModule", "type": "address" },
156 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" }
157 | ],
158 | "internalType": "struct DataTypes.CommentData",
159 | "name": "vars",
160 | "type": "tuple"
161 | }
162 | ],
163 | "name": "comment",
164 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
165 | "stateMutability": "nonpayable",
166 | "type": "function"
167 | },
168 | {
169 | "inputs": [
170 | {
171 | "components": [
172 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
173 | { "internalType": "string", "name": "contentURI", "type": "string" },
174 | { "internalType": "uint256", "name": "profileIdPointed", "type": "uint256" },
175 | { "internalType": "uint256", "name": "pubIdPointed", "type": "uint256" },
176 | { "internalType": "bytes", "name": "referenceModuleData", "type": "bytes" },
177 | { "internalType": "address", "name": "collectModule", "type": "address" },
178 | { "internalType": "bytes", "name": "collectModuleInitData", "type": "bytes" },
179 | { "internalType": "address", "name": "referenceModule", "type": "address" },
180 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" },
181 | {
182 | "components": [
183 | { "internalType": "uint8", "name": "v", "type": "uint8" },
184 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
185 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
186 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
187 | ],
188 | "internalType": "struct DataTypes.EIP712Signature",
189 | "name": "sig",
190 | "type": "tuple"
191 | }
192 | ],
193 | "internalType": "struct DataTypes.CommentWithSigData",
194 | "name": "vars",
195 | "type": "tuple"
196 | }
197 | ],
198 | "name": "commentWithSig",
199 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
200 | "stateMutability": "nonpayable",
201 | "type": "function"
202 | },
203 | {
204 | "inputs": [
205 | {
206 | "components": [
207 | { "internalType": "address", "name": "to", "type": "address" },
208 | { "internalType": "string", "name": "handle", "type": "string" },
209 | { "internalType": "string", "name": "imageURI", "type": "string" },
210 | { "internalType": "address", "name": "followModule", "type": "address" },
211 | { "internalType": "bytes", "name": "followModuleInitData", "type": "bytes" },
212 | { "internalType": "string", "name": "followNFTURI", "type": "string" }
213 | ],
214 | "internalType": "struct DataTypes.CreateProfileData",
215 | "name": "vars",
216 | "type": "tuple"
217 | }
218 | ],
219 | "name": "createProfile",
220 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
221 | "stateMutability": "nonpayable",
222 | "type": "function"
223 | },
224 | {
225 | "inputs": [{ "internalType": "address", "name": "wallet", "type": "address" }],
226 | "name": "defaultProfile",
227 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
228 | "stateMutability": "view",
229 | "type": "function"
230 | },
231 | {
232 | "inputs": [
233 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
234 | { "internalType": "uint256", "name": "pubId", "type": "uint256" },
235 | { "internalType": "uint256", "name": "collectNFTId", "type": "uint256" },
236 | { "internalType": "address", "name": "from", "type": "address" },
237 | { "internalType": "address", "name": "to", "type": "address" }
238 | ],
239 | "name": "emitCollectNFTTransferEvent",
240 | "outputs": [],
241 | "stateMutability": "nonpayable",
242 | "type": "function"
243 | },
244 | {
245 | "inputs": [
246 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
247 | { "internalType": "uint256", "name": "followNFTId", "type": "uint256" },
248 | { "internalType": "address", "name": "from", "type": "address" },
249 | { "internalType": "address", "name": "to", "type": "address" }
250 | ],
251 | "name": "emitFollowNFTTransferEvent",
252 | "outputs": [],
253 | "stateMutability": "nonpayable",
254 | "type": "function"
255 | },
256 | {
257 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
258 | "name": "exists",
259 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
260 | "stateMutability": "view",
261 | "type": "function"
262 | },
263 | {
264 | "inputs": [
265 | { "internalType": "uint256[]", "name": "profileIds", "type": "uint256[]" },
266 | { "internalType": "bytes[]", "name": "datas", "type": "bytes[]" }
267 | ],
268 | "name": "follow",
269 | "outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }],
270 | "stateMutability": "nonpayable",
271 | "type": "function"
272 | },
273 | {
274 | "inputs": [
275 | {
276 | "components": [
277 | { "internalType": "address", "name": "follower", "type": "address" },
278 | { "internalType": "uint256[]", "name": "profileIds", "type": "uint256[]" },
279 | { "internalType": "bytes[]", "name": "datas", "type": "bytes[]" },
280 | {
281 | "components": [
282 | { "internalType": "uint8", "name": "v", "type": "uint8" },
283 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
284 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
285 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
286 | ],
287 | "internalType": "struct DataTypes.EIP712Signature",
288 | "name": "sig",
289 | "type": "tuple"
290 | }
291 | ],
292 | "internalType": "struct DataTypes.FollowWithSigData",
293 | "name": "vars",
294 | "type": "tuple"
295 | }
296 | ],
297 | "name": "followWithSig",
298 | "outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }],
299 | "stateMutability": "nonpayable",
300 | "type": "function"
301 | },
302 | {
303 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
304 | "name": "getApproved",
305 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
306 | "stateMutability": "view",
307 | "type": "function"
308 | },
309 | {
310 | "inputs": [
311 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
312 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
313 | ],
314 | "name": "getCollectModule",
315 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
316 | "stateMutability": "view",
317 | "type": "function"
318 | },
319 | {
320 | "inputs": [
321 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
322 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
323 | ],
324 | "name": "getCollectNFT",
325 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
326 | "stateMutability": "view",
327 | "type": "function"
328 | },
329 | {
330 | "inputs": [],
331 | "name": "getCollectNFTImpl",
332 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
333 | "stateMutability": "view",
334 | "type": "function"
335 | },
336 | {
337 | "inputs": [
338 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
339 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
340 | ],
341 | "name": "getContentURI",
342 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
343 | "stateMutability": "view",
344 | "type": "function"
345 | },
346 | {
347 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
348 | "name": "getDispatcher",
349 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
350 | "stateMutability": "view",
351 | "type": "function"
352 | },
353 | {
354 | "inputs": [],
355 | "name": "getDomainSeparator",
356 | "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }],
357 | "stateMutability": "view",
358 | "type": "function"
359 | },
360 | {
361 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
362 | "name": "getFollowModule",
363 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
364 | "stateMutability": "view",
365 | "type": "function"
366 | },
367 | {
368 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
369 | "name": "getFollowNFT",
370 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
371 | "stateMutability": "view",
372 | "type": "function"
373 | },
374 | {
375 | "inputs": [],
376 | "name": "getFollowNFTImpl",
377 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
378 | "stateMutability": "view",
379 | "type": "function"
380 | },
381 | {
382 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
383 | "name": "getFollowNFTURI",
384 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
385 | "stateMutability": "view",
386 | "type": "function"
387 | },
388 | {
389 | "inputs": [],
390 | "name": "getGovernance",
391 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
392 | "stateMutability": "view",
393 | "type": "function"
394 | },
395 | {
396 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
397 | "name": "getHandle",
398 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
399 | "stateMutability": "view",
400 | "type": "function"
401 | },
402 | {
403 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
404 | "name": "getProfile",
405 | "outputs": [
406 | {
407 | "components": [
408 | { "internalType": "uint256", "name": "pubCount", "type": "uint256" },
409 | { "internalType": "address", "name": "followModule", "type": "address" },
410 | { "internalType": "address", "name": "followNFT", "type": "address" },
411 | { "internalType": "string", "name": "handle", "type": "string" },
412 | { "internalType": "string", "name": "imageURI", "type": "string" },
413 | { "internalType": "string", "name": "followNFTURI", "type": "string" }
414 | ],
415 | "internalType": "struct DataTypes.ProfileStruct",
416 | "name": "",
417 | "type": "tuple"
418 | }
419 | ],
420 | "stateMutability": "view",
421 | "type": "function"
422 | },
423 | {
424 | "inputs": [{ "internalType": "string", "name": "handle", "type": "string" }],
425 | "name": "getProfileIdByHandle",
426 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
427 | "stateMutability": "view",
428 | "type": "function"
429 | },
430 | {
431 | "inputs": [
432 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
433 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
434 | ],
435 | "name": "getPub",
436 | "outputs": [
437 | {
438 | "components": [
439 | { "internalType": "uint256", "name": "profileIdPointed", "type": "uint256" },
440 | { "internalType": "uint256", "name": "pubIdPointed", "type": "uint256" },
441 | { "internalType": "string", "name": "contentURI", "type": "string" },
442 | { "internalType": "address", "name": "referenceModule", "type": "address" },
443 | { "internalType": "address", "name": "collectModule", "type": "address" },
444 | { "internalType": "address", "name": "collectNFT", "type": "address" }
445 | ],
446 | "internalType": "struct DataTypes.PublicationStruct",
447 | "name": "",
448 | "type": "tuple"
449 | }
450 | ],
451 | "stateMutability": "view",
452 | "type": "function"
453 | },
454 | {
455 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
456 | "name": "getPubCount",
457 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
458 | "stateMutability": "view",
459 | "type": "function"
460 | },
461 | {
462 | "inputs": [
463 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
464 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
465 | ],
466 | "name": "getPubPointer",
467 | "outputs": [
468 | { "internalType": "uint256", "name": "", "type": "uint256" },
469 | { "internalType": "uint256", "name": "", "type": "uint256" }
470 | ],
471 | "stateMutability": "view",
472 | "type": "function"
473 | },
474 | {
475 | "inputs": [
476 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
477 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
478 | ],
479 | "name": "getPubType",
480 | "outputs": [{ "internalType": "enum DataTypes.PubType", "name": "", "type": "uint8" }],
481 | "stateMutability": "view",
482 | "type": "function"
483 | },
484 | {
485 | "inputs": [
486 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
487 | { "internalType": "uint256", "name": "pubId", "type": "uint256" }
488 | ],
489 | "name": "getReferenceModule",
490 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
491 | "stateMutability": "view",
492 | "type": "function"
493 | },
494 | {
495 | "inputs": [],
496 | "name": "getState",
497 | "outputs": [{ "internalType": "enum DataTypes.ProtocolState", "name": "", "type": "uint8" }],
498 | "stateMutability": "view",
499 | "type": "function"
500 | },
501 | {
502 | "inputs": [
503 | { "internalType": "string", "name": "name", "type": "string" },
504 | { "internalType": "string", "name": "symbol", "type": "string" },
505 | { "internalType": "address", "name": "newGovernance", "type": "address" }
506 | ],
507 | "name": "initialize",
508 | "outputs": [],
509 | "stateMutability": "nonpayable",
510 | "type": "function"
511 | },
512 | {
513 | "inputs": [
514 | { "internalType": "address", "name": "owner", "type": "address" },
515 | { "internalType": "address", "name": "operator", "type": "address" }
516 | ],
517 | "name": "isApprovedForAll",
518 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
519 | "stateMutability": "view",
520 | "type": "function"
521 | },
522 | {
523 | "inputs": [{ "internalType": "address", "name": "collectModule", "type": "address" }],
524 | "name": "isCollectModuleWhitelisted",
525 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
526 | "stateMutability": "view",
527 | "type": "function"
528 | },
529 | {
530 | "inputs": [{ "internalType": "address", "name": "followModule", "type": "address" }],
531 | "name": "isFollowModuleWhitelisted",
532 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
533 | "stateMutability": "view",
534 | "type": "function"
535 | },
536 | {
537 | "inputs": [{ "internalType": "address", "name": "profileCreator", "type": "address" }],
538 | "name": "isProfileCreatorWhitelisted",
539 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
540 | "stateMutability": "view",
541 | "type": "function"
542 | },
543 | {
544 | "inputs": [{ "internalType": "address", "name": "referenceModule", "type": "address" }],
545 | "name": "isReferenceModuleWhitelisted",
546 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
547 | "stateMutability": "view",
548 | "type": "function"
549 | },
550 | {
551 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
552 | "name": "mintTimestampOf",
553 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
554 | "stateMutability": "view",
555 | "type": "function"
556 | },
557 | {
558 | "inputs": [
559 | {
560 | "components": [
561 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
562 | { "internalType": "uint256", "name": "profileIdPointed", "type": "uint256" },
563 | { "internalType": "uint256", "name": "pubIdPointed", "type": "uint256" },
564 | { "internalType": "bytes", "name": "referenceModuleData", "type": "bytes" },
565 | { "internalType": "address", "name": "referenceModule", "type": "address" },
566 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" }
567 | ],
568 | "internalType": "struct DataTypes.MirrorData",
569 | "name": "vars",
570 | "type": "tuple"
571 | }
572 | ],
573 | "name": "mirror",
574 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
575 | "stateMutability": "nonpayable",
576 | "type": "function"
577 | },
578 | {
579 | "inputs": [
580 | {
581 | "components": [
582 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
583 | { "internalType": "uint256", "name": "profileIdPointed", "type": "uint256" },
584 | { "internalType": "uint256", "name": "pubIdPointed", "type": "uint256" },
585 | { "internalType": "bytes", "name": "referenceModuleData", "type": "bytes" },
586 | { "internalType": "address", "name": "referenceModule", "type": "address" },
587 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" },
588 | {
589 | "components": [
590 | { "internalType": "uint8", "name": "v", "type": "uint8" },
591 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
592 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
593 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
594 | ],
595 | "internalType": "struct DataTypes.EIP712Signature",
596 | "name": "sig",
597 | "type": "tuple"
598 | }
599 | ],
600 | "internalType": "struct DataTypes.MirrorWithSigData",
601 | "name": "vars",
602 | "type": "tuple"
603 | }
604 | ],
605 | "name": "mirrorWithSig",
606 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
607 | "stateMutability": "nonpayable",
608 | "type": "function"
609 | },
610 | {
611 | "inputs": [],
612 | "name": "name",
613 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
614 | "stateMutability": "view",
615 | "type": "function"
616 | },
617 | {
618 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
619 | "name": "ownerOf",
620 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
621 | "stateMutability": "view",
622 | "type": "function"
623 | },
624 | {
625 | "inputs": [
626 | { "internalType": "address", "name": "spender", "type": "address" },
627 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
628 | {
629 | "components": [
630 | { "internalType": "uint8", "name": "v", "type": "uint8" },
631 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
632 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
633 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
634 | ],
635 | "internalType": "struct DataTypes.EIP712Signature",
636 | "name": "sig",
637 | "type": "tuple"
638 | }
639 | ],
640 | "name": "permit",
641 | "outputs": [],
642 | "stateMutability": "nonpayable",
643 | "type": "function"
644 | },
645 | {
646 | "inputs": [
647 | { "internalType": "address", "name": "owner", "type": "address" },
648 | { "internalType": "address", "name": "operator", "type": "address" },
649 | { "internalType": "bool", "name": "approved", "type": "bool" },
650 | {
651 | "components": [
652 | { "internalType": "uint8", "name": "v", "type": "uint8" },
653 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
654 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
655 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
656 | ],
657 | "internalType": "struct DataTypes.EIP712Signature",
658 | "name": "sig",
659 | "type": "tuple"
660 | }
661 | ],
662 | "name": "permitForAll",
663 | "outputs": [],
664 | "stateMutability": "nonpayable",
665 | "type": "function"
666 | },
667 | {
668 | "inputs": [
669 | {
670 | "components": [
671 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
672 | { "internalType": "string", "name": "contentURI", "type": "string" },
673 | { "internalType": "address", "name": "collectModule", "type": "address" },
674 | { "internalType": "bytes", "name": "collectModuleInitData", "type": "bytes" },
675 | { "internalType": "address", "name": "referenceModule", "type": "address" },
676 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" }
677 | ],
678 | "internalType": "struct DataTypes.PostData",
679 | "name": "vars",
680 | "type": "tuple"
681 | }
682 | ],
683 | "name": "post",
684 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
685 | "stateMutability": "nonpayable",
686 | "type": "function"
687 | },
688 | {
689 | "inputs": [
690 | {
691 | "components": [
692 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
693 | { "internalType": "string", "name": "contentURI", "type": "string" },
694 | { "internalType": "address", "name": "collectModule", "type": "address" },
695 | { "internalType": "bytes", "name": "collectModuleInitData", "type": "bytes" },
696 | { "internalType": "address", "name": "referenceModule", "type": "address" },
697 | { "internalType": "bytes", "name": "referenceModuleInitData", "type": "bytes" },
698 | {
699 | "components": [
700 | { "internalType": "uint8", "name": "v", "type": "uint8" },
701 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
702 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
703 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
704 | ],
705 | "internalType": "struct DataTypes.EIP712Signature",
706 | "name": "sig",
707 | "type": "tuple"
708 | }
709 | ],
710 | "internalType": "struct DataTypes.PostWithSigData",
711 | "name": "vars",
712 | "type": "tuple"
713 | }
714 | ],
715 | "name": "postWithSig",
716 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
717 | "stateMutability": "nonpayable",
718 | "type": "function"
719 | },
720 | {
721 | "inputs": [
722 | { "internalType": "address", "name": "from", "type": "address" },
723 | { "internalType": "address", "name": "to", "type": "address" },
724 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
725 | ],
726 | "name": "safeTransferFrom",
727 | "outputs": [],
728 | "stateMutability": "nonpayable",
729 | "type": "function"
730 | },
731 | {
732 | "inputs": [
733 | { "internalType": "address", "name": "from", "type": "address" },
734 | { "internalType": "address", "name": "to", "type": "address" },
735 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
736 | { "internalType": "bytes", "name": "_data", "type": "bytes" }
737 | ],
738 | "name": "safeTransferFrom",
739 | "outputs": [],
740 | "stateMutability": "nonpayable",
741 | "type": "function"
742 | },
743 | {
744 | "inputs": [
745 | { "internalType": "address", "name": "operator", "type": "address" },
746 | { "internalType": "bool", "name": "approved", "type": "bool" }
747 | ],
748 | "name": "setApprovalForAll",
749 | "outputs": [],
750 | "stateMutability": "nonpayable",
751 | "type": "function"
752 | },
753 | {
754 | "inputs": [{ "internalType": "uint256", "name": "profileId", "type": "uint256" }],
755 | "name": "setDefaultProfile",
756 | "outputs": [],
757 | "stateMutability": "nonpayable",
758 | "type": "function"
759 | },
760 | {
761 | "inputs": [
762 | {
763 | "components": [
764 | { "internalType": "address", "name": "wallet", "type": "address" },
765 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
766 | {
767 | "components": [
768 | { "internalType": "uint8", "name": "v", "type": "uint8" },
769 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
770 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
771 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
772 | ],
773 | "internalType": "struct DataTypes.EIP712Signature",
774 | "name": "sig",
775 | "type": "tuple"
776 | }
777 | ],
778 | "internalType": "struct DataTypes.SetDefaultProfileWithSigData",
779 | "name": "vars",
780 | "type": "tuple"
781 | }
782 | ],
783 | "name": "setDefaultProfileWithSig",
784 | "outputs": [],
785 | "stateMutability": "nonpayable",
786 | "type": "function"
787 | },
788 | {
789 | "inputs": [
790 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
791 | { "internalType": "address", "name": "dispatcher", "type": "address" }
792 | ],
793 | "name": "setDispatcher",
794 | "outputs": [],
795 | "stateMutability": "nonpayable",
796 | "type": "function"
797 | },
798 | {
799 | "inputs": [
800 | {
801 | "components": [
802 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
803 | { "internalType": "address", "name": "dispatcher", "type": "address" },
804 | {
805 | "components": [
806 | { "internalType": "uint8", "name": "v", "type": "uint8" },
807 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
808 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
809 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
810 | ],
811 | "internalType": "struct DataTypes.EIP712Signature",
812 | "name": "sig",
813 | "type": "tuple"
814 | }
815 | ],
816 | "internalType": "struct DataTypes.SetDispatcherWithSigData",
817 | "name": "vars",
818 | "type": "tuple"
819 | }
820 | ],
821 | "name": "setDispatcherWithSig",
822 | "outputs": [],
823 | "stateMutability": "nonpayable",
824 | "type": "function"
825 | },
826 | {
827 | "inputs": [{ "internalType": "address", "name": "newEmergencyAdmin", "type": "address" }],
828 | "name": "setEmergencyAdmin",
829 | "outputs": [],
830 | "stateMutability": "nonpayable",
831 | "type": "function"
832 | },
833 | {
834 | "inputs": [
835 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
836 | { "internalType": "address", "name": "followModule", "type": "address" },
837 | { "internalType": "bytes", "name": "followModuleInitData", "type": "bytes" }
838 | ],
839 | "name": "setFollowModule",
840 | "outputs": [],
841 | "stateMutability": "nonpayable",
842 | "type": "function"
843 | },
844 | {
845 | "inputs": [
846 | {
847 | "components": [
848 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
849 | { "internalType": "address", "name": "followModule", "type": "address" },
850 | { "internalType": "bytes", "name": "followModuleInitData", "type": "bytes" },
851 | {
852 | "components": [
853 | { "internalType": "uint8", "name": "v", "type": "uint8" },
854 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
855 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
856 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
857 | ],
858 | "internalType": "struct DataTypes.EIP712Signature",
859 | "name": "sig",
860 | "type": "tuple"
861 | }
862 | ],
863 | "internalType": "struct DataTypes.SetFollowModuleWithSigData",
864 | "name": "vars",
865 | "type": "tuple"
866 | }
867 | ],
868 | "name": "setFollowModuleWithSig",
869 | "outputs": [],
870 | "stateMutability": "nonpayable",
871 | "type": "function"
872 | },
873 | {
874 | "inputs": [
875 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
876 | { "internalType": "string", "name": "followNFTURI", "type": "string" }
877 | ],
878 | "name": "setFollowNFTURI",
879 | "outputs": [],
880 | "stateMutability": "nonpayable",
881 | "type": "function"
882 | },
883 | {
884 | "inputs": [
885 | {
886 | "components": [
887 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
888 | { "internalType": "string", "name": "followNFTURI", "type": "string" },
889 | {
890 | "components": [
891 | { "internalType": "uint8", "name": "v", "type": "uint8" },
892 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
893 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
894 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
895 | ],
896 | "internalType": "struct DataTypes.EIP712Signature",
897 | "name": "sig",
898 | "type": "tuple"
899 | }
900 | ],
901 | "internalType": "struct DataTypes.SetFollowNFTURIWithSigData",
902 | "name": "vars",
903 | "type": "tuple"
904 | }
905 | ],
906 | "name": "setFollowNFTURIWithSig",
907 | "outputs": [],
908 | "stateMutability": "nonpayable",
909 | "type": "function"
910 | },
911 | {
912 | "inputs": [{ "internalType": "address", "name": "newGovernance", "type": "address" }],
913 | "name": "setGovernance",
914 | "outputs": [],
915 | "stateMutability": "nonpayable",
916 | "type": "function"
917 | },
918 | {
919 | "inputs": [
920 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
921 | { "internalType": "string", "name": "imageURI", "type": "string" }
922 | ],
923 | "name": "setProfileImageURI",
924 | "outputs": [],
925 | "stateMutability": "nonpayable",
926 | "type": "function"
927 | },
928 | {
929 | "inputs": [
930 | {
931 | "components": [
932 | { "internalType": "uint256", "name": "profileId", "type": "uint256" },
933 | { "internalType": "string", "name": "imageURI", "type": "string" },
934 | {
935 | "components": [
936 | { "internalType": "uint8", "name": "v", "type": "uint8" },
937 | { "internalType": "bytes32", "name": "r", "type": "bytes32" },
938 | { "internalType": "bytes32", "name": "s", "type": "bytes32" },
939 | { "internalType": "uint256", "name": "deadline", "type": "uint256" }
940 | ],
941 | "internalType": "struct DataTypes.EIP712Signature",
942 | "name": "sig",
943 | "type": "tuple"
944 | }
945 | ],
946 | "internalType": "struct DataTypes.SetProfileImageURIWithSigData",
947 | "name": "vars",
948 | "type": "tuple"
949 | }
950 | ],
951 | "name": "setProfileImageURIWithSig",
952 | "outputs": [],
953 | "stateMutability": "nonpayable",
954 | "type": "function"
955 | },
956 | {
957 | "inputs": [{ "internalType": "enum DataTypes.ProtocolState", "name": "newState", "type": "uint8" }],
958 | "name": "setState",
959 | "outputs": [],
960 | "stateMutability": "nonpayable",
961 | "type": "function"
962 | },
963 | {
964 | "inputs": [{ "internalType": "address", "name": "", "type": "address" }],
965 | "name": "sigNonces",
966 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
967 | "stateMutability": "view",
968 | "type": "function"
969 | },
970 | {
971 | "inputs": [{ "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" }],
972 | "name": "supportsInterface",
973 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
974 | "stateMutability": "view",
975 | "type": "function"
976 | },
977 | {
978 | "inputs": [],
979 | "name": "symbol",
980 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
981 | "stateMutability": "view",
982 | "type": "function"
983 | },
984 | {
985 | "inputs": [{ "internalType": "uint256", "name": "index", "type": "uint256" }],
986 | "name": "tokenByIndex",
987 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
988 | "stateMutability": "view",
989 | "type": "function"
990 | },
991 | {
992 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
993 | "name": "tokenDataOf",
994 | "outputs": [
995 | {
996 | "components": [
997 | { "internalType": "address", "name": "owner", "type": "address" },
998 | { "internalType": "uint96", "name": "mintTimestamp", "type": "uint96" }
999 | ],
1000 | "internalType": "struct IERC721Time.TokenData",
1001 | "name": "",
1002 | "type": "tuple"
1003 | }
1004 | ],
1005 | "stateMutability": "view",
1006 | "type": "function"
1007 | },
1008 | {
1009 | "inputs": [
1010 | { "internalType": "address", "name": "owner", "type": "address" },
1011 | { "internalType": "uint256", "name": "index", "type": "uint256" }
1012 | ],
1013 | "name": "tokenOfOwnerByIndex",
1014 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
1015 | "stateMutability": "view",
1016 | "type": "function"
1017 | },
1018 | {
1019 | "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }],
1020 | "name": "tokenURI",
1021 | "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
1022 | "stateMutability": "view",
1023 | "type": "function"
1024 | },
1025 | {
1026 | "inputs": [],
1027 | "name": "totalSupply",
1028 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
1029 | "stateMutability": "view",
1030 | "type": "function"
1031 | },
1032 | {
1033 | "inputs": [
1034 | { "internalType": "address", "name": "from", "type": "address" },
1035 | { "internalType": "address", "name": "to", "type": "address" },
1036 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
1037 | ],
1038 | "name": "transferFrom",
1039 | "outputs": [],
1040 | "stateMutability": "nonpayable",
1041 | "type": "function"
1042 | },
1043 | {
1044 | "inputs": [
1045 | { "internalType": "address", "name": "collectModule", "type": "address" },
1046 | { "internalType": "bool", "name": "whitelist", "type": "bool" }
1047 | ],
1048 | "name": "whitelistCollectModule",
1049 | "outputs": [],
1050 | "stateMutability": "nonpayable",
1051 | "type": "function"
1052 | },
1053 | {
1054 | "inputs": [
1055 | { "internalType": "address", "name": "followModule", "type": "address" },
1056 | { "internalType": "bool", "name": "whitelist", "type": "bool" }
1057 | ],
1058 | "name": "whitelistFollowModule",
1059 | "outputs": [],
1060 | "stateMutability": "nonpayable",
1061 | "type": "function"
1062 | },
1063 | {
1064 | "inputs": [
1065 | { "internalType": "address", "name": "profileCreator", "type": "address" },
1066 | { "internalType": "bool", "name": "whitelist", "type": "bool" }
1067 | ],
1068 | "name": "whitelistProfileCreator",
1069 | "outputs": [],
1070 | "stateMutability": "nonpayable",
1071 | "type": "function"
1072 | },
1073 | {
1074 | "inputs": [
1075 | { "internalType": "address", "name": "referenceModule", "type": "address" },
1076 | { "internalType": "bool", "name": "whitelist", "type": "bool" }
1077 | ],
1078 | "name": "whitelistReferenceModule",
1079 | "outputs": [],
1080 | "stateMutability": "nonpayable",
1081 | "type": "function"
1082 | }
1083 | ]
1084 |
--------------------------------------------------------------------------------
/src/context/LensContext.tsx:
--------------------------------------------------------------------------------
1 | import { createContext, useContext, useMemo } from "react";
2 |
3 | interface LensStorage {
4 | lensHubAddress?: string;
5 | network?: "mainnet" | "testnet";
6 | }
7 |
8 | const LensContext = createContext({
9 | lensHubAddress: undefined,
10 | network: "mainnet",
11 | });
12 |
13 | export interface LensProviderProps {
14 | lensHubAddress?: string;
15 | network?: "mainnet" | "testnet";
16 | }
17 |
18 | function LensProvider({ children, lensHubAddress, network }: React.PropsWithChildren): JSX.Element {
19 | const contextValue = useMemo(() => {
20 | return { lensHubAddress, network };
21 | }, [lensHubAddress, network]);
22 |
23 | return {children};
24 | }
25 |
26 | const useLensHubAddress = (): string => {
27 | const context = useContext(LensContext);
28 |
29 | if (context?.lensHubAddress) {
30 | return context.lensHubAddress;
31 | }
32 |
33 | if (context?.network === "testnet") {
34 | return "0x60Ae865ee4C725cd04353b5AAb364553f56ceF82";
35 | }
36 |
37 | return "0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d";
38 | };
39 |
40 | export { LensContext, LensProvider, useLensHubAddress };
41 |
--------------------------------------------------------------------------------
/src/hooks/api/broadcast.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { RelayErrorReasons } from "../../types/error";
4 |
5 | interface BroadcastRequest {
6 | request: {
7 | id?: string;
8 | signature?: string;
9 | };
10 | }
11 |
12 | export interface SuccessfulBroadcast {
13 | txId: string;
14 | txHash: string;
15 | }
16 | export interface FailedBroadcast {
17 | reason: RelayErrorReasons;
18 | }
19 |
20 | export const wasSuccessfulBroadcast = (
21 | broadcast: SuccessfulBroadcast | FailedBroadcast,
22 | ): broadcast is SuccessfulBroadcast => (broadcast as SuccessfulBroadcast).txId !== undefined;
23 |
24 | export const wasFailedBroadcast = (broadcast: SuccessfulBroadcast | FailedBroadcast): broadcast is FailedBroadcast =>
25 | (broadcast as FailedBroadcast).reason !== undefined;
26 |
27 | // more: https://docs.lens.xyz/docs/broadcast-transaction
28 | interface BroadcastResponse {
29 | broadcast: SuccessfulBroadcast | FailedBroadcast;
30 | }
31 |
32 | const BROADCAST = gql`
33 | mutation Broadcast($request: BroadcastRequest!) {
34 | broadcast(request: $request) {
35 | ... on RelayerResult {
36 | txHash
37 | txId
38 | }
39 | ... on RelayError {
40 | reason
41 | }
42 | }
43 | }
44 | `;
45 |
46 | export const useBroadcast = (id?: string, signature?: string): MutationTuple => {
47 | return useMutation(BROADCAST, {
48 | variables: {
49 | request: {
50 | id,
51 | signature,
52 | },
53 | },
54 | });
55 | };
56 |
--------------------------------------------------------------------------------
/src/hooks/api/collect.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { TypedDataResponse } from "../../types/lens";
4 |
5 | interface CollectRequest {
6 | request: {
7 | publicationId?: string;
8 | };
9 | }
10 |
11 | // more: https://docs.lens.xyz/docs/create-collected-typed-data
12 | interface CollectResponse {
13 | createCollectTypedData: TypedDataResponse;
14 | }
15 |
16 | const COLLECT = gql`
17 | mutation ($request: CreateCollectRequest!) {
18 | createCollectTypedData(request: $request) {
19 | id
20 | expiresAt
21 | typedData {
22 | types {
23 | CollectWithSig {
24 | name
25 | type
26 | }
27 | }
28 | domain {
29 | name
30 | chainId
31 | version
32 | verifyingContract
33 | }
34 | value {
35 | nonce
36 | deadline
37 | profileId
38 | pubId
39 | data
40 | }
41 | }
42 | }
43 | }
44 | `;
45 |
46 | export const useCreateCollectTypedData = (publicationId?: string): MutationTuple => {
47 | return useMutation(COLLECT, {
48 | variables: {
49 | request: {
50 | publicationId,
51 | },
52 | },
53 | });
54 | };
55 |
--------------------------------------------------------------------------------
/src/hooks/api/comment.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { TypedDataResponse } from "../../types/lens";
4 | import { CollectModule, ReferenceModule } from "../../types/modules";
5 | import { FailedBroadcast, SuccessfulBroadcast } from "./broadcast";
6 |
7 | interface CreateCommentTypedDataRequest {
8 | request: {
9 | profileId?: string;
10 | publicationId?: string;
11 | contentURI?: string;
12 | collectModule?: CollectModule;
13 | referenceModule?: ReferenceModule;
14 | };
15 | }
16 |
17 | // more: https://docs.lens.xyz/docs/create-comment-typed-data
18 | interface CreateCommentTypedDataResponse {
19 | createCommentTypedData?: TypedDataResponse;
20 | }
21 |
22 | const CREATE_COMMENT_TYPED_DATA = gql`
23 | mutation ($request: CreatePublicCommentRequest!) {
24 | createCommentTypedData(request: $request) {
25 | id
26 | expiresAt
27 | typedData {
28 | types {
29 | CommentWithSig {
30 | name
31 | type
32 | }
33 | }
34 | domain {
35 | name
36 | chainId
37 | version
38 | verifyingContract
39 | }
40 | value {
41 | nonce
42 | deadline
43 | profileId
44 | profileIdPointed
45 | pubIdPointed
46 | contentURI
47 | collectModule
48 | collectModuleInitData
49 | referenceModule
50 | referenceModuleInitData
51 | referenceModuleData
52 | }
53 | }
54 | }
55 | }
56 | `;
57 |
58 | export const useCreateCommentTypedData = (
59 | profileId?: string,
60 | publicationId?: string,
61 | contentURI?: string,
62 | collectModule?: CollectModule,
63 | referenceModule?: ReferenceModule,
64 | ): MutationTuple => {
65 | return useMutation(CREATE_COMMENT_TYPED_DATA, {
66 | variables: {
67 | request: {
68 | profileId,
69 | publicationId,
70 | contentURI,
71 | collectModule,
72 | referenceModule,
73 | },
74 | },
75 | });
76 | };
77 |
78 | const CREATE_COMMENT_VIA_DISPATCHER = gql`
79 | mutation ($request: CreatePublicCommentRequest!) {
80 | createCommentViaDispatcher(request: $request) {
81 | ... on RelayerResult {
82 | txHash
83 | txId
84 | }
85 | ... on RelayError {
86 | reason
87 | }
88 | }
89 | }
90 | `;
91 |
92 | interface CreateCommentViaDispatcherResponse {
93 | createCommentViaDispatcher: SuccessfulBroadcast | FailedBroadcast;
94 | }
95 |
96 | export const useCreateCommentViaDispatcher = (
97 | profileId?: string,
98 | publicationId?: string,
99 | contentURI?: string,
100 | collectModule?: CollectModule,
101 | referenceModule?: ReferenceModule,
102 | ): MutationTuple => {
103 | return useMutation(CREATE_COMMENT_VIA_DISPATCHER, {
104 | variables: {
105 | request: {
106 | profileId,
107 | publicationId,
108 | contentURI,
109 | collectModule,
110 | referenceModule,
111 | },
112 | },
113 | });
114 | };
115 |
--------------------------------------------------------------------------------
/src/hooks/api/follow.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { TypedDataResponse } from "../../types/lens";
4 |
5 | interface FollowRequest {
6 | request: {
7 | follow?: Array<{
8 | profile?: string;
9 | // TODO: Support follow modules
10 | // followModule: string;
11 | }>;
12 | };
13 | }
14 |
15 | // more: https://docs.lens.xyz/docs/create-follow-typed-data
16 | interface FollowResponse {
17 | createFollowTypedData: TypedDataResponse;
18 | }
19 |
20 | const FOLLOW = gql`
21 | mutation ($request: FollowRequest!) {
22 | createFollowTypedData(request: $request) {
23 | id
24 | expiresAt
25 | typedData {
26 | domain {
27 | name
28 | chainId
29 | version
30 | verifyingContract
31 | }
32 | types {
33 | FollowWithSig {
34 | name
35 | type
36 | }
37 | }
38 | value {
39 | nonce
40 | deadline
41 | profileIds
42 | datas
43 | }
44 | }
45 | }
46 | }
47 | `;
48 |
49 | export const useCreateFollowTypedData = (profile?: string): MutationTuple => {
50 | return useMutation(FOLLOW, {
51 | variables: {
52 | request: {
53 | follow: [
54 | {
55 | profile,
56 | },
57 | ],
58 | },
59 | },
60 | });
61 | };
62 |
63 | interface UnfollowRequest {
64 | request: {
65 | profile?: string;
66 | };
67 | }
68 |
69 | // more: https://docs.lens.xyz/docs/create-unfollow-typed-data
70 | interface UnfollowResponse {
71 | createUnfollowTypedData: TypedDataResponse;
72 | }
73 |
74 | const UNFOLLOW = gql`
75 | mutation ($request: UnfollowRequest!) {
76 | createUnfollowTypedData(request: $request) {
77 | id
78 | expiresAt
79 | typedData {
80 | domain {
81 | name
82 | chainId
83 | version
84 | verifyingContract
85 | }
86 | types {
87 | BurnWithSig {
88 | name
89 | type
90 | }
91 | }
92 | value {
93 | nonce
94 | deadline
95 | tokenId
96 | }
97 | }
98 | }
99 | }
100 | `;
101 |
102 | export const useCreateUnfollowTypedData = (profile?: string): MutationTuple => {
103 | return useMutation(UNFOLLOW, {
104 | variables: {
105 | request: {
106 | profile,
107 | },
108 | },
109 | });
110 | };
111 |
--------------------------------------------------------------------------------
/src/hooks/api/indexer.ts:
--------------------------------------------------------------------------------
1 | import { gql, QueryResult, useQuery } from "@apollo/client";
2 | import { TransactionReceipt } from "@ethersproject/abstract-provider";
3 |
4 | interface IndexerRequest {
5 | request: {
6 | txId?: string;
7 | };
8 | }
9 |
10 | // more: https://docs.lens.xyz/docs/has-transaction-been-indexed
11 | interface IndexerResponse {
12 | hasTxHashBeenIndexed?: {
13 | indexed: boolean;
14 | txReceipt: TransactionReceipt;
15 | metadataStatus: {
16 | status: "NOT_FOUND" | "PENDING" | "METADATA_VALIDATION_FAILED" | "SUCCESS";
17 | reason: string;
18 | };
19 | };
20 | }
21 |
22 | const INDEXED = gql`
23 | query ($request: HasTxHashBeenIndexedRequest!) {
24 | hasTxHashBeenIndexed(request: $request) {
25 | ... on TransactionIndexedResult {
26 | indexed
27 | txReceipt {
28 | to
29 | from
30 | contractAddress
31 | transactionIndex
32 | root
33 | gasUsed
34 | logsBloom
35 | blockHash
36 | transactionHash
37 | blockNumber
38 | confirmations
39 | cumulativeGasUsed
40 | effectiveGasPrice
41 | byzantium
42 | type
43 | status
44 | logs {
45 | blockNumber
46 | blockHash
47 | transactionIndex
48 | removed
49 | address
50 | data
51 | topics
52 | transactionHash
53 | logIndex
54 | }
55 | }
56 | metadataStatus {
57 | status
58 | reason
59 | }
60 | }
61 | ... on TransactionError {
62 | reason
63 | txReceipt {
64 | to
65 | from
66 | contractAddress
67 | transactionIndex
68 | root
69 | gasUsed
70 | logsBloom
71 | blockHash
72 | transactionHash
73 | blockNumber
74 | confirmations
75 | cumulativeGasUsed
76 | effectiveGasPrice
77 | byzantium
78 | type
79 | status
80 | logs {
81 | blockNumber
82 | blockHash
83 | transactionIndex
84 | removed
85 | address
86 | data
87 | topics
88 | transactionHash
89 | logIndex
90 | }
91 | }
92 | }
93 | __typename
94 | }
95 | }
96 | `;
97 |
98 | export const useIndexed = (txId?: string, broadcasting?: boolean): QueryResult => {
99 | return useQuery(INDEXED, {
100 | variables: {
101 | request: {
102 | txId,
103 | },
104 | },
105 | pollInterval: 500,
106 | fetchPolicy: "network-only",
107 | skip: !txId || !broadcasting,
108 | });
109 | };
110 |
--------------------------------------------------------------------------------
/src/hooks/api/login.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, QueryResult, useMutation, useQuery } from "@apollo/client";
2 |
3 | interface ChallengeRequest {
4 | request: {
5 | address?: string;
6 | };
7 | }
8 |
9 | interface ChallengeResponse {
10 | challenge: {
11 | text: string;
12 | };
13 | }
14 |
15 | const GET_CHALLENGE = gql`
16 | query ($request: ChallengeRequest!) {
17 | challenge(request: $request) {
18 | text
19 | }
20 | }
21 | `;
22 |
23 | export const useChallenge = (address?: string): QueryResult => {
24 | return useQuery(GET_CHALLENGE, {
25 | variables: {
26 | request: {
27 | address,
28 | },
29 | },
30 | skip: !address,
31 | });
32 | };
33 |
34 | interface AuthenticateRequest {
35 | request: {
36 | address?: string;
37 | signature?: string;
38 | };
39 | }
40 |
41 | interface AuthenticateResponse {
42 | authenticate: {
43 | accessToken: string;
44 | refreshToken: string;
45 | };
46 | }
47 |
48 | const AUTHENTICATE = gql`
49 | mutation ($request: SignedAuthChallenge!) {
50 | authenticate(request: $request) {
51 | accessToken
52 | refreshToken
53 | }
54 | }
55 | `;
56 |
57 | export const useAuthenticate = (
58 | address?: string,
59 | signature?: string,
60 | ): MutationTuple => {
61 | return useMutation(AUTHENTICATE, {
62 | variables: {
63 | request: {
64 | address,
65 | signature,
66 | },
67 | },
68 | });
69 | };
70 |
71 | interface RefreshRequest {
72 | request: {
73 | refreshToken?: string;
74 | };
75 | }
76 |
77 | interface RefreshResponse {
78 | refresh: {
79 | accessToken: string;
80 | refreshToken: string;
81 | };
82 | }
83 |
84 | const REFRESH_AUTHENTICATION = gql`
85 | mutation ($request: RefreshRequest!) {
86 | refresh(request: $request) {
87 | accessToken
88 | refreshToken
89 | }
90 | }
91 | `;
92 |
93 | export const useRefresh = (refreshToken?: string): MutationTuple => {
94 | return useMutation(REFRESH_AUTHENTICATION, {
95 | variables: {
96 | request: {
97 | refreshToken,
98 | },
99 | },
100 | });
101 | };
102 |
--------------------------------------------------------------------------------
/src/hooks/api/mirror.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { TypedDataResponse } from "../../types/lens";
4 | import { ReferenceModule } from "../../types/modules";
5 | import { FailedBroadcast, SuccessfulBroadcast } from "./broadcast";
6 |
7 | interface MirrorRequest {
8 | request: {
9 | profileId?: string;
10 | publicationId?: string;
11 | referenceModule?: ReferenceModule;
12 | };
13 | }
14 |
15 | // more: https://docs.lens.xyz/docs/create-mirror-typed-data
16 | interface MirrorResponse {
17 | createMirrorTypedData: TypedDataResponse;
18 | }
19 |
20 | const MIRROR = gql`
21 | mutation ($request: CreateMirrorRequest!) {
22 | createMirrorTypedData(request: $request) {
23 | id
24 | expiresAt
25 | typedData {
26 | types {
27 | MirrorWithSig {
28 | name
29 | type
30 | }
31 | }
32 | domain {
33 | name
34 | chainId
35 | version
36 | verifyingContract
37 | }
38 | value {
39 | nonce
40 | deadline
41 | profileId
42 | profileIdPointed
43 | pubIdPointed
44 | referenceModule
45 | referenceModuleData
46 | referenceModuleInitData
47 | }
48 | }
49 | }
50 | }
51 | `;
52 |
53 | export const useCreateMirrorTypedData = (
54 | profileId?: string,
55 | publicationId?: string,
56 | referenceModule?: ReferenceModule,
57 | ): MutationTuple => {
58 | return useMutation(MIRROR, {
59 | variables: {
60 | request: {
61 | profileId,
62 | publicationId,
63 | referenceModule,
64 | },
65 | },
66 | });
67 | };
68 |
69 | const CREATE_MIRROR_VIA_DISPATCHER = gql`
70 | mutation ($request: CreateMirrorRequest!) {
71 | createMirrorViaDispatcher(request: $request) {
72 | ... on RelayerResult {
73 | txHash
74 | txId
75 | }
76 | ... on RelayError {
77 | reason
78 | }
79 | }
80 | }
81 | `;
82 |
83 | interface CreateMirrorViaDispatcherResponse {
84 | createMirrorViaDispatcher: SuccessfulBroadcast | FailedBroadcast;
85 | }
86 |
87 | export const useCreateMirrorViaDispatcher = (
88 | profileId?: string,
89 | publicationId?: string,
90 | referenceModule?: ReferenceModule,
91 | ): MutationTuple => {
92 | return useMutation(CREATE_MIRROR_VIA_DISPATCHER, {
93 | variables: {
94 | request: {
95 | profileId,
96 | publicationId,
97 | referenceModule,
98 | },
99 | },
100 | });
101 | };
102 |
--------------------------------------------------------------------------------
/src/hooks/api/post.ts:
--------------------------------------------------------------------------------
1 | import { gql, MutationTuple, useMutation } from "@apollo/client";
2 |
3 | import { TypedDataResponse } from "../../types/lens";
4 | import { CollectModule, ReferenceModule } from "../../types/modules";
5 | import { FailedBroadcast, SuccessfulBroadcast } from "./broadcast";
6 |
7 | interface CreatePostTypedDataRequest {
8 | request: {
9 | profileId?: string;
10 | contentURI?: string;
11 | collectModule?: CollectModule;
12 | referenceModule?: ReferenceModule;
13 | };
14 | }
15 |
16 | // more: https://docs.lens.xyz/docs/create-post-typed-data
17 | interface CreatePostTypedDataResponse {
18 | createPostTypedData?: TypedDataResponse;
19 | }
20 |
21 | const CREATE_POST_TYPED_DATA = gql`
22 | mutation ($request: CreatePublicPostRequest!) {
23 | createPostTypedData(request: $request) {
24 | id
25 | expiresAt
26 | typedData {
27 | types {
28 | PostWithSig {
29 | name
30 | type
31 | }
32 | }
33 | domain {
34 | name
35 | chainId
36 | version
37 | verifyingContract
38 | }
39 | value {
40 | nonce
41 | deadline
42 | profileId
43 | contentURI
44 | collectModule
45 | collectModuleInitData
46 | referenceModule
47 | referenceModuleInitData
48 | }
49 | }
50 | }
51 | }
52 | `;
53 |
54 | export const useCreatePostTypedData = (
55 | profileId?: string,
56 | contentURI?: string,
57 | collectModule?: CollectModule,
58 | referenceModule?: ReferenceModule,
59 | ): MutationTuple => {
60 | return useMutation(CREATE_POST_TYPED_DATA, {
61 | variables: {
62 | request: {
63 | profileId,
64 | contentURI,
65 | collectModule,
66 | referenceModule,
67 | },
68 | },
69 | });
70 | };
71 |
72 | const CREATE_POST_VIA_DISPATCHER = gql`
73 | mutation ($request: CreatePublicPostRequest!) {
74 | createPostViaDispatcher(request: $request) {
75 | ... on RelayerResult {
76 | txHash
77 | txId
78 | }
79 | ... on RelayError {
80 | reason
81 | }
82 | }
83 | }
84 | `;
85 |
86 | interface CreatePostViaDispatcherResponse {
87 | createPostViaDispatcher: SuccessfulBroadcast | FailedBroadcast;
88 | }
89 |
90 | export const useCreatePostViaDispatcher = (
91 | profileId?: string,
92 | contentURI?: string,
93 | collectModule?: CollectModule,
94 | referenceModule?: ReferenceModule,
95 | ): MutationTuple => {
96 | return useMutation(CREATE_POST_VIA_DISPATCHER, {
97 | variables: {
98 | request: {
99 | profileId,
100 | contentURI,
101 | collectModule,
102 | referenceModule,
103 | },
104 | },
105 | });
106 | };
107 |
--------------------------------------------------------------------------------
/src/hooks/api/profile.ts:
--------------------------------------------------------------------------------
1 | import { gql, QueryResult, useQuery } from "@apollo/client";
2 | import { useEffect, useState } from "react";
3 |
4 | import { DefaultProfile } from "../../types/lens";
5 |
6 | interface ProfilesRequest {
7 | request: {
8 | ownedBy?: string;
9 | };
10 | }
11 |
12 | // more: https://docs.lens.xyz/docs/get-profiles
13 | interface ProfilesResponse {
14 | profiles?: {
15 | items: DefaultProfile[];
16 | };
17 | }
18 |
19 | const GET_PROFILES = gql`
20 | query ($request: ProfileQueryRequest!) {
21 | profiles(request: $request) {
22 | items {
23 | id
24 | name
25 | bio
26 | attributes {
27 | displayType
28 | traitType
29 | key
30 | value
31 | }
32 | followNftAddress
33 | metadata
34 | isDefault
35 | picture {
36 | ... on NftImage {
37 | contractAddress
38 | tokenId
39 | uri
40 | verified
41 | }
42 | ... on MediaSet {
43 | original {
44 | url
45 | mimeType
46 | }
47 | }
48 | __typename
49 | }
50 | handle
51 | coverPicture {
52 | ... on NftImage {
53 | contractAddress
54 | tokenId
55 | uri
56 | verified
57 | }
58 | ... on MediaSet {
59 | original {
60 | url
61 | mimeType
62 | }
63 | }
64 | __typename
65 | }
66 | ownedBy
67 | dispatcher {
68 | address
69 | canUseRelay
70 | }
71 | stats {
72 | totalFollowers
73 | totalFollowing
74 | totalPosts
75 | totalComments
76 | totalMirrors
77 | totalPublications
78 | totalCollects
79 | }
80 | followModule {
81 | ... on FeeFollowModuleSettings {
82 | type
83 | amount {
84 | asset {
85 | symbol
86 | name
87 | decimals
88 | address
89 | }
90 | value
91 | }
92 | recipient
93 | }
94 | ... on ProfileFollowModuleSettings {
95 | type
96 | }
97 | ... on RevertFollowModuleSettings {
98 | type
99 | }
100 | }
101 | }
102 | pageInfo {
103 | prev
104 | next
105 | totalCount
106 | }
107 | }
108 | }
109 | `;
110 |
111 | export const useProfiles = (ownedBy?: string): QueryResult => {
112 | return useQuery(GET_PROFILES, {
113 | variables: {
114 | request: {
115 | ownedBy,
116 | },
117 | },
118 | skip: !ownedBy,
119 | });
120 | };
121 |
122 | interface DefaultProfileRequest {
123 | request: {
124 | ethereumAddress?: string;
125 | };
126 | }
127 |
128 | // more: https://docs.lens.xyz/docs/get-default-profile
129 | interface DefaultProfileResponse {
130 | defaultProfile?: DefaultProfile;
131 | }
132 |
133 | const GET_DEFAULT_PROFILE = gql`
134 | query ($request: DefaultProfileRequest!) {
135 | defaultProfile(request: $request) {
136 | id
137 | name
138 | bio
139 | attributes {
140 | displayType
141 | traitType
142 | key
143 | value
144 | }
145 | followNftAddress
146 | metadata
147 | isDefault
148 | picture {
149 | ... on NftImage {
150 | contractAddress
151 | tokenId
152 | uri
153 | verified
154 | }
155 | ... on MediaSet {
156 | original {
157 | url
158 | mimeType
159 | }
160 | }
161 | __typename
162 | }
163 | handle
164 | coverPicture {
165 | ... on NftImage {
166 | contractAddress
167 | tokenId
168 | uri
169 | verified
170 | }
171 | ... on MediaSet {
172 | original {
173 | url
174 | mimeType
175 | }
176 | }
177 | __typename
178 | }
179 | ownedBy
180 | dispatcher {
181 | address
182 | canUseRelay
183 | }
184 | stats {
185 | totalFollowers
186 | totalFollowing
187 | totalPosts
188 | totalComments
189 | totalMirrors
190 | totalPublications
191 | totalCollects
192 | }
193 | followModule {
194 | ... on FeeFollowModuleSettings {
195 | type
196 | amount {
197 | asset {
198 | symbol
199 | name
200 | decimals
201 | address
202 | }
203 | value
204 | }
205 | recipient
206 | }
207 | ... on ProfileFollowModuleSettings {
208 | type
209 | }
210 | ... on RevertFollowModuleSettings {
211 | type
212 | }
213 | }
214 | }
215 | }
216 | `;
217 |
218 | // TODO: Allow selecting profile
219 | export const useDefaultProfile = (ethereumAddress?: string): DefaultProfileResponse => {
220 | const [response, setResponse] = useState({ defaultProfile: undefined });
221 |
222 | const defaultProfileQuery = useQuery(GET_DEFAULT_PROFILE, {
223 | variables: {
224 | request: {
225 | ethereumAddress,
226 | },
227 | },
228 | skip: !ethereumAddress,
229 | });
230 |
231 | const profilesQuery = useProfiles(ethereumAddress);
232 |
233 | useEffect(() => {
234 | if (defaultProfileQuery.data?.defaultProfile) {
235 | setResponse({ defaultProfile: defaultProfileQuery.data?.defaultProfile });
236 | } else if (profilesQuery.data?.profiles?.items && profilesQuery.data?.profiles?.items.length > 0) {
237 | setResponse({ defaultProfile: profilesQuery.data?.profiles?.items[0] });
238 | }
239 | }, [ethereumAddress, profilesQuery, defaultProfileQuery]);
240 |
241 | return response;
242 | };
243 |
244 | interface ProfileRequest {
245 | request: {
246 | handle?: string;
247 | };
248 | }
249 |
250 | // more: https://docs.lens.xyz/docs/get-profile
251 | interface ProfileResponse {
252 | profile?: DefaultProfile;
253 | }
254 |
255 | const GET_PROFILE = gql`
256 | query ($request: SingleProfileQueryRequest!) {
257 | profile(request: $request) {
258 | id
259 | name
260 | bio
261 | attributes {
262 | displayType
263 | traitType
264 | key
265 | value
266 | }
267 | followNftAddress
268 | metadata
269 | isDefault
270 | picture {
271 | ... on NftImage {
272 | contractAddress
273 | tokenId
274 | uri
275 | verified
276 | }
277 | ... on MediaSet {
278 | original {
279 | url
280 | mimeType
281 | }
282 | }
283 | __typename
284 | }
285 | handle
286 | coverPicture {
287 | ... on NftImage {
288 | contractAddress
289 | tokenId
290 | uri
291 | verified
292 | }
293 | ... on MediaSet {
294 | original {
295 | url
296 | mimeType
297 | }
298 | }
299 | __typename
300 | }
301 | ownedBy
302 | isFollowedByMe
303 | dispatcher {
304 | address
305 | canUseRelay
306 | }
307 | stats {
308 | totalFollowers
309 | totalFollowing
310 | totalPosts
311 | totalComments
312 | totalMirrors
313 | totalPublications
314 | totalCollects
315 | }
316 | followModule {
317 | ... on FeeFollowModuleSettings {
318 | type
319 | amount {
320 | asset {
321 | symbol
322 | name
323 | decimals
324 | address
325 | }
326 | value
327 | }
328 | recipient
329 | }
330 | ... on ProfileFollowModuleSettings {
331 | type
332 | }
333 | ... on RevertFollowModuleSettings {
334 | type
335 | }
336 | }
337 | }
338 | }
339 | `;
340 |
341 | export const useProfile = (handle?: string): QueryResult => {
342 | return useQuery(GET_PROFILE, {
343 | variables: {
344 | request: { handle },
345 | },
346 | skip: !handle,
347 | });
348 | };
349 |
350 | interface DispatcherRequest {
351 | request: {
352 | profileId?: string;
353 | };
354 | }
355 |
356 | // more: https://docs.lens.xyz/docs/dispatcher
357 | interface DispatcherResponse {
358 | profile?: {
359 | dispatcher?: {
360 | address: string;
361 | canUseRelay: boolean;
362 | };
363 | };
364 | }
365 |
366 | const HAS_DISPATCHER = gql`
367 | query ($request: SingleProfileQueryRequest!) {
368 | profile(request: $request) {
369 | id
370 | dispatcher {
371 | address
372 | canUseRelay
373 | }
374 | }
375 | }
376 | `;
377 |
378 | export const useProfileHasDispatcher = (profileId?: string): boolean => {
379 | const [dispatch, setDispatch] = useState(false);
380 |
381 | const { data } = useQuery(HAS_DISPATCHER, {
382 | variables: {
383 | request: { profileId },
384 | },
385 | skip: !profileId,
386 | });
387 |
388 | useEffect(() => {
389 | setDispatch(data?.profile?.dispatcher?.canUseRelay ?? false);
390 | }, [data]);
391 |
392 | return dispatch;
393 | };
394 |
395 | function isDefaultProfileResponse(
396 | response: ProfileResponse | DefaultProfileResponse,
397 | ): response is DefaultProfileResponse {
398 | return (response as DefaultProfileResponse).defaultProfile !== undefined;
399 | }
400 |
401 | function isProfileResponse(response: ProfileResponse | DefaultProfileResponse): response is ProfileResponse {
402 | return (response as ProfileResponse).profile !== undefined;
403 | }
404 |
405 | export const useProfilePicture = (response?: ProfileResponse | DefaultProfileResponse): string | undefined => {
406 | if (response) {
407 | if (isProfileResponse(response)) {
408 | return response.profile?.picture?.original?.url;
409 | } else if (isDefaultProfileResponse(response)) {
410 | return response.defaultProfile?.picture?.original?.url;
411 | }
412 | }
413 | };
414 |
--------------------------------------------------------------------------------
/src/hooks/api/publication.ts:
--------------------------------------------------------------------------------
1 | import { gql, QueryResult, useQuery } from "@apollo/client";
2 |
3 | import { PageInfo, Post, PublicationType } from "../../types/lens";
4 | import { PublicationMainFocus } from "../../types/metadata";
5 |
6 | interface GetPublicationRequest {
7 | request: {
8 | publicationId?: string;
9 | };
10 | profileId?: string;
11 | }
12 |
13 | // more: https://docs.lens.xyz/docs/get-publication
14 | interface GetPublicationResponse {
15 | publication?: Post;
16 | }
17 |
18 | const GET_PUBLICATION = gql`
19 | query ($request: PublicationQueryRequest!, $profileId: ProfileId) {
20 | publication(request: $request) {
21 | __typename
22 | ... on Post {
23 | ...PostFields
24 | }
25 | ... on Comment {
26 | ...CommentFields
27 | }
28 | ... on Mirror {
29 | ...MirrorFields
30 | }
31 | }
32 | }
33 |
34 | fragment MediaFields on Media {
35 | url
36 | mimeType
37 | }
38 |
39 | fragment ProfileFields on Profile {
40 | id
41 | name
42 | bio
43 | attributes {
44 | displayType
45 | traitType
46 | key
47 | value
48 | }
49 | isFollowedByMe
50 | isFollowing(who: null)
51 | followNftAddress
52 | metadata
53 | isDefault
54 | handle
55 | picture {
56 | ... on NftImage {
57 | contractAddress
58 | tokenId
59 | uri
60 | verified
61 | }
62 | ... on MediaSet {
63 | original {
64 | ...MediaFields
65 | }
66 | }
67 | }
68 | coverPicture {
69 | ... on NftImage {
70 | contractAddress
71 | tokenId
72 | uri
73 | verified
74 | }
75 | ... on MediaSet {
76 | original {
77 | ...MediaFields
78 | }
79 | }
80 | }
81 | ownedBy
82 | dispatcher {
83 | address
84 | }
85 | stats {
86 | totalFollowers
87 | totalFollowing
88 | totalPosts
89 | totalComments
90 | totalMirrors
91 | totalPublications
92 | totalCollects
93 | }
94 | followModule {
95 | ... on FeeFollowModuleSettings {
96 | type
97 | amount {
98 | asset {
99 | name
100 | symbol
101 | decimals
102 | address
103 | }
104 | value
105 | }
106 | recipient
107 | }
108 | ... on ProfileFollowModuleSettings {
109 | type
110 | }
111 | ... on RevertFollowModuleSettings {
112 | type
113 | }
114 | }
115 | }
116 |
117 | fragment PublicationStatsFields on PublicationStats {
118 | totalAmountOfMirrors
119 | totalAmountOfCollects
120 | totalAmountOfComments
121 | }
122 |
123 | fragment MetadataOutputFields on MetadataOutput {
124 | name
125 | description
126 | content
127 | media {
128 | original {
129 | ...MediaFields
130 | }
131 | }
132 | attributes {
133 | displayType
134 | traitType
135 | value
136 | }
137 | tags
138 | }
139 |
140 | fragment Erc20Fields on Erc20 {
141 | name
142 | symbol
143 | decimals
144 | address
145 | }
146 |
147 | fragment CollectModuleFields on CollectModule {
148 | __typename
149 | ... on FreeCollectModuleSettings {
150 | type
151 | followerOnly
152 | contractAddress
153 | }
154 | ... on FeeCollectModuleSettings {
155 | type
156 | amount {
157 | asset {
158 | ...Erc20Fields
159 | }
160 | value
161 | }
162 | recipient
163 | referralFee
164 | }
165 | ... on LimitedFeeCollectModuleSettings {
166 | type
167 | collectLimit
168 | amount {
169 | asset {
170 | ...Erc20Fields
171 | }
172 | value
173 | }
174 | recipient
175 | referralFee
176 | }
177 | ... on LimitedTimedFeeCollectModuleSettings {
178 | type
179 | collectLimit
180 | amount {
181 | asset {
182 | ...Erc20Fields
183 | }
184 | value
185 | }
186 | recipient
187 | referralFee
188 | endTimestamp
189 | }
190 | ... on RevertCollectModuleSettings {
191 | type
192 | }
193 | ... on TimedFeeCollectModuleSettings {
194 | type
195 | amount {
196 | asset {
197 | ...Erc20Fields
198 | }
199 | value
200 | }
201 | recipient
202 | referralFee
203 | endTimestamp
204 | }
205 | }
206 |
207 | fragment PostFields on Post {
208 | id
209 | profile {
210 | ...ProfileFields
211 | }
212 | stats {
213 | ...PublicationStatsFields
214 | }
215 | metadata {
216 | ...MetadataOutputFields
217 | }
218 | createdAt
219 | collectModule {
220 | ...CollectModuleFields
221 | }
222 | referenceModule {
223 | ... on FollowOnlyReferenceModuleSettings {
224 | type
225 | }
226 | }
227 | appId
228 | hidden
229 | reaction(request: null)
230 | mirrors(by: $profileId)
231 | hasCollectedByMe
232 | }
233 |
234 | fragment MirrorBaseFields on Mirror {
235 | id
236 | profile {
237 | ...ProfileFields
238 | }
239 | stats {
240 | ...PublicationStatsFields
241 | }
242 | metadata {
243 | ...MetadataOutputFields
244 | }
245 | createdAt
246 | collectModule {
247 | ...CollectModuleFields
248 | }
249 | referenceModule {
250 | ... on FollowOnlyReferenceModuleSettings {
251 | type
252 | }
253 | }
254 | appId
255 | hidden
256 | reaction(request: null)
257 | hasCollectedByMe
258 | }
259 |
260 | fragment MirrorFields on Mirror {
261 | ...MirrorBaseFields
262 | mirrorOf {
263 | ... on Post {
264 | ...PostFields
265 | }
266 | ... on Comment {
267 | ...CommentFields
268 | }
269 | }
270 | }
271 |
272 | fragment CommentBaseFields on Comment {
273 | id
274 | profile {
275 | ...ProfileFields
276 | }
277 | stats {
278 | ...PublicationStatsFields
279 | }
280 | metadata {
281 | ...MetadataOutputFields
282 | }
283 | createdAt
284 | collectModule {
285 | ...CollectModuleFields
286 | }
287 | referenceModule {
288 | ... on FollowOnlyReferenceModuleSettings {
289 | type
290 | }
291 | }
292 | appId
293 | hidden
294 | reaction(request: null)
295 | mirrors(by: null)
296 | hasCollectedByMe
297 | }
298 |
299 | fragment CommentFields on Comment {
300 | ...CommentBaseFields
301 | mainPost {
302 | ... on Post {
303 | ...PostFields
304 | }
305 | ... on Mirror {
306 | ...MirrorBaseFields
307 | mirrorOf {
308 | ... on Post {
309 | ...PostFields
310 | }
311 | ... on Comment {
312 | ...CommentMirrorOfFields
313 | }
314 | }
315 | }
316 | }
317 | }
318 |
319 | fragment CommentMirrorOfFields on Comment {
320 | ...CommentBaseFields
321 | mainPost {
322 | ... on Post {
323 | ...PostFields
324 | }
325 | ... on Mirror {
326 | ...MirrorBaseFields
327 | }
328 | }
329 | }
330 | `;
331 |
332 | export const usePublication = (
333 | publicationId?: string,
334 | profileId?: string,
335 | ): QueryResult => {
336 | return useQuery(GET_PUBLICATION, {
337 | variables: {
338 | request: {
339 | publicationId,
340 | },
341 | profileId,
342 | },
343 | skip: !publicationId,
344 | });
345 | };
346 |
347 | interface GetPublicationsRequest {
348 | request: {
349 | profileId?: string;
350 | commentsOf?: string;
351 | publicationTypes?: PublicationType[];
352 | metadata?: {
353 | tags?: {
354 | oneOf: string[];
355 | };
356 | mainContentFocus?: PublicationMainFocus;
357 | };
358 | sources?: string[];
359 | cursor?: string;
360 | };
361 | }
362 |
363 | // more: https://docs.lens.xyz/docs/get-publications
364 | interface GetPublicationsResponse {
365 | publications?: {
366 | items: Post[];
367 | pageInfo: PageInfo;
368 | };
369 | }
370 |
371 | const GET_PUBLICATIONS = gql`
372 | query ($request: PublicationsQueryRequest!) {
373 | publications(request: $request) {
374 | items {
375 | __typename
376 | ... on Post {
377 | ...PostFields
378 | }
379 | ... on Comment {
380 | ...CommentFields
381 | }
382 | ... on Mirror {
383 | ...MirrorFields
384 | }
385 | }
386 | pageInfo {
387 | prev
388 | next
389 | totalCount
390 | }
391 | }
392 | }
393 | fragment MediaFields on Media {
394 | url
395 | mimeType
396 | }
397 | fragment ProfileFields on Profile {
398 | id
399 | name
400 | bio
401 | attributes {
402 | displayType
403 | traitType
404 | key
405 | value
406 | }
407 | isFollowedByMe
408 | isFollowing(who: null)
409 | followNftAddress
410 | metadata
411 | isDefault
412 | handle
413 | picture {
414 | ... on NftImage {
415 | contractAddress
416 | tokenId
417 | uri
418 | verified
419 | }
420 | ... on MediaSet {
421 | original {
422 | ...MediaFields
423 | }
424 | }
425 | }
426 | coverPicture {
427 | ... on NftImage {
428 | contractAddress
429 | tokenId
430 | uri
431 | verified
432 | }
433 | ... on MediaSet {
434 | original {
435 | ...MediaFields
436 | }
437 | }
438 | }
439 | ownedBy
440 | dispatcher {
441 | address
442 | }
443 | stats {
444 | totalFollowers
445 | totalFollowing
446 | totalPosts
447 | totalComments
448 | totalMirrors
449 | totalPublications
450 | totalCollects
451 | }
452 | followModule {
453 | ... on FeeFollowModuleSettings {
454 | type
455 | amount {
456 | asset {
457 | name
458 | symbol
459 | decimals
460 | address
461 | }
462 | value
463 | }
464 | recipient
465 | }
466 | ... on ProfileFollowModuleSettings {
467 | type
468 | }
469 | ... on RevertFollowModuleSettings {
470 | type
471 | }
472 | }
473 | }
474 | fragment PublicationStatsFields on PublicationStats {
475 | totalAmountOfMirrors
476 | totalAmountOfCollects
477 | totalAmountOfComments
478 | }
479 | fragment MetadataOutputFields on MetadataOutput {
480 | name
481 | description
482 | content
483 | media {
484 | original {
485 | ...MediaFields
486 | }
487 | }
488 | attributes {
489 | displayType
490 | traitType
491 | value
492 | }
493 | }
494 | fragment Erc20Fields on Erc20 {
495 | name
496 | symbol
497 | decimals
498 | address
499 | }
500 | fragment CollectModuleFields on CollectModule {
501 | __typename
502 | ... on FreeCollectModuleSettings {
503 | type
504 | followerOnly
505 | contractAddress
506 | }
507 | ... on FeeCollectModuleSettings {
508 | type
509 | amount {
510 | asset {
511 | ...Erc20Fields
512 | }
513 | value
514 | }
515 | recipient
516 | referralFee
517 | }
518 | ... on LimitedFeeCollectModuleSettings {
519 | type
520 | collectLimit
521 | amount {
522 | asset {
523 | ...Erc20Fields
524 | }
525 | value
526 | }
527 | recipient
528 | referralFee
529 | }
530 | ... on LimitedTimedFeeCollectModuleSettings {
531 | type
532 | collectLimit
533 | amount {
534 | asset {
535 | ...Erc20Fields
536 | }
537 | value
538 | }
539 | recipient
540 | referralFee
541 | endTimestamp
542 | }
543 | ... on RevertCollectModuleSettings {
544 | type
545 | }
546 | ... on TimedFeeCollectModuleSettings {
547 | type
548 | amount {
549 | asset {
550 | ...Erc20Fields
551 | }
552 | value
553 | }
554 | recipient
555 | referralFee
556 | endTimestamp
557 | }
558 | }
559 | fragment PostFields on Post {
560 | id
561 | profile {
562 | ...ProfileFields
563 | }
564 | stats {
565 | ...PublicationStatsFields
566 | }
567 | metadata {
568 | ...MetadataOutputFields
569 | }
570 | createdAt
571 | collectModule {
572 | ...CollectModuleFields
573 | }
574 | referenceModule {
575 | ... on FollowOnlyReferenceModuleSettings {
576 | type
577 | }
578 | }
579 | appId
580 | hidden
581 | reaction(request: null)
582 | mirrors(by: null)
583 | hasCollectedByMe
584 | }
585 | fragment MirrorBaseFields on Mirror {
586 | id
587 | profile {
588 | ...ProfileFields
589 | }
590 | stats {
591 | ...PublicationStatsFields
592 | }
593 | metadata {
594 | ...MetadataOutputFields
595 | }
596 | createdAt
597 | collectModule {
598 | ...CollectModuleFields
599 | }
600 | referenceModule {
601 | ... on FollowOnlyReferenceModuleSettings {
602 | type
603 | }
604 | }
605 | appId
606 | hidden
607 | reaction(request: null)
608 | hasCollectedByMe
609 | }
610 | fragment MirrorFields on Mirror {
611 | ...MirrorBaseFields
612 | mirrorOf {
613 | ... on Post {
614 | ...PostFields
615 | }
616 | ... on Comment {
617 | ...CommentFields
618 | }
619 | }
620 | }
621 | fragment CommentBaseFields on Comment {
622 | id
623 | profile {
624 | ...ProfileFields
625 | }
626 | stats {
627 | ...PublicationStatsFields
628 | }
629 | metadata {
630 | ...MetadataOutputFields
631 | }
632 | createdAt
633 | collectModule {
634 | ...CollectModuleFields
635 | }
636 | referenceModule {
637 | ... on FollowOnlyReferenceModuleSettings {
638 | type
639 | }
640 | }
641 | appId
642 | hidden
643 | reaction(request: null)
644 | mirrors(by: null)
645 | hasCollectedByMe
646 | }
647 | fragment CommentFields on Comment {
648 | ...CommentBaseFields
649 | mainPost {
650 | ... on Post {
651 | ...PostFields
652 | }
653 | ... on Mirror {
654 | ...MirrorBaseFields
655 | mirrorOf {
656 | ... on Post {
657 | ...PostFields
658 | }
659 | ... on Comment {
660 | ...CommentMirrorOfFields
661 | }
662 | }
663 | }
664 | }
665 | }
666 | fragment CommentMirrorOfFields on Comment {
667 | ...CommentBaseFields
668 | mainPost {
669 | ... on Post {
670 | ...PostFields
671 | }
672 | ... on Mirror {
673 | ...MirrorBaseFields
674 | }
675 | }
676 | }
677 | `;
678 |
679 | export const usePublications = (
680 | profileId?: string,
681 | publicationTypes: PublicationType[] = [PublicationType.POST],
682 | sources?: [string],
683 | ): QueryResult => {
684 | return useQuery(GET_PUBLICATIONS, {
685 | variables: {
686 | request: {
687 | profileId,
688 | publicationTypes,
689 | sources,
690 | },
691 | },
692 | skip: !profileId,
693 | });
694 | };
695 |
696 | export const usePublicationComments = (
697 | publicationId?: string,
698 | ): QueryResult => {
699 | return useQuery(GET_PUBLICATIONS, {
700 | variables: {
701 | request: {
702 | commentsOf: publicationId,
703 | },
704 | },
705 | skip: !publicationId,
706 | });
707 | };
708 |
--------------------------------------------------------------------------------
/src/hooks/api/search.ts:
--------------------------------------------------------------------------------
1 | import { gql, QueryResult, useQuery } from "@apollo/client";
2 |
3 | import { Profile } from "../../types/lens";
4 |
5 | interface ProfileSearchRequest {
6 | request: {
7 | query?: string;
8 | type: "PROFILE";
9 | limit: number;
10 | };
11 | }
12 |
13 | // more: https://docs.lens.xyz/docs/search-profiles-and-publications
14 | interface ProfileSearchResponse {
15 | search?: {
16 | items: Profile[];
17 | };
18 | }
19 |
20 | const SEARCH = gql`
21 | query ($request: SearchQueryRequest!) {
22 | search(request: $request) {
23 | ... on PublicationSearchResult {
24 | __typename
25 | items {
26 | __typename
27 | ... on Comment {
28 | ...CommentFields
29 | }
30 | ... on Post {
31 | ...PostFields
32 | }
33 | }
34 | pageInfo {
35 | prev
36 | totalCount
37 | next
38 | }
39 | }
40 | ... on ProfileSearchResult {
41 | __typename
42 | items {
43 | ... on Profile {
44 | ...ProfileFields
45 | }
46 | }
47 | pageInfo {
48 | prev
49 | totalCount
50 | next
51 | }
52 | }
53 | }
54 | }
55 |
56 | fragment MediaFields on Media {
57 | url
58 | mimeType
59 | }
60 |
61 | fragment MirrorBaseFields on Mirror {
62 | id
63 | profile {
64 | ...ProfileFields
65 | }
66 | stats {
67 | ...PublicationStatsFields
68 | }
69 | metadata {
70 | ...MetadataOutputFields
71 | }
72 | createdAt
73 | collectModule {
74 | ...CollectModuleFields
75 | }
76 | referenceModule {
77 | ... on FollowOnlyReferenceModuleSettings {
78 | type
79 | }
80 | }
81 | appId
82 | }
83 |
84 | fragment ProfileFields on Profile {
85 | profileId: id
86 | name
87 | bio
88 | attributes {
89 | displayType
90 | traitType
91 | key
92 | value
93 | }
94 | isFollowedByMe
95 | isFollowing(who: null)
96 | metadataUrl: metadata
97 | isDefault
98 | handle
99 | picture {
100 | ... on NftImage {
101 | contractAddress
102 | tokenId
103 | uri
104 | verified
105 | }
106 | ... on MediaSet {
107 | original {
108 | ...MediaFields
109 | }
110 | }
111 | }
112 | coverPicture {
113 | ... on NftImage {
114 | contractAddress
115 | tokenId
116 | uri
117 | verified
118 | }
119 | ... on MediaSet {
120 | original {
121 | ...MediaFields
122 | }
123 | }
124 | }
125 | ownedBy
126 | dispatcher {
127 | address
128 | }
129 | stats {
130 | totalFollowers
131 | totalFollowing
132 | totalPosts
133 | totalComments
134 | totalMirrors
135 | totalPublications
136 | totalCollects
137 | }
138 | followModule {
139 | ... on FeeFollowModuleSettings {
140 | type
141 | amount {
142 | asset {
143 | name
144 | symbol
145 | decimals
146 | address
147 | }
148 | value
149 | }
150 | recipient
151 | }
152 | ... on ProfileFollowModuleSettings {
153 | type
154 | }
155 | ... on RevertFollowModuleSettings {
156 | type
157 | }
158 | }
159 | }
160 |
161 | fragment PublicationStatsFields on PublicationStats {
162 | totalAmountOfMirrors
163 | totalAmountOfCollects
164 | totalAmountOfComments
165 | }
166 |
167 | fragment MetadataOutputFields on MetadataOutput {
168 | name
169 | description
170 | content
171 | media {
172 | original {
173 | ...MediaFields
174 | }
175 | }
176 | attributes {
177 | displayType
178 | traitType
179 | value
180 | }
181 | }
182 |
183 | fragment Erc20Fields on Erc20 {
184 | name
185 | symbol
186 | decimals
187 | address
188 | }
189 |
190 | fragment CollectModuleFields on CollectModule {
191 | __typename
192 | ... on FreeCollectModuleSettings {
193 | type
194 | followerOnly
195 | contractAddress
196 | }
197 | ... on FeeCollectModuleSettings {
198 | type
199 | amount {
200 | asset {
201 | ...Erc20Fields
202 | }
203 | value
204 | }
205 | recipient
206 | referralFee
207 | }
208 | ... on LimitedFeeCollectModuleSettings {
209 | type
210 | collectLimit
211 | amount {
212 | asset {
213 | ...Erc20Fields
214 | }
215 | value
216 | }
217 | recipient
218 | referralFee
219 | }
220 | ... on LimitedTimedFeeCollectModuleSettings {
221 | type
222 | collectLimit
223 | amount {
224 | asset {
225 | ...Erc20Fields
226 | }
227 | value
228 | }
229 | recipient
230 | referralFee
231 | endTimestamp
232 | }
233 | ... on RevertCollectModuleSettings {
234 | type
235 | }
236 | ... on TimedFeeCollectModuleSettings {
237 | type
238 | amount {
239 | asset {
240 | ...Erc20Fields
241 | }
242 | value
243 | }
244 | recipient
245 | referralFee
246 | endTimestamp
247 | }
248 | }
249 |
250 | fragment PostFields on Post {
251 | id
252 | profile {
253 | ...ProfileFields
254 | }
255 | stats {
256 | ...PublicationStatsFields
257 | }
258 | metadata {
259 | ...MetadataOutputFields
260 | }
261 | createdAt
262 | collectModule {
263 | ...CollectModuleFields
264 | }
265 | referenceModule {
266 | ... on FollowOnlyReferenceModuleSettings {
267 | type
268 | }
269 | }
270 | appId
271 | hidden
272 | reaction(request: null)
273 | mirrors(by: null)
274 | hasCollectedByMe
275 | }
276 |
277 | fragment CommentBaseFields on Comment {
278 | id
279 | profile {
280 | ...ProfileFields
281 | }
282 | stats {
283 | ...PublicationStatsFields
284 | }
285 | metadata {
286 | ...MetadataOutputFields
287 | }
288 | createdAt
289 | collectModule {
290 | ...CollectModuleFields
291 | }
292 | referenceModule {
293 | ... on FollowOnlyReferenceModuleSettings {
294 | type
295 | }
296 | }
297 | appId
298 | hidden
299 | reaction(request: null)
300 | mirrors(by: null)
301 | hasCollectedByMe
302 | }
303 |
304 | fragment CommentFields on Comment {
305 | ...CommentBaseFields
306 | mainPost {
307 | ... on Post {
308 | ...PostFields
309 | }
310 | ... on Mirror {
311 | ...MirrorBaseFields
312 | mirrorOf {
313 | ... on Post {
314 | ...PostFields
315 | }
316 | ... on Comment {
317 | ...CommentMirrorOfFields
318 | }
319 | }
320 | }
321 | }
322 | }
323 |
324 | fragment CommentMirrorOfFields on Comment {
325 | ...CommentBaseFields
326 | mainPost {
327 | ... on Post {
328 | ...PostFields
329 | }
330 | ... on Mirror {
331 | ...MirrorBaseFields
332 | }
333 | }
334 | }
335 | `;
336 |
337 | export const useSearch = (
338 | query?: string,
339 | limit: number = 9,
340 | ): QueryResult => {
341 | return useQuery(SEARCH, {
342 | variables: {
343 | request: {
344 | query,
345 | type: "PROFILE",
346 | limit,
347 | },
348 | },
349 | skip: !query,
350 | });
351 | };
352 |
--------------------------------------------------------------------------------
/src/hooks/combined/collect.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { useCreateCollectTypedData } from "../api/collect";
5 | import { useBroadcastAPIHook } from "../utils/broadcast";
6 | import { useSignTypedData } from "../utils/sign";
7 |
8 | export const useCollect = (
9 | publicationId: string | undefined,
10 | onFunctions?: OnFunctions,
11 | ): { collect: () => void; loading: boolean; error: Error | null } => {
12 | const [createCollectTypedData, { data: collectTypedData }] = useCreateCollectTypedData(publicationId);
13 |
14 | const signReturn = useSignTypedData(collectTypedData?.createCollectTypedData?.typedData);
15 |
16 | const {
17 | start: collect,
18 | loading,
19 | error,
20 | } = useBroadcastAPIHook(collectTypedData?.createCollectTypedData?.id, undefined, signReturn, onFunctions);
21 |
22 | useEffect(() => {
23 | loading && createCollectTypedData().catch(console.error);
24 | }, [publicationId, loading]);
25 |
26 | return { collect, loading, error };
27 | };
28 |
--------------------------------------------------------------------------------
/src/hooks/combined/comment.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { useCreateCommentTypedData, useCreateCommentViaDispatcher } from "../api/comment";
5 | import { useProfileHasDispatcher } from "../api/profile";
6 | import { useBroadcastAPIHook } from "../utils/broadcast";
7 | import { useSignTypedData } from "../utils/sign";
8 |
9 | export const useComment = (
10 | profileId: string | undefined,
11 | publicationId: string | undefined,
12 | commentURL: string | undefined,
13 | onFunctions?: OnFunctions,
14 | ): { comment: () => void; loading: boolean; error: Error | null } => {
15 | const dispatch = useProfileHasDispatcher(profileId);
16 |
17 | const [createCommentTypedData, { data: commentTypedData, reset: resetTypedData }] = useCreateCommentTypedData(
18 | profileId,
19 | publicationId,
20 | commentURL,
21 | {
22 | freeCollectModule: {
23 | followerOnly: false,
24 | },
25 | },
26 | );
27 |
28 | const [createCommentViaDispatcher, { data: commentViaDispatcher, reset: resetViaDispatcher }] =
29 | useCreateCommentViaDispatcher(profileId, publicationId, commentURL, {
30 | freeCollectModule: {
31 | followerOnly: false,
32 | },
33 | });
34 |
35 | const signReturn = useSignTypedData(commentTypedData?.createCommentTypedData?.typedData);
36 |
37 | const {
38 | start: comment,
39 | loading,
40 | error,
41 | } = useBroadcastAPIHook(
42 | commentTypedData?.createCommentTypedData?.id,
43 | commentViaDispatcher?.createCommentViaDispatcher,
44 | signReturn,
45 | onFunctions,
46 | );
47 |
48 | useEffect(() => {
49 | resetTypedData();
50 | resetViaDispatcher();
51 | }, [commentURL]);
52 |
53 | useEffect(() => {
54 | if (loading && commentURL) {
55 | if (dispatch) {
56 | createCommentViaDispatcher().catch(console.error);
57 | } else {
58 | createCommentTypedData().catch(console.error);
59 | }
60 | }
61 | }, [commentURL, loading]);
62 |
63 | return { comment, loading, error };
64 | };
65 |
--------------------------------------------------------------------------------
/src/hooks/combined/follow.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { useCreateFollowTypedData, useCreateUnfollowTypedData } from "../api/follow";
5 | import { useBroadcastAPIHook } from "../utils/broadcast";
6 | import { useSignTypedData } from "../utils/sign";
7 |
8 | export const useFollow = (
9 | profileId: string,
10 | onFunctions?: OnFunctions,
11 | ): { follow: () => void; loading: boolean; error: Error | null } => {
12 | const [createFollowTypedData, { data: followTypedData }] = useCreateFollowTypedData(profileId);
13 |
14 | const signReturn = useSignTypedData(followTypedData?.createFollowTypedData?.typedData);
15 |
16 | const {
17 | start: follow,
18 | loading,
19 | error,
20 | } = useBroadcastAPIHook(followTypedData?.createFollowTypedData?.id, undefined, signReturn, onFunctions);
21 |
22 | useEffect(() => {
23 | loading && createFollowTypedData().catch(console.error);
24 | }, [profileId, loading]);
25 |
26 | return { follow, loading, error };
27 | };
28 |
29 | export const useUnfollow = (
30 | profileId: string,
31 | onFunctions: OnFunctions,
32 | ): { unfollow: () => void; loading: boolean; error: Error | null } => {
33 | const [createUnfollowTypedData, { data: unfollowTypedData }] = useCreateUnfollowTypedData(profileId);
34 |
35 | const signReturn = useSignTypedData(unfollowTypedData?.createUnfollowTypedData?.typedData);
36 |
37 | const {
38 | start: unfollow,
39 | loading,
40 | error,
41 | } = useBroadcastAPIHook(unfollowTypedData?.createUnfollowTypedData?.id, undefined, signReturn, onFunctions);
42 |
43 | useEffect(() => {
44 | loading && createUnfollowTypedData().catch(console.error);
45 | }, [profileId, loading]);
46 |
47 | return { unfollow, loading, error };
48 | };
49 |
--------------------------------------------------------------------------------
/src/hooks/combined/mirror.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { useCreateMirrorTypedData, useCreateMirrorViaDispatcher } from "../api/mirror";
5 | import { useProfileHasDispatcher } from "../api/profile";
6 | import { useBroadcastAPIHook } from "../utils/broadcast";
7 | import { useSignTypedData } from "../utils/sign";
8 |
9 | export const useMirror = (
10 | profileId: string | undefined,
11 | publicationId: string | undefined,
12 | onFunctions?: OnFunctions,
13 | ): { mirror: () => void; loading: boolean; error: Error | null } => {
14 | const dispatch = useProfileHasDispatcher(profileId);
15 | const [createMirrorTypedData, { data: mirrorTypedData }] = useCreateMirrorTypedData(profileId, publicationId);
16 |
17 | const [createMirrorViaDispatcher, { data: mirrorViaDispatcher }] = useCreateMirrorViaDispatcher(
18 | profileId,
19 | publicationId,
20 | );
21 |
22 | const signReturn = useSignTypedData(mirrorTypedData?.createMirrorTypedData?.typedData);
23 |
24 | const {
25 | start: mirror,
26 | loading,
27 | error,
28 | } = useBroadcastAPIHook(
29 | mirrorTypedData?.createMirrorTypedData?.id,
30 | mirrorViaDispatcher?.createMirrorViaDispatcher,
31 | signReturn,
32 | onFunctions,
33 | );
34 |
35 | useEffect(() => {
36 | if (loading) {
37 | if (dispatch) {
38 | createMirrorViaDispatcher().catch(console.error);
39 | } else {
40 | createMirrorTypedData().catch(console.error);
41 | }
42 | }
43 | }, [profileId, publicationId, loading]);
44 |
45 | return { mirror, loading, error };
46 | };
47 |
--------------------------------------------------------------------------------
/src/hooks/combined/post.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { publicationIdFromReceipt } from "../../utils/tx";
5 | import { useCreatePostTypedData, useCreatePostViaDispatcher } from "../api/post";
6 | import { useProfileHasDispatcher } from "../api/profile";
7 | import { useBroadcastAPIHook } from "../utils/broadcast";
8 | import { useSignTypedData } from "../utils/sign";
9 |
10 | export const usePost = (
11 | profileId: string | undefined,
12 | postURL: string | undefined,
13 | { onBroadcasted, onCompleted }: OnFunctions = { onBroadcasted: undefined, onCompleted: undefined },
14 | ): {
15 | post: () => void;
16 | loading: boolean;
17 | error: Error | null;
18 | publicationId: string | undefined;
19 | } => {
20 | const dispatch = useProfileHasDispatcher(profileId);
21 |
22 | const [publicationId, setPublicationId] = useState(undefined);
23 |
24 | const [createPostTypedData, { data: postTypedData, reset: resetTypedData }] = useCreatePostTypedData(
25 | profileId,
26 | postURL,
27 | {
28 | freeCollectModule: {
29 | followerOnly: false,
30 | },
31 | },
32 | );
33 |
34 | const [createPostViaDispatcher, { data: postViaDispatcher, reset: resetViaDispatcher }] = useCreatePostViaDispatcher(
35 | profileId,
36 | postURL,
37 | {
38 | freeCollectModule: {
39 | followerOnly: false,
40 | },
41 | },
42 | );
43 |
44 | const signReturn = useSignTypedData(postTypedData?.createPostTypedData?.typedData);
45 |
46 | const {
47 | start: post,
48 | loading,
49 | error,
50 | } = useBroadcastAPIHook(
51 | postTypedData?.createPostTypedData?.id,
52 | postViaDispatcher?.createPostViaDispatcher,
53 | signReturn,
54 | {
55 | onCompleted(receipt) {
56 | const parsedPublicationId = publicationIdFromReceipt(receipt);
57 | setPublicationId(parsedPublicationId);
58 | onCompleted?.(receipt);
59 | },
60 | onBroadcasted,
61 | },
62 | );
63 |
64 | useEffect(() => {
65 | resetTypedData();
66 | resetViaDispatcher();
67 | }, [postURL]);
68 |
69 | useEffect(() => {
70 | if (loading && postURL) {
71 | if (dispatch) {
72 | createPostViaDispatcher().catch(console.error);
73 | } else {
74 | createPostTypedData().catch(console.error);
75 | }
76 | }
77 | }, [postURL, loading]);
78 |
79 | return { post, loading, error, publicationId };
80 | };
81 |
--------------------------------------------------------------------------------
/src/hooks/contract/collect.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, usePrepareContractWrite } from "wagmi";
2 |
3 | import LensHubAbi from "../../assets/abi/lenshub.json";
4 | import { useLensHubAddress } from "../../context/LensContext";
5 | import { ContractReturn } from ".";
6 |
7 | export const useContractCollect = (profileId?: string, pubId?: string, dataBytes?: string): ContractReturn => {
8 | const addressOrName = useLensHubAddress();
9 |
10 | const { config, error: prepareError } = usePrepareContractWrite({
11 | addressOrName,
12 | contractInterface: LensHubAbi,
13 | functionName: "collect",
14 | args: [profileId, pubId, dataBytes],
15 | enabled: profileId !== undefined && pubId !== undefined,
16 | });
17 |
18 | const { write, data, error: writeError, status } = useContractWrite(config);
19 |
20 | return { write, data, prepareError, writeError, status };
21 | };
22 |
--------------------------------------------------------------------------------
/src/hooks/contract/comment.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, usePrepareContractWrite } from "wagmi";
2 |
3 | import LensHubAbi from "../../assets/abi/lenshub.json";
4 | import { useLensHubAddress } from "../../context/LensContext";
5 | import { ContractReturn } from ".";
6 |
7 | export const useContractComment = (
8 | profileId?: string,
9 | contentURI?: string,
10 | profileIdPointed?: string,
11 | pubIdPointed?: string,
12 | collectModule?: string,
13 | collectModuleInitData?: string,
14 | referenceModule?: string,
15 | referenceModuleInitData?: string,
16 | referenceModuleData?: string,
17 | ): ContractReturn => {
18 | const addressOrName = useLensHubAddress();
19 |
20 | const { config, error: prepareError } = usePrepareContractWrite({
21 | addressOrName,
22 | contractInterface: LensHubAbi,
23 | functionName: "comment",
24 | args: [
25 | {
26 | profileId,
27 | contentURI,
28 | profileIdPointed,
29 | pubIdPointed,
30 | collectModule,
31 | collectModuleInitData,
32 | referenceModule,
33 | referenceModuleInitData,
34 | referenceModuleData,
35 | },
36 | ],
37 | enabled:
38 | profileId !== undefined &&
39 | contentURI !== undefined &&
40 | profileIdPointed !== undefined &&
41 | pubIdPointed !== undefined &&
42 | collectModule !== undefined &&
43 | collectModuleInitData !== undefined &&
44 | referenceModule !== undefined &&
45 | referenceModuleInitData !== undefined &&
46 | referenceModuleData !== undefined,
47 | });
48 |
49 | const { write, data, error: writeError, status } = useContractWrite(config);
50 |
51 | return { write, data, prepareError, writeError, status };
52 | };
53 |
--------------------------------------------------------------------------------
/src/hooks/contract/follow.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, usePrepareContractWrite } from "wagmi";
2 |
3 | import FollowNFTAbi from "../../assets/abi/follow-nft.json";
4 | import LensHubAbi from "../../assets/abi/lenshub.json";
5 | import { useLensHubAddress } from "../../context/LensContext";
6 | import { ContractReturn } from ".";
7 |
8 | export const useContractFollow = (profileIds?: string[], datas?: string[]): ContractReturn => {
9 | const addressOrName = useLensHubAddress();
10 |
11 | const { config, error: prepareError } = usePrepareContractWrite({
12 | addressOrName,
13 | contractInterface: LensHubAbi,
14 | functionName: "follow",
15 | args: [profileIds, datas],
16 | enabled: profileIds !== undefined && profileIds.length > 0 && datas !== undefined && datas.length > 0,
17 | });
18 |
19 | const { write, data, error: writeError, status } = useContractWrite(config);
20 |
21 | return { write, data, prepareError, writeError, status };
22 | };
23 |
24 | export const useContractUnfollow = (followNFTAddress?: string, tokenId?: string): ContractReturn => {
25 | const { config, error: prepareError } = usePrepareContractWrite({
26 | contractInterface: FollowNFTAbi,
27 | addressOrName: followNFTAddress ?? "",
28 | functionName: "burn",
29 | args: [tokenId],
30 | enabled: followNFTAddress !== undefined && tokenId !== undefined,
31 | });
32 |
33 | const { write, data, error: writeError, status } = useContractWrite(config);
34 |
35 | return { write, data, prepareError, writeError, status };
36 | };
37 |
--------------------------------------------------------------------------------
/src/hooks/contract/index.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, useSignTypedData } from "wagmi";
2 |
3 | export interface ContractReturn {
4 | data: import("@wagmi/core").SendTransactionResult | undefined;
5 | status: ReturnType["status"];
6 | prepareError: Error | null;
7 | writeError: Error | null;
8 | write: ReturnType["write"];
9 | }
10 |
11 | export interface SignReturn {
12 | data: string | undefined;
13 | status: ReturnType["status"];
14 | error: Error | null;
15 | signTypedData: ReturnType["signTypedData"];
16 | }
17 |
--------------------------------------------------------------------------------
/src/hooks/contract/mirror.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, usePrepareContractWrite } from "wagmi";
2 |
3 | import LensHubAbi from "../../assets/abi/lenshub.json";
4 | import { useLensHubAddress } from "../../context/LensContext";
5 | import { ContractReturn } from ".";
6 |
7 | export const useContractMirror = (
8 | profileId?: string,
9 | profileIdPointed?: string,
10 | pubIdPointed?: string,
11 | referenceModuleData?: string,
12 | referenceModule?: string,
13 | referenceModuleInitData?: string,
14 | ): ContractReturn => {
15 | const addressOrName = useLensHubAddress();
16 |
17 | const { config, error: prepareError } = usePrepareContractWrite({
18 | addressOrName,
19 | contractInterface: LensHubAbi,
20 | functionName: "mirror",
21 | args: [
22 | { profileId, profileIdPointed, pubIdPointed, referenceModuleData, referenceModule, referenceModuleInitData },
23 | ],
24 | enabled:
25 | profileId !== undefined &&
26 | profileIdPointed !== undefined &&
27 | pubIdPointed !== undefined &&
28 | referenceModuleData !== undefined &&
29 | referenceModule !== undefined &&
30 | referenceModuleInitData !== undefined,
31 | });
32 |
33 | const { write, data, error: writeError, status } = useContractWrite(config);
34 |
35 | return { write, data, prepareError, writeError, status };
36 | };
37 |
--------------------------------------------------------------------------------
/src/hooks/contract/post.ts:
--------------------------------------------------------------------------------
1 | import { useContractWrite, usePrepareContractWrite } from "wagmi";
2 |
3 | import LensHubAbi from "../../assets/abi/lenshub.json";
4 | import { useLensHubAddress } from "../../context/LensContext";
5 | import { ContractReturn } from ".";
6 |
7 | export const useContractPost = (
8 | profileId?: string,
9 | contentURI?: string,
10 | collectModule?: string,
11 | collectModuleInitData?: string,
12 | referenceModule?: string,
13 | referenceModuleInitData?: string,
14 | ): ContractReturn => {
15 | const addressOrName = useLensHubAddress();
16 |
17 | const { config, error: prepareError } = usePrepareContractWrite({
18 | addressOrName,
19 | contractInterface: LensHubAbi,
20 | functionName: "post",
21 | args: [
22 | {
23 | profileId,
24 | contentURI,
25 | collectModule,
26 | collectModuleInitData,
27 | referenceModule,
28 | referenceModuleInitData,
29 | },
30 | ],
31 | enabled:
32 | profileId !== undefined &&
33 | contentURI !== undefined &&
34 | collectModule !== undefined &&
35 | collectModuleInitData !== undefined &&
36 | referenceModule !== undefined &&
37 | referenceModuleInitData !== undefined,
38 | });
39 |
40 | const { write, data, error: writeError, status } = useContractWrite(config);
41 |
42 | return { write, data, prepareError, writeError, status };
43 | };
44 |
--------------------------------------------------------------------------------
/src/hooks/contract/profile.ts:
--------------------------------------------------------------------------------
1 | import { useContractRead } from "wagmi";
2 |
3 | import LensHubAbi from "../../assets/abi/lenshub.json";
4 | import { useLensHubAddress } from "../../context/LensContext";
5 |
6 | export const useContractProfile = (profileId?: string): ReturnType => {
7 | const addressOrName = useLensHubAddress();
8 |
9 | return useContractRead({
10 | addressOrName,
11 | contractInterface: LensHubAbi,
12 | functionName: "getProfile",
13 | args: [profileId],
14 | enabled: profileId !== undefined,
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/src/hooks/utils/broadcast.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | import { OnFunctions } from "../../types/on";
4 | import { FailedBroadcast, SuccessfulBroadcast, useBroadcast, wasSuccessfulBroadcast } from "../api/broadcast";
5 | import { useIndexed } from "../api/indexer";
6 | import { SignReturn } from "../contract";
7 |
8 | export const useBroadcastAPIHook = (
9 | id: string | undefined,
10 | dispatchBroadcast: SuccessfulBroadcast | FailedBroadcast | undefined,
11 | { signTypedData, error: signError, data, status }: SignReturn,
12 | { onBroadcasted, onCompleted }: OnFunctions = { onBroadcasted: undefined, onCompleted: undefined },
13 | ): { start: () => void; loading: boolean; error: Error | null } => {
14 | const [loading, setLoading] = useState(false);
15 | const [writing, setWriting] = useState(false);
16 | const [broadcasting, setBroadcasting] = useState(false);
17 | const [error, setError] = useState(null);
18 | const [txId, setTxId] = useState();
19 |
20 | const [broadcast, { data: broadcastData }] = useBroadcast(id, data);
21 |
22 | const { data: indexedData } = useIndexed(txId, broadcasting);
23 |
24 | useEffect(() => {
25 | if (loading && !writing && id && signTypedData) {
26 | setWriting(true);
27 | signTypedData();
28 | }
29 | }, [signTypedData, loading, id]);
30 |
31 | useEffect(() => {
32 | if (status === "error") {
33 | setError(signError);
34 | }
35 | }, [signError]);
36 |
37 | useEffect(() => {
38 | if (status === "error") {
39 | setLoading(false);
40 | setWriting(false);
41 | setBroadcasting(false);
42 | }
43 | }, [status]);
44 |
45 | useEffect(() => {
46 | if (!broadcasting) {
47 | if (dispatchBroadcast && wasSuccessfulBroadcast(dispatchBroadcast)) {
48 | setBroadcasting(true);
49 | setTxId(dispatchBroadcast.txId);
50 | } else if (id && data) {
51 | setBroadcasting(true);
52 | broadcast().catch(console.error);
53 | }
54 | }
55 | }, [id, data, dispatchBroadcast]);
56 |
57 | useEffect(() => {
58 | if (broadcastData?.broadcast && broadcasting) {
59 | if (wasSuccessfulBroadcast(broadcastData.broadcast)) {
60 | setTxId(broadcastData.broadcast.txId);
61 | } else {
62 | setBroadcasting(false);
63 | setLoading(false);
64 | setWriting(false);
65 | setError(new Error(broadcastData.broadcast.reason));
66 | onCompleted?.();
67 | }
68 | }
69 | }, [broadcastData]);
70 |
71 | useEffect(() => {
72 | if (txId && broadcasting) {
73 | if (indexedData?.hasTxHashBeenIndexed?.txReceipt) {
74 | onBroadcasted?.(indexedData?.hasTxHashBeenIndexed?.txReceipt);
75 | }
76 |
77 | if (indexedData?.hasTxHashBeenIndexed?.indexed) {
78 | setBroadcasting(false);
79 | setLoading(false);
80 | setWriting(false);
81 | if (indexedData?.hasTxHashBeenIndexed?.metadataStatus?.status === "METADATA_VALIDATION_FAILED") {
82 | setError(new Error(indexedData.hasTxHashBeenIndexed.metadataStatus.reason));
83 | } else {
84 | onCompleted?.(indexedData.hasTxHashBeenIndexed.txReceipt);
85 | }
86 | }
87 | }
88 | }, [indexedData]);
89 |
90 | const start = (): void => {
91 | setLoading(true);
92 | };
93 |
94 | return { start, loading, error };
95 | };
96 |
--------------------------------------------------------------------------------
/src/hooks/utils/contract.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | import { ContractReturn } from "../contract";
4 |
5 | export const useContractAPIHook = (
6 | { write, writeError, prepareError, data, status }: ContractReturn,
7 | onCompleted?: (hash?: string) => void,
8 | ): { start: () => void; loading: boolean; error: Error | null } => {
9 | const [loading, setLoading] = useState(false);
10 | const [writing, setWriting] = useState(false);
11 | const [error, setError] = useState(null);
12 |
13 | useEffect(() => {
14 | if (loading && !writing && write) {
15 | setWriting(true);
16 | write();
17 | }
18 | }, [write, loading]);
19 |
20 | useEffect(() => {
21 | if (status === "error") {
22 | setError(writeError);
23 | }
24 | }, [writeError]);
25 |
26 | useEffect(() => {
27 | if (status === "error") {
28 | setError(prepareError);
29 | }
30 | }, [prepareError]);
31 |
32 | useEffect(() => {
33 | if (status === "error") {
34 | setLoading(false);
35 | setWriting(false);
36 | }
37 | }, [status]);
38 |
39 | useEffect(() => {
40 | data
41 | ?.wait(1)
42 | .then((receipt) => {
43 | setLoading(false);
44 | setWriting(false);
45 | onCompleted?.(receipt.transactionHash);
46 | })
47 | .catch((error) => {
48 | setLoading(false);
49 | setWriting(false);
50 | setError(error);
51 | onCompleted?.();
52 | });
53 | }, [data]);
54 |
55 | const start = (): void => {
56 | setLoading(true);
57 | };
58 |
59 | return { start, loading, error };
60 | };
61 |
--------------------------------------------------------------------------------
/src/hooks/utils/sign.ts:
--------------------------------------------------------------------------------
1 | import { useSignTypedData as useSignTypedDataWagmi } from "wagmi";
2 |
3 | import { TypedData } from "../../types/lens";
4 | import { omitDeep } from "../../utils/omit-deep";
5 | import { SignReturn } from "../contract";
6 |
7 | export const useSignTypedData = (toSign: TypedData | undefined): SignReturn => {
8 | return useSignTypedDataWagmi({
9 | domain: omitDeep(toSign?.domain, "__typename"),
10 | types: omitDeep(toSign?.types, "__typename"),
11 | value: omitDeep(toSign?.value, "__typename"),
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { useAuthenticate, useChallenge, useRefresh } from "./hooks/api/login";
2 | import {
3 | useDefaultProfile,
4 | useProfile,
5 | useProfileHasDispatcher,
6 | useProfilePicture,
7 | useProfiles,
8 | } from "./hooks/api/profile";
9 | import { usePublication, usePublicationComments, usePublications } from "./hooks/api/publication";
10 | import { useSearch } from "./hooks/api/search";
11 | import { useCollect } from "./hooks/combined/collect";
12 | import { useComment } from "./hooks/combined/comment";
13 | import { useFollow, useUnfollow } from "./hooks/combined/follow";
14 | import { useMirror } from "./hooks/combined/mirror";
15 | import { usePost } from "./hooks/combined/post";
16 | import { useContractCollect } from "./hooks/contract/collect";
17 | import { useContractComment } from "./hooks/contract/comment";
18 | import { useContractFollow, useContractUnfollow } from "./hooks/contract/follow";
19 | import { useContractMirror } from "./hooks/contract/mirror";
20 | import { useContractPost } from "./hooks/contract/post";
21 | import { useContractProfile } from "./hooks/contract/profile";
22 | import { PublicationType } from "./types/lens";
23 |
24 | export {
25 | PublicationType,
26 | useAuthenticate,
27 | useChallenge,
28 | useCollect,
29 | useComment,
30 | useContractCollect,
31 | useContractComment,
32 | useContractFollow,
33 | useContractMirror,
34 | useContractPost,
35 | useContractProfile,
36 | useContractUnfollow,
37 | useDefaultProfile,
38 | useFollow,
39 | useMirror,
40 | usePost,
41 | useProfile,
42 | useProfileHasDispatcher,
43 | useProfilePicture,
44 | useProfiles,
45 | usePublication,
46 | usePublicationComments,
47 | usePublications,
48 | useRefresh,
49 | useSearch,
50 | useUnfollow,
51 | };
52 |
--------------------------------------------------------------------------------
/src/types/error.ts:
--------------------------------------------------------------------------------
1 | export type MetamaskError = Error & {
2 | code: "ACTION_REJECTED";
3 | reason: string;
4 | };
5 |
6 | export enum RelayErrorReasons {
7 | REJECTED = "REJECTED",
8 | EXPIRED = "EXPIRED",
9 | WRONG_WALLET_SIGNED = "WRONG_WALLET_SIGNED",
10 | NOT_ALLOWED = "NOT_ALLOWED",
11 | }
12 |
--------------------------------------------------------------------------------
/src/types/lens.ts:
--------------------------------------------------------------------------------
1 | import { MetadataResponse } from "./metadata";
2 |
3 | export interface Profile {
4 | profileId: string;
5 | name?: string;
6 | handle: string;
7 | picture?: {
8 | original?: {
9 | url?: string;
10 | };
11 | };
12 | ownedBy: string;
13 | isFollowedByMe?: boolean;
14 | stats: {
15 | totalFollowers: number;
16 | totalFollowing: number;
17 | totalPosts: number;
18 | totalComments: number;
19 | totalMirrors: number;
20 | totalPublications: number;
21 | totalCollects: number;
22 | };
23 | }
24 |
25 | export interface DefaultProfile extends Omit {
26 | id: string;
27 | }
28 |
29 | export enum PublicationSortCriteria {
30 | TOP_COMMENTED = "TOP_COMMENTED",
31 | TOP_COLLECTED = "TOP_COLLECTED",
32 | TOP_MIRRORED = "TOP_MIRRORED",
33 | CURATED_PROFILES = "CURATED_PROFILES",
34 | LATEST = "LATEST",
35 | }
36 |
37 | export enum PublicationType {
38 | POST = "POST",
39 | COMMENT = "COMMENT",
40 | MIRROR = "MIRROR",
41 | }
42 |
43 | export enum TimelineTypes {
44 | POST = "POST",
45 | COMMENT = "COMMENT",
46 | MIRROR = "MIRROR",
47 | COLLECT_POST = "COLLECT_POST",
48 | COLLECT_COMMENT = "COLLECT_COMMENT",
49 | }
50 |
51 | // Relevant data from a post
52 | export interface Post {
53 | id: string;
54 | profile: Profile;
55 | stats: {
56 | totalAmountOfMirrors: number;
57 | totalAmountOfCollects: number;
58 | totalAmountOfComments: number;
59 | };
60 | metadata: MetadataResponse;
61 | createdAt: string;
62 | collectedBy: {
63 | address: string;
64 | };
65 | hasCollectedByMe?: boolean;
66 | mirrors?: string[];
67 | mirrorOf?: Post;
68 | appId?: string;
69 | }
70 |
71 | export interface PostWithMedia extends Post {
72 | metadata: MetadataResponse;
73 | }
74 |
75 | export function postHasMedia(post: Post): post is PostWithMedia {
76 | return (post as PostWithMedia).metadata.media !== undefined && (post as PostWithMedia).metadata.media.length > 0;
77 | }
78 |
79 | export interface PageInfo {
80 | prev: string;
81 | next: string;
82 | totalCount: number;
83 | }
84 |
85 | export interface TypedData {
86 | types: any;
87 | domain: any;
88 | value: any;
89 | }
90 |
91 | export interface TypedDataResponse {
92 | id: string;
93 | expiresAt: string;
94 | typedData: TypedData;
95 | }
96 |
--------------------------------------------------------------------------------
/src/types/metadata.ts:
--------------------------------------------------------------------------------
1 | export interface PublicationMetadataMedia {
2 | item: string;
3 | /**
4 | * This is the mime type of media
5 | */
6 | type?: string | null;
7 |
8 | /**
9 | * The alt tags for accessibility
10 | */
11 | altTag?: string | null;
12 |
13 | /**
14 | * The cover for any video or audio you attached
15 | */
16 | cover?: string | null;
17 | }
18 |
19 | export enum PublicationMetadataVersions {
20 | one = "1.0.0",
21 | // please use metadata v2 when doing anything! v1 is supported but discontinued.
22 | two = "2.0.0",
23 | }
24 |
25 | export enum PublicationMetadataDisplayType {
26 | number = "number",
27 | string = "string",
28 | date = "date",
29 | }
30 |
31 | export interface PublicationMetadataAttribute {
32 | displayType?: PublicationMetadataDisplayType | undefined | null;
33 | traitType?: string | undefined | null;
34 | value: string;
35 | }
36 |
37 | export enum PublicationContentWarning {
38 | NSFW = "NSFW",
39 | SENSITIVE = "SENSITIVE",
40 | SPOILER = "SPOILER",
41 | }
42 |
43 | export enum PublicationMainFocus {
44 | VIDEO = "VIDEO",
45 | IMAGE = "IMAGE",
46 | ARTICLE = "ARTICLE",
47 | TEXT_ONLY = "TEXT_ONLY",
48 | AUDIO = "AUDIO",
49 | LINK = "LINK",
50 | EMBED = "EMBED",
51 | }
52 |
53 | export interface Metadata {
54 | /**
55 | * The metadata version.
56 | */
57 | version: PublicationMetadataVersions;
58 |
59 | /**
60 | * The metadata lens_id can be anything but if your uploading to ipfs
61 | * you will want it to be random.. using uuid could be an option!
62 | */
63 | metadata_id: string;
64 |
65 | /**
66 | * A human-readable description of the item. Can be markdown.
67 | */
68 | description?: string | undefined | null;
69 |
70 | /**
71 | * The content of a publication. Can be markdown. If this is blank `media` must be defined or its out of spec.
72 | */
73 | content?: string | undefined | null;
74 |
75 | /**
76 | * IOS 639-1 language code aka en or it and ISO 3166-1 alpha-2 region code aka US or IT aka en-US or it-IT
77 | * Full spec > https://tools.ietf.org/search/bcp47
78 | */
79 | locale: string;
80 |
81 | /**
82 | * Ability to tag your publication
83 | */
84 | tags?: string[] | undefined | null;
85 |
86 | /**
87 | * Ability to add a content warning
88 | */
89 | contentWarning?: PublicationContentWarning | undefined | null;
90 |
91 | /**
92 | * Main content focus that for this publication
93 | */
94 | mainContentFocus: PublicationMainFocus;
95 |
96 | /**
97 | * This is the URL that will appear below the asset's image on OpenSea and others etc
98 | * and will allow users to leave OpenSea and view the item on the site.
99 | */
100 | external_url?: string | undefined | null;
101 |
102 | /**
103 | * Name of the item.
104 | */
105 | name: string;
106 |
107 | /**
108 | * These are the attributes for the item, which will show up on the OpenSea and others NFT trading websites on the
109 | item.
110 | */
111 | attributes: PublicationMetadataAttribute[];
112 |
113 | /**
114 | * legacy to support OpenSea will store any NFT image here.
115 | */
116 | image?: string | undefined | null;
117 |
118 | /**
119 | * This is the mime type of image. This is used if you uploading more advanced cover images
120 | * as sometimes IPFS does not emit the content header so this solves the pr
121 | */
122 | imageMimeType?: string | undefined | null;
123 |
124 | /**
125 | * This is lens supported attached media items to the publication
126 | */
127 | media?: PublicationMetadataMedia[] | undefined | null;
128 |
129 | /**
130 | * In spec for OpenSea and other providers - also used when using EMBED main publication focus
131 | * A URL to a multi-media attachment for the item. The file extensions GLTF, GLB, WEBM, MP4, M4V, OGV,
132 | * and OGG are supported, along with the audio-only extensions MP3, WAV, and OGA.
133 | * Animation_url also supports HTML pages, allowing you to build rich experiences and interactive NFTs using JavaScript canvas,
134 | * WebGL, and more. Scripts and relative paths within the HTML page are now supported. However, access to browser extensions is not supported.
135 |
136 | */
137 | animation_url?: string | undefined | null;
138 |
139 | /**
140 | * This is the appId the content belongs to
141 | */
142 | appId?: string | undefined | null;
143 | }
144 |
145 | // Media object returned from Lens API is different than what is submitted
146 | export interface MetadataResponse extends Omit {
147 | media: Array<{
148 | original: {
149 | url?: string;
150 | width?: number;
151 | height?: number;
152 | mimeType?: string;
153 | };
154 | }>;
155 | }
156 |
--------------------------------------------------------------------------------
/src/types/modules.ts:
--------------------------------------------------------------------------------
1 | export interface CollectModule {
2 | freeCollectModule?: {
3 | followerOnly: boolean;
4 | };
5 | feeCollectModule?: {
6 | amount: {
7 | currency: string;
8 | value: string;
9 | };
10 | recipient: string;
11 | referralFee: number;
12 | followerOnly: boolean;
13 | };
14 | }
15 |
16 | export interface ReferenceModule {
17 | followerOnlyReferenceModule: boolean;
18 | }
19 |
--------------------------------------------------------------------------------
/src/types/on.ts:
--------------------------------------------------------------------------------
1 | import { TransactionReceipt } from "@ethersproject/abstract-provider";
2 |
3 | export type OnBroadcastedFunction = ((receipt: TransactionReceipt) => void) | undefined;
4 | export type OnCompletedFunction = ((receipt?: TransactionReceipt) => void) | undefined;
5 |
6 | export interface OnFunctions {
7 | onBroadcasted?: OnBroadcastedFunction;
8 | onCompleted?: OnCompletedFunction;
9 | }
10 |
--------------------------------------------------------------------------------
/src/utils/omit-deep.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | function has(obj: any, prop: any): boolean {
3 | return Function.prototype.bind.call(Function.call, Object.prototype.hasOwnProperty)(obj, prop);
4 | }
5 |
6 | function isUnsafeKey(key: any) {
7 | return key === "__proto__" || key === "constructor" || key === "prototype";
8 | }
9 |
10 | function validateKey(key: any) {
11 | if (isUnsafeKey(key)) {
12 | throw new Error(`Cannot set unsafe key: "${key}"`);
13 | }
14 | }
15 |
16 | function unset(obj: any, prop: any) {
17 | if (!isObject(obj)) {
18 | throw new TypeError("expected an object.");
19 | }
20 |
21 | var isArray = Array.isArray(prop);
22 |
23 | if (!isArray && obj.hasOwnProperty(prop)) {
24 | delete obj[prop];
25 | return true;
26 | }
27 |
28 | if (has(obj, prop)) {
29 | var segs = isArray ? prop.slice() : prop.split(".");
30 | var last = segs.pop();
31 | while (segs.length && segs[segs.length - 1].slice(-1) === "\\") {
32 | last = segs.pop().slice(0, -1) + "." + last;
33 | }
34 | while (segs.length) {
35 | prop = segs.shift();
36 | validateKey(prop);
37 | obj = obj[prop];
38 | }
39 | return delete obj[last];
40 | }
41 | return true;
42 | }
43 |
44 | function isObject(o: any) {
45 | return Object.prototype.toString.call(o) === "[object Object]";
46 | }
47 |
48 | function isPlainObject(o: any) {
49 | var ctor, prot;
50 |
51 | if (isObject(o) === false) return false;
52 |
53 | // If has modified constructor
54 | ctor = o.constructor;
55 | if (ctor === undefined) return true;
56 |
57 | // If has modified prototype
58 | prot = ctor.prototype;
59 | if (isObject(prot) === false) return false;
60 |
61 | // If constructor does not have an Object-specific method
62 | if (prot.hasOwnProperty("isPrototypeOf") === false) {
63 | return false;
64 | }
65 |
66 | // Most likely a plain Object
67 | return true;
68 | }
69 |
70 | export function omitDeep(value: any, keys: any) {
71 | if (typeof value === "undefined") {
72 | return {};
73 | }
74 |
75 | if (Array.isArray(value)) {
76 | for (var i = 0; i < value.length; i++) {
77 | value[i] = omitDeep(value[i], keys);
78 | }
79 | return value;
80 | }
81 |
82 | if (!isPlainObject(value)) {
83 | return value;
84 | }
85 |
86 | if (typeof keys === "string") {
87 | keys = [keys];
88 | }
89 |
90 | if (!Array.isArray(keys)) {
91 | return value;
92 | }
93 |
94 | for (var j = 0; j < keys.length; j++) {
95 | unset(value, keys[j]);
96 | }
97 |
98 | for (var key in value) {
99 | if (value.hasOwnProperty(key)) {
100 | value[key] = omitDeep(value[key], keys);
101 | }
102 | }
103 |
104 | return value;
105 | }
106 |
--------------------------------------------------------------------------------
/src/utils/tx.ts:
--------------------------------------------------------------------------------
1 | import { TransactionReceipt } from "@ethersproject/abstract-provider";
2 | import { ethers } from "ethers";
3 |
4 | export const publicationIdFromReceipt = (receipt: TransactionReceipt | undefined): string | undefined => {
5 | if (receipt?.logs[0] && receipt.logs[0].topics.length === 3) {
6 | let profileId = ethers.utils.hexStripZeros(receipt?.logs[0].topics[1]);
7 | if (profileId.length % 2 === 1) {
8 | profileId = `${profileId.substring(0, 2)}0${profileId.substring(2)}`;
9 | }
10 | let postId = ethers.utils.hexStripZeros(receipt?.logs[0].topics[2]);
11 | if (postId.length % 2 === 1) {
12 | postId = `${postId.substring(0, 2)}0${postId.substring(2)}`;
13 | }
14 |
15 | return `${profileId}-${postId}`;
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": false,
4 | "allowSyntheticDefaultImports": true,
5 | "declaration": true,
6 | "esModuleInterop": false,
7 | "forceConsistentCasingInFileNames": true,
8 | "isolatedModules": true,
9 | "jsx": "react-jsx",
10 | "lib": ["es2019", "es2017", "dom"],
11 | "module": "commonjs",
12 | "moduleResolution": "node",
13 | "outDir": "dist",
14 | "resolveJsonModule": true,
15 | "skipLibCheck": true,
16 | "strict": true,
17 | "target": "es2021",
18 | "useDefineForClassFields": true
19 | },
20 | "exclude": ["node_modules", "**/dist/**"],
21 | "include": ["./src/**/*.ts", "./src/**/*.tsx"]
22 | }
23 |
--------------------------------------------------------------------------------