├── .gitignore ├── .prettierignore ├── .prettierrc ├── README.md ├── db-schema.svg ├── functions ├── Dockerfile ├── README.md ├── index-accounts.js ├── index-activities.js ├── index-directories.js ├── index-opengraphs.js ├── lib │ ├── crypto.js │ ├── db.js │ ├── farcaster-api.js │ ├── graph.js │ ├── scraper.js │ └── utils.js ├── package.json └── yarn.lock └── subgraph └── registry-v2 ├── abis ├── IdRegistry.json └── NameRegistry.json ├── networks.json ├── package.json ├── schema.graphql ├── src ├── id-registry.ts └── name-registry.ts ├── subgraph.yaml ├── tests ├── id-registry-utils.ts ├── id-registry.test.ts ├── name-registry-utils.ts └── name-registry.test.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | build/ 4 | generated/ 5 | 6 | # misc 7 | .DS_Store 8 | output.txt 9 | 10 | # debug 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | .pnpm-debug.log* 15 | 16 | # vim 17 | *.swp 18 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | /.pnp 4 | .pnp.js 5 | 6 | # testing 7 | /coverage 8 | 9 | # next.js 10 | /.next/ 11 | /out/ 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | *.pem 19 | 20 | # debug 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .pnpm-debug.log* 25 | 26 | # local env files 27 | .env*.local 28 | 29 | # vercel 30 | .vercel 31 | 32 | # typescript 33 | *.tsbuildinfo 34 | 35 | # vim 36 | *.swp 37 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "bracketSpacing": true, 6 | "semi": false, 7 | "bracketSameLine": true 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Farcaster Indexer 2 | 3 | This software indexes [Farcaster](https://farcaster.xyz) data into a Supabase database. The primary purpose of the database is to serve [Farcaster News](https://www.farcasternews.xyz). 4 | 5 | We are opening read-only database access to the public with the hope of accelerating permissionless innovation on the Farcaster Protocol by making it easy to start a new project. We don't provide an SLA and strongly encourage you to run your own indexer and database once your project takes off. 6 | 7 | IMPORTANT: Our database is no longer up to date since the [Farcaster contract upgrade](https://www.notion.so/Migration-Guide-Phase-I-f34bf0b713924ba6b9652b6bb4fe44ef). 8 | 9 | ## Accessing our database 10 | 11 | You can use the Supabase [JS client](https://supabase.com/docs/reference/javascript/installing), [Dart client](https://supabase.com/docs/installing), or [REST API](https://supabase.com/docs/guides/api#rest-api-overview) to access our database with the following config: 12 | 13 | - Project URL: `https://kpwbglpxjuhiqtgtvenz.supabase.co` 14 | - API key: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imtwd2JnbHB4anVoaXF0Z3R2ZW56Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTgzNzg2MjEsImV4cCI6MTk3Mzk1NDYyMX0.zecokpSRK0MI_nOaSAgFZJCMkPSpEXraPKqQD5fogE4` 15 | 16 | The following views are available: 17 | ![DB schema](db-schema.svg) 18 | 19 | Please see the following sections for more fields and other details: 20 | 21 | ### account_view 22 | 23 | We check updates to [Farcaster name registry](https://www.farcaster.xyz/docs/the-basics#name-registry) every 5 minutes and reflect user registrations, username transfer, and directory URL changes to our database. We scrape directory, proof, and profile URLs at the rate of 4000 accounts per hour in case there are updates. 24 | 25 | The following fields are available in `account_view`: 26 | 27 | - `id`: Primary key of the view 28 | - `address` (not nullable, unique): From Farcaster name registry 29 | - `username` (not nullable, unique): From Farcaster name registry 30 | - `display_name` (nullable): From directory 31 | - `avatar_url` (nullable): From directory 32 | - `bio` (nullable): From profile API 33 | - `num_followings` (nullable): From profile API 34 | - `num_followers` (nullable): From profile API 35 | - `url` (not nullable): Directory URL from Farcaster name registry 36 | - `activity_url` (nullable) From directory 37 | - `proof_url` (nullable) From directory 38 | - `merkle_root` (nullable): From directory 39 | - `signature` (nullable): From directory 40 | - `directory_raw_data` (nullable): Raw JSON of the directory 41 | - `signed_message` (nullable): From proof 42 | - `signer_address` (nullable): From proof 43 | - `farcaster_address` (nullable): From proof 44 | - `original_message` (nullable): From proof 45 | - `proof_raw_data` (nullable): Raw JSON of the proof 46 | - `entry_created_at` (not nullable): Tx timestamp of registration 47 | - `entry_updated_at` (not nullable): Tx timestamp of updates to the registry 48 | - `latest_activity_sequence` (nullable): The latest activity sequence 49 | - `directory_updated_at` (nullable): Timestamp of the last time we scraped the directory URL 50 | - `activity_updated_at` (nullable): Timestamp of the last time we scraped the activity URL 51 | 52 | ### activity_view 53 | 54 | We scrape activity URLs at the rate of 6000 accounts per hour. We index all new activities. Reactions, recasts, watches, and reply counts are updated up to the 20 most recent activities or posted within the past 2 weeks per account. If an activity is deleted, the row disappears from the view. 55 | 56 | The following fields are available in `activity_view`: 57 | 58 | - `id` (not nullable, unique): Primary key of the view 59 | - `account` (not nullable): ID of the account that posted the text 60 | - `sequence` (not nullable) 61 | - `text` (not nullable) 62 | - `published_at` (not nullable) 63 | - `num_reply_children` (not nullable) 64 | - `reactions_count` (not nullable) 65 | - `recasts_count` (not nullable) 66 | - `watches_count` (not nullable) 67 | - `reply_to` (nullable): ID of the activity this text is replying to 68 | - `merkle_root` (not nullable) 69 | - `signature` (not nullable) 70 | - `prev_merkle_root` (not nullable) 71 | - `recast_merkle_root` (not nullable) 72 | - `raw_data` (not nullable): Raw JSON of the activity 73 | 74 | There is a unique constraint on `account` and `sequence`. 75 | 76 | ### opengraph_view 77 | 78 | We extract URLs from `activity_view.text` and scrape the opengraph. Note that we perform our own scraping, so these are different from the opengraph field you see in the content of the activity URL. 79 | 80 | The following fields are available in `opengraph_view`: 81 | 82 | - `id` (not nullable, unique): Primary key of the view 83 | - `normalized_url` (not nullable, unique) 84 | - `scraped_url` (not nullable, unique): Pre-normalized URL that we scraped 85 | - `type` (nullable): og:type 86 | - `url` (nullable): og:url 87 | - `title` (nullable): og:title 88 | - `description` (nullable): og:description 89 | - `image` (nullable): JSON that contains `url`, `width`, `height`, and `type` fields 90 | - `raw_data` (not nullable): Raw JSON of the scraped opengraph data 91 | 92 | ### activity_opengraph_view 93 | 94 | This view connects `activity_view` and `opengraph_view` as a many-to-many relationship. The absence of `activity` in this table indicates that we have not scraped URLs in the `activity_view.text` yet. `null` value for `opengraph` indicates that the indexer checked the `activity`, but no URLs or opengraph were detected. 95 | 96 | The following fields are available in `activity_opengraph_view`: 97 | 98 | - activity (not nullable, not unique): ID of `activity_view`. 99 | - opengraph (nullable, not unique): ID of `opengraph_view`. 100 | 101 | ## Want to contribute? 102 | 103 | Check out [some ideas here](https://github.com/lfglabs/farcaster-indexer/issues) 104 | 105 | ## Need help? 106 | 107 | You can DM me on [Twitter](https://twitter.com/kn). 108 | -------------------------------------------------------------------------------- /functions/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazon/aws-lambda-nodejs:16 2 | ARG MAIN 3 | COPY package.json ${LAMBDA_TASK_ROOT} 4 | RUN npm install 5 | COPY $MAIN ${LAMBDA_TASK_ROOT}/main.js 6 | COPY lib ${LAMBDA_TASK_ROOT}/lib 7 | CMD ["main.handler"] 8 | -------------------------------------------------------------------------------- /functions/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | 1. Install [Docker](https://docs.docker.com/get-started/) 4 | 1. Install [aws CLI](https://docs.aws.amazon.com/cli/v1/userguide/install-macos.html#awscli-install-osx-pip) 5 | 6 | # Test locally 7 | 8 | 1. Build the Docker image: 9 | 10 | ``` 11 | docker build -t lambda-index-fc-accounts --build-arg MAIN=index-accounts.js . 12 | ``` 13 | 14 | 2. Run the image: 15 | 16 | ``` 17 | docker run --rm -p 9000:8080 -e SUPABASE_API_KEY='' -e SUPABASE_URL='' -e GRAPH_API_URL='' lambda-index-fc-accounts 18 | ``` 19 | 20 | 3. Invoke the function: 21 | 22 | ``` 23 | aws lambda invoke \ 24 | --region us-east-2 \ 25 | --endpoint http://localhost:9000 \ 26 | --no-sign-request \ 27 | --function-name function \ 28 | output.txt 29 | ``` 30 | 31 | For other functions, replace `lambda-index-fc-accounts` and `index-accounts.js` with the corresponding name. 32 | 33 | # Deploy 34 | 35 | 1. Login to AWS ERC: 36 | 37 | ``` 38 | aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 985583747716.dkr.ecr.us-east-2.amazonaws.com 39 | ``` 40 | 41 | 2. Build the Docker image: 42 | 43 | ``` 44 | docker build -t lambda-index-fc-accounts --build-arg MAIN=index-accounts.js . 45 | ``` 46 | 47 | 3. Create a tag: 48 | 49 | ``` 50 | docker tag lambda-index-fc-accounts:latest 985583747716.dkr.ecr.us-east-2.amazonaws.com/lambda-index-fc-accounts:latest 51 | ``` 52 | 53 | 4. Push the latest image to our ERC repo: 54 | 55 | ``` 56 | docker push 985583747716.dkr.ecr.us-east-2.amazonaws.com/lambda-index-fc-accounts:latest 57 | ``` 58 | 59 | 5. Use the AWS console and update Docker image of the corresponding Lambda function. 60 | 61 | For other functions, replace `lambda-index-fc-accounts` and `index-accounts.js` with the corresponding name. 62 | -------------------------------------------------------------------------------- /functions/index-accounts.js: -------------------------------------------------------------------------------- 1 | import db from './lib/db.js' 2 | import graph from './lib/graph.js' 3 | import utils from './lib/utils.js' 4 | import fetch from 'node-fetch' 5 | 6 | // This is workaround for urql package depending on fetch() to be defined globally 7 | globalThis.fetch = fetch 8 | 9 | export const handler = async (event, context) => { 10 | console.log('Start indexing accounts') 11 | const latestAccountUpdatedAt = await db.getLatestAccountUpdatedAt() 12 | const accounts = await graph.getAccounts(latestAccountUpdatedAt) 13 | 14 | // This function handles the tricky case where the same username 15 | // goes through register => deregister => register cycles: 16 | // 1) Username is not already in DB: The graph returns only the latest account and the delete 17 | // will be skipped because deleted timestamp is after created timestamp on the account. 18 | // 2) Username is already in DB: We fail in this case becase we attempt to insert an account 19 | // with the same username that is already in the DB. 20 | // TODO: We should handle the case #2 gracefully instead of manually deleting the account. 21 | // TODO: The following transactions should be atomic, e.g., if this function fails after 22 | // insert but before completing the update/delete, retrying this function will fail with 23 | // conflict during the insert step. 24 | const accountsToInsert = accounts.filter( 25 | (account) => account.createdAt === account.updatedAt 26 | ) 27 | console.log( 28 | `${accountsToInsert.length}/${accounts.length} accounts are created` 29 | ) 30 | await db.insertAccounts( 31 | accountsToInsert.map((u) => utils.convertGraphAccountToDbAccount(u)) 32 | ) 33 | 34 | const accountsToUpdate = accounts.filter( 35 | (account) => account.createdAt !== account.updatedAt 36 | ) 37 | console.log( 38 | `${accountsToUpdate.length}/${accounts.length} accounts are updated` 39 | ) 40 | for (const account of accountsToUpdate) { 41 | await db.insertOrUpdateAccount( 42 | utils.convertGraphAccountToDbAccount(account) 43 | ) 44 | } 45 | 46 | const deletedAccounts = await graph.getDeletedAccounts(latestAccountUpdatedAt) 47 | for (const account of deletedAccounts) { 48 | await db.deleteAccount(account.address, parseInt(account.deletedAt)) 49 | } 50 | console.log('Done indexing accounts.') 51 | } 52 | -------------------------------------------------------------------------------- /functions/index-activities.js: -------------------------------------------------------------------------------- 1 | import db from './lib/db.js' 2 | import utils from './lib/utils.js' 3 | import crypto from './lib/crypto.js' 4 | 5 | // Reindex up to most recent 20 activities or 14 days ago in case metrics have changed 6 | const REINDEX_UP_TO_MOST_RECENT = 20 7 | const REINDEX_UP_TO_DAYS_AGO = 14 8 | 9 | export const handler = async (event, context) => { 10 | console.log('Start indexing activities') 11 | const timestampUpdate = { activity_updated_at: new Date().toISOString() } 12 | const daysAgoThreshold = utils.getDaysAgoInTime(REINDEX_UP_TO_DAYS_AGO) 13 | const accountsToUpdate = [] 14 | for (const account of await db.getNextAccountsToUpdateActivity()) { 15 | const { id, address, directories, latest_activity_sequence } = account 16 | accountsToUpdate.push(id) 17 | if (!directories.length) continue 18 | console.log(`Indexing activities for account ${id}`) 19 | // TODO: https://guardian.farcaster.xyz/origin/address_activity 20 | // Currently returns up to 5000 latest activities and does not seem to support pagination. 21 | // We could not index all activities for the following accounts that had more than 22 | // 5000 activities: @dwr. 23 | const activities = await utils.fetchWithLog(directories[0].activity_url) 24 | // We currently assume changes in content hosted on activity URLs are backwards compatible. 25 | // EX: sequence is always increasing vs. decreasing. 26 | if (activities) { 27 | const activitiesToUpsert = [] 28 | const deletedActivities = {} 29 | let prevSequence = null 30 | let activityValid = true 31 | for (const rawActivity of activities) { 32 | const activity = utils.convertToDbActivity(id, rawActivity) 33 | const { sequence, merkle_root, delete_merkle_root } = activity 34 | activityValid = crypto.validateActivitySignature(address, rawActivity) 35 | if (!activityValid) { 36 | console.warn( 37 | `Invalid activity signature for account ${id} at sequence ${sequence}` 38 | ) 39 | break 40 | } 41 | if ( 42 | latest_activity_sequence !== null && // Index all if not indexed yet 43 | sequence <= latest_activity_sequence && 44 | activitiesToUpsert.length >= REINDEX_UP_TO_MOST_RECENT && 45 | activity.published_at < daysAgoThreshold 46 | ) { 47 | break 48 | } 49 | // Some activity JSON files have multiple items with the same sequence number 50 | // e.g., https://gist.githubusercontent.com/gsgalloway/0a922a4fab3127404bded802fcde80b2/raw/activity.json 51 | // We skip earlier ones in those cases. 52 | if (sequence === prevSequence) { 53 | console.warn( 54 | `Skipping duplicate sequence ${sequence} for account ${id} (prevSequence: ${prevSequence})` 55 | ) 56 | continue 57 | } 58 | if (delete_merkle_root) { 59 | deletedActivities[delete_merkle_root] = true 60 | } 61 | if (merkle_root in deletedActivities) { 62 | activity.deleted = true 63 | delete deletedActivities[merkle_root] 64 | } 65 | activitiesToUpsert.push(activity) 66 | prevSequence = sequence 67 | } 68 | // Skip updating activities if at least one activity is invalid 69 | if (activityValid) { 70 | // Mark activities that are already in DB as deleted 71 | await db.markActivitiesAsDeleted(id, Object.keys(deletedActivities)) 72 | await db.upsertActivities(activitiesToUpsert) 73 | } 74 | } 75 | } 76 | await db.updateAccounts(timestampUpdate, accountsToUpdate) 77 | await db.updateLatestActivitySequence(accountsToUpdate) 78 | await db.updateReplyToActivity() 79 | console.log('Done indexing activities.') 80 | } 81 | -------------------------------------------------------------------------------- /functions/index-directories.js: -------------------------------------------------------------------------------- 1 | import db from './lib/db.js' 2 | import fc from './lib/farcaster-api.js' 3 | import utils from './lib/utils.js' 4 | 5 | const extractAddressFromDirectoryUrl = (url) => { 6 | // Ex: https://guardian.farcaster.xyz/origin/directory/0x2cf0b72866F4e51A7C35a02998B5E66896ee2c50 7 | const parts = url.split('guardian.farcaster.xyz/origin/directory/') 8 | return parts.length > 1 ? parts[1] : null 9 | } 10 | 11 | export const handler = async (event, context) => { 12 | console.log('Start indexing directories') 13 | const timestampUpdate = { directory_updated_at: new Date().toISOString() } 14 | const directoriesToUpsert = [] 15 | const proofsToUpsert = [] 16 | const proofsToDelete = [] 17 | const profilesToUpsert = [] 18 | const accountsToUpdate = [] 19 | for (const account of await db.getNextAccountsToUpdateDirectory()) { 20 | const { id, url } = account 21 | console.log(`Processing account ${id}`) 22 | const directory = await utils.fetchWithLog(url) 23 | if (directory) { 24 | directoriesToUpsert.push(utils.convertToDbDirectory(id, directory)) 25 | // Using farcaster address from proof or directory url 26 | // because graph lowercases account addresses and the 27 | // profile URL is case sensitive. 28 | let caseSensitiveAddress 29 | const proof = await utils.fetchWithLog(directory.body.proofUrl) 30 | if (proof) { 31 | proofsToUpsert.push(utils.convertToDbProof(id, proof)) 32 | caseSensitiveAddress = proof.farcasterAddress 33 | } else { 34 | proofsToDelete.push(id) 35 | caseSensitiveAddress = extractAddressFromDirectoryUrl(url) 36 | } 37 | if (caseSensitiveAddress) { 38 | const profile = await fc.getProfile(caseSensitiveAddress) 39 | if (profile) { 40 | profilesToUpsert.push(utils.convertToDbProfile(id, profile)) 41 | } 42 | } 43 | } 44 | accountsToUpdate.push(id) 45 | } 46 | await db.upsertDirectories(directoriesToUpsert) 47 | await db.upsertProofs(proofsToUpsert) 48 | await db.deleteProofs(proofsToDelete) 49 | await db.upsertProfiles(profilesToUpsert) 50 | await db.updateAccounts(timestampUpdate, accountsToUpdate) 51 | console.log('Done indexing directories.') 52 | } 53 | -------------------------------------------------------------------------------- /functions/index-opengraphs.js: -------------------------------------------------------------------------------- 1 | import db from './lib/db.js' 2 | import scraper from './lib/scraper.js' 3 | 4 | const TWITTER_DOMAINS = ['mobile.twitter.com', 'twitter.com'] 5 | 6 | export const handler = async (event, context) => { 7 | console.log('Start indexing urls') 8 | for (const activity of await db.getNextActivitiesToUpdateIndexOpengraphs()) { 9 | const errors = [] 10 | try { 11 | // Get the opengraphs from the activity text 12 | const urlsInActivityText = scraper.extractUrls(activity.text) 13 | console.log( 14 | `Found ${urlsInActivityText.size} urls in activity's text ${activity.id}` 15 | ) 16 | const opengraphsToUpsert = [] 17 | const normalizedUrls = new Set() 18 | for (const url of urlsInActivityText) { 19 | try { 20 | const opengraph = await scraper.getOpengraphFromUrl(url) 21 | if ( 22 | TWITTER_DOMAINS.includes(opengraph.domain) && 23 | !opengraph.title && 24 | !opengraph.description 25 | ) { 26 | // We sometimes don't scrape twitter well. 27 | // If so we fall back to Farcaster's scraper. 28 | continue 29 | } 30 | if (!normalizedUrls.has(opengraph.normalized_url)) { 31 | normalizedUrls.add(opengraph.normalized_url) 32 | opengraphsToUpsert.push(opengraph) 33 | } 34 | } catch (e) { 35 | // Skipping both permanent and temporary errors for now 36 | // since we fall back to the opengraphs in the activity 37 | if ( 38 | e instanceof scraper.PermanentError || 39 | e instanceof scraper.TemporaryError 40 | ) { 41 | errors.push(e.message) 42 | console.warn( 43 | `Skipping ${url} due to the following error: ${e.message}` 44 | ) 45 | continue 46 | } 47 | throw e 48 | } 49 | } 50 | // Get the opengraphs from the activity opengraphs 51 | const urlsInActivityOpengraphs = 52 | scraper.getOpengraphsFromActivity(activity) 53 | console.log( 54 | `Found ${urlsInActivityOpengraphs.length} urls in activity's opengraphs ${activity.id}` 55 | ) 56 | for (const url of urlsInActivityOpengraphs) { 57 | // Index only if there is no similar url already extracted from the activity text 58 | if ( 59 | !Array.from(normalizedUrls).some( 60 | (nu) => 61 | nu.startsWith(url.normalized_url) || 62 | url.normalized_url.startsWith(nu) 63 | ) 64 | ) { 65 | normalizedUrls.add(url.normalized_url) 66 | opengraphsToUpsert.push(url) 67 | } 68 | } 69 | await db.upsertOpengraphs(activity.id, opengraphsToUpsert) 70 | } catch (e) { 71 | console.error(`Unknown error scraping ${activity.id}: ${e.message}`) 72 | throw e 73 | } 74 | if (errors.length) { 75 | db.getNextActivitiesToUpdateIndexOpengraphs( 76 | activity.id, 77 | errors.join('\n') 78 | ) 79 | } 80 | } 81 | console.log('Done indexing urls.') 82 | } 83 | -------------------------------------------------------------------------------- /functions/lib/crypto.js: -------------------------------------------------------------------------------- 1 | // See https://www.farcaster.xyz/docs/signed-blob 2 | // We are not verifying directory signatures because it's getting deprecated in v2 protocol. 3 | import { keccak256 } from '@ethersproject/keccak256' 4 | import { toUtf8Bytes } from '@ethersproject/strings' 5 | import { verifyMessage } from '@ethersproject/wallet' 6 | 7 | // The following serialization function is needed because 8 | // JSON stringify is property order dependent. 9 | // See Farcaster doc for the details: https://www.farcaster.xyz/docs/signed-blob#footnotes 10 | // From https://github.com/standard-crypto/farcaster-js/blob/main/src/serialization.ts#L3 11 | const serializeAddressActivityBody = (body) => { 12 | const canonicalForm = { 13 | type: body.type, 14 | publishedAt: body.publishedAt, 15 | sequence: body.sequence, 16 | username: body.username, 17 | address: body.address, 18 | data: { 19 | text: body.data.text, 20 | replyParentMerkleRoot: body.data.replyParentMerkleRoot, 21 | }, 22 | prevMerkleRoot: body.prevMerkleRoot, 23 | tokenCommunities: body.tokenCommunities, 24 | } 25 | return JSON.stringify(canonicalForm) 26 | } 27 | 28 | const validateActivitySignature = (address, addressActivity) => { 29 | const serializedCast = serializeAddressActivityBody(addressActivity.body) 30 | const derivedMerkleRoot = keccak256(toUtf8Bytes(serializedCast)) 31 | const signerAddress = verifyMessage( 32 | derivedMerkleRoot, 33 | addressActivity.signature 34 | ) 35 | return ( 36 | signerAddress.toLowerCase() === address.toLowerCase() && 37 | derivedMerkleRoot === addressActivity.merkleRoot 38 | ) 39 | } 40 | 41 | export default { 42 | validateActivitySignature, 43 | } 44 | -------------------------------------------------------------------------------- /functions/lib/db.js: -------------------------------------------------------------------------------- 1 | import { createClient } from '@supabase/supabase-js' 2 | 3 | const supabase = createClient( 4 | process.env['SUPABASE_URL'], 5 | process.env['SUPABASE_API_KEY'] 6 | ) 7 | 8 | const _checkError = (error) => { 9 | if (error) { 10 | throw new Error(error.message) 11 | } 12 | } 13 | 14 | const _defaultAccountSelect = (fields) => { 15 | // Test accounts uses localhost and/or starts with __tt_ 16 | return supabase 17 | .from('accounts') 18 | .select(fields) 19 | .not('url', 'like', '%://localhost%') 20 | .not('username', 'like', '\\_\\_tt\\_%') 21 | } 22 | 23 | // Update 200 accounts at a time to avoid AWS Lambda timeout 24 | const getNextAccountsToUpdateDirectory = async () => { 25 | const { data, error } = await _defaultAccountSelect('id, url') 26 | .order('directory_updated_at', { ascending: true, nullsFirst: true }) 27 | .limit(200) 28 | _checkError(error) 29 | return data 30 | } 31 | 32 | // Update 200 accounts at a time to avoid AWS Lambda timeout 33 | const getNextAccountsToUpdateActivity = async () => { 34 | const { data, error } = await _defaultAccountSelect( 35 | 'id, address, latest_activity_sequence, directories (activity_url)' 36 | ) 37 | .order('activity_updated_at', { ascending: true, nullsFirst: true }) 38 | .limit(200) 39 | _checkError(error) 40 | return data 41 | } 42 | 43 | const getLatestAccountUpdatedAt = async () => { 44 | const { data, error } = await supabase 45 | .from('accounts') 46 | .select() 47 | .order('entry_updated_at', { ascending: false }) 48 | .limit(1) 49 | _checkError(error) 50 | return data.length ? data[0].entry_updated_at : 0 51 | } 52 | 53 | const getLatestAccountDeletedAt = async () => { 54 | const { data, error } = await supabase 55 | .from('accounts') 56 | .select() 57 | .order('entry_deleted_at', { ascending: false }) 58 | .not('entry_deleted_at', 'is', null) 59 | .limit(1) 60 | _checkError(error) 61 | return data.length ? data[0].entry_deleted_at : 0 62 | } 63 | 64 | const insertAccounts = async (accounts) => { 65 | if (!accounts.length) return 66 | const { error } = await supabase.from('accounts').insert(accounts) 67 | _checkError(error) 68 | console.log(`Inserted ${accounts.length} accounts`) 69 | } 70 | 71 | const _getAccount = async (address, createdAt) => { 72 | const { data, error } = await supabase 73 | .from('accounts') 74 | .select() 75 | .match({ address: address }) 76 | .lt('entry_created_at', createdAt) 77 | _checkError(error) 78 | return data.length ? data[0] : null 79 | } 80 | 81 | const _checkAccountExists = async (address) => { 82 | const { count, error } = await supabase 83 | .from('accounts') 84 | .select('*', { count: 'exact', head: true }) 85 | .eq('address', address) 86 | _checkError(error) 87 | return count > 0 88 | } 89 | 90 | const updateAccount = async (account) => { 91 | const { error } = await supabase 92 | .from('accounts') 93 | .update(account) 94 | .eq('id', account.id) 95 | _checkError(error) 96 | console.log(`Updated account ${account.id}`) 97 | } 98 | 99 | const updateAccounts = async (update, accountIds) => { 100 | const { data, error } = await supabase 101 | .from('accounts') 102 | .update(update) 103 | .in('id', accountIds) 104 | _checkError(error) 105 | console.log(`Updated ${data.length} accounts`) 106 | } 107 | 108 | const insertOrUpdateAccount = async (account) => { 109 | if (await _checkAccountExists(account.address)) { 110 | const { error } = await supabase 111 | .from('accounts') 112 | .update(account) 113 | .eq('address', account.address) 114 | _checkError(error) 115 | console.log(`Updated account ${account.address}`) 116 | } else { 117 | await insertAccounts([account]) 118 | console.log(`Inserted account ${account.address}`) 119 | } 120 | } 121 | 122 | const deleteAccount = async (address, deletedAt) => { 123 | const account = await _getAccount(address, deletedAt) 124 | if (account) { 125 | const { error } = await supabase 126 | .from('accounts') 127 | .delete() 128 | .eq('id', account.id) 129 | _checkError(error) 130 | console.log(`Deleted account ${account.username}`) 131 | } else { 132 | console.warn( 133 | `Could not delete account: No record found with address ${address}` 134 | ) 135 | } 136 | } 137 | 138 | const _upsert = async (tableName, items, onConflict, returning = 'minimal') => { 139 | if (!items.length) return { data: [] } 140 | const { data, error } = await supabase 141 | .from(tableName) 142 | .upsert(items, { onConflict: onConflict, returning: returning }) 143 | _checkError(error) 144 | console.log(`Upserted ${items.length} ${tableName}`) 145 | return { data } 146 | } 147 | 148 | const upsertDirectories = async (directories) => { 149 | return _upsert('directories', directories, 'account') 150 | } 151 | 152 | const upsertProofs = async (proofs) => { 153 | return _upsert('proofs', proofs, 'account') 154 | } 155 | 156 | const deleteProofs = async (accountIds) => { 157 | if (!accountIds.length) return 158 | const { data, error } = await supabase 159 | .from('proofs') 160 | .delete() 161 | .in('account', accountIds) 162 | _checkError(error) 163 | console.log(`Deleted ${data.length} proofs`) 164 | } 165 | 166 | const upsertProfiles = async (profiles) => { 167 | return _upsert('profiles', profiles, 'account') 168 | } 169 | 170 | const upsertActivities = async (activities) => { 171 | return _upsert('activities', activities, 'account, sequence') 172 | } 173 | 174 | const markActivitiesAsDeleted = async (accountId, merkleRoots) => { 175 | if (!merkleRoots.length) return 176 | const { data, error } = await supabase 177 | .from('activities') 178 | .update({ deleted: true }) 179 | .eq('account', accountId) // Only can delete own activities 180 | .in('merkle_root', merkleRoots) 181 | try { 182 | _checkError(error) 183 | } catch (error) { 184 | // Try break up updates into two requests if URI too long 185 | // TODO: This should be a generic function for all batch updates 186 | if (error.message?.startsWith('URI too long')) { 187 | const breakIndex = Math.floor(merkleRoots.length / 2) 188 | if (breakIndex !== 0) { 189 | await markActivitiesAsDeleted( 190 | accountId, 191 | merkleRoots.slice(0, breakIndex) 192 | ) 193 | await markActivitiesAsDeleted(accountId, merkleRoots.slice(breakIndex)) 194 | return 195 | } 196 | } 197 | throw error 198 | } 199 | if (data.length < merkleRoots.length) { 200 | console.warn( 201 | `Could not find ${ 202 | merkleRoots.length - data.length 203 | } activities to mark as deleted` 204 | ) 205 | } 206 | console.log( 207 | `Marked ${data.length} activities as deleted for account ${accountId}` 208 | ) 209 | } 210 | 211 | /* 212 | CREATE FUNCTION update_latest_activity_sequence(account_ids int[]) RETURNS void AS $$ 213 | UPDATE accounts AS a 214 | SET latest_activity_sequence = ( 215 | SELECT max(sequence) FROM activities WHERE a.id = account 216 | ) 217 | WHERE a.id = ANY(account_ids) 218 | $$ language sql; 219 | */ 220 | const updateLatestActivitySequence = async (accountIds) => { 221 | const { error } = await supabase.rpc('update_latest_activity_sequence', { 222 | account_ids: accountIds, 223 | }) 224 | _checkError(error) 225 | console.log( 226 | `Updated latest_activity_sequence field of ${accountIds.length} accounts via the update_latest_activity_sequence RPC call` 227 | ) 228 | } 229 | 230 | /* 231 | CREATE FUNCTION update_reply_to_activity() RETURNS void AS $$ 232 | update activities as a1 233 | set reply_to = ( 234 | select a2.id from activities as a2 where a2.merkle_root = a1.reply_parent_merkle_root order by a2.published_at asc limit 1 235 | ) 236 | where reply_parent_merkle_root != '' and reply_to is null 237 | $$ LANGUAGE SQL; 238 | */ 239 | const updateReplyToActivity = async () => { 240 | const { error } = await supabase.rpc('update_reply_to_activity') 241 | _checkError(error) 242 | console.log( 243 | 'Updated reply_to field of activities via the update_reply_to_activity RPC call' 244 | ) 245 | } 246 | 247 | const getNextActivitiesToUpdateIndexOpengraphs = async () => { 248 | const { data, error } = await supabase 249 | .rpc('select_activities_to_index_opengraphs') 250 | .order('published_at', { ascending: false }) 251 | .limit(300) 252 | _checkError(error) 253 | return data 254 | } 255 | 256 | const upsertOpengraphs = async (activityId, opengraphs) => { 257 | if (opengraphs.length) { 258 | const { data } = await _upsert( 259 | 'opengraphs', 260 | opengraphs, 261 | 'normalized_url', 262 | 'representation' 263 | ) 264 | const manyToMany = data.map((og) => { 265 | return { activity: activityId, opengraph: og.id } 266 | }) 267 | return _upsert('activities_opengraphs', manyToMany, 'activity, opengraph') 268 | } else { 269 | // Insert an entry with opengraph null indicates opengraphs were scraped but empty 270 | const { error } = await supabase 271 | .from('activities_opengraphs') 272 | .insert({ activity: activityId, opengraph: null }) 273 | _checkError(error) 274 | console.log(`Marked activity ${activityId} as scraped`) 275 | } 276 | } 277 | 278 | const updateOpengraphIndexingErrors = async (activityId, errors) => { 279 | const { error } = await supabase 280 | .from('activities') 281 | .update({ opengraph_indexing_errors: errors }) 282 | .eq('id', activityId) 283 | _checkError(error) 284 | console.log(`Logged opengraph indexing errors for activity ${activityId}`) 285 | } 286 | 287 | export default { 288 | getNextAccountsToUpdateDirectory, 289 | getNextAccountsToUpdateActivity, 290 | getLatestAccountUpdatedAt, 291 | getLatestAccountDeletedAt, 292 | insertAccounts, 293 | updateAccount, 294 | updateAccounts, 295 | insertOrUpdateAccount, 296 | deleteAccount, 297 | upsertDirectories, 298 | upsertProofs, 299 | deleteProofs, 300 | upsertProfiles, 301 | upsertActivities, 302 | markActivitiesAsDeleted, 303 | updateLatestActivitySequence, 304 | updateReplyToActivity, 305 | getNextActivitiesToUpdateIndexOpengraphs, 306 | upsertOpengraphs, 307 | updateOpengraphIndexingErrors, 308 | } 309 | -------------------------------------------------------------------------------- /functions/lib/farcaster-api.js: -------------------------------------------------------------------------------- 1 | import utils from './utils.js' 2 | 3 | const HOST = 'https://api.farcaster.xyz/v1' 4 | 5 | const getProfile = async (address) => { 6 | return await utils.fetchWithLog(`${HOST}/profiles/${address}`) 7 | } 8 | 9 | export default { 10 | getProfile, 11 | } 12 | -------------------------------------------------------------------------------- /functions/lib/graph.js: -------------------------------------------------------------------------------- 1 | import { createClient } from '@urql/core' 2 | 3 | const PAGE_SIZE = 100 4 | 5 | const client = createClient({ 6 | url: process.env['GRAPH_API_URL'], 7 | }) 8 | 9 | const _query = async (query, vars = {}) => { 10 | const { data, error } = await client.query(query, vars).toPromise() 11 | if (error) { 12 | console.error('Error querying graph:', error) 13 | throw new Error(error) 14 | } 15 | return data 16 | } 17 | 18 | const _queryAllRows = async (query, tableName) => { 19 | const res = [] 20 | let currentPage 21 | let currentIndex = 0 22 | console.log(`Querying all rows from ${tableName}`) 23 | do { 24 | const data = await _query(query, { skip: currentIndex * PAGE_SIZE }) 25 | currentPage = data ? data[tableName] : [] 26 | console.log(`Page ${currentIndex + 1}: ${currentPage.length} rows`) 27 | res.push(...currentPage) 28 | currentIndex++ 29 | } while (currentPage.length > 0) 30 | console.log(`Found ${res.length} rows in ${tableName}`) 31 | return res 32 | } 33 | 34 | const getAccounts = async (updatedSince) => { 35 | const query = ` 36 | query($skip: Int) { 37 | users(first: ${PAGE_SIZE}, skip: $skip, where: {updatedAt_gt: ${updatedSince}}, orderBy: updatedAt, orderDirection: asc) { 38 | id 39 | username 40 | address 41 | url 42 | initialized 43 | createdAt 44 | updatedAt 45 | } 46 | } 47 | ` 48 | let users = await _queryAllRows(query, 'users') 49 | if (updatedSince === 0) { 50 | // @noon and @spoon have the same address which should never happen. 51 | // This is probably due to a bug in the early contract development. 52 | // @noon is active on Farcaster while @spoon is not so we are skipping @spoon. 53 | users = users.filter((user) => user.id !== 'spoon') 54 | } 55 | console.log( 56 | `Found ${users.length} users updated in the registry since ${updatedSince}` 57 | ) 58 | return users 59 | } 60 | 61 | const getDeletedAccounts = async (deletedSince) => { 62 | const query = ` 63 | query($skip: Int) { 64 | deletedUsers(first: ${PAGE_SIZE}, skip: $skip, where: {deletedAt_gt: ${deletedSince}}, orderBy: deletedAt, orderDirection: asc) { 65 | id 66 | username 67 | address 68 | deletedAt 69 | } 70 | } 71 | ` 72 | const users = await _queryAllRows(query, 'deletedUsers') 73 | console.log( 74 | `Found ${users.length} users deleted from the registry since ${deletedSince}` 75 | ) 76 | return users 77 | } 78 | 79 | export default { getAccounts, getDeletedAccounts } 80 | -------------------------------------------------------------------------------- /functions/lib/scraper.js: -------------------------------------------------------------------------------- 1 | import ogs from 'open-graph-scraper' 2 | import urlRegex from 'url-regex' 3 | import utils from './utils.js' 4 | 5 | class PermanentError extends Error {} 6 | class TemporaryError extends Error {} 7 | 8 | // Farcaster uses imgur as image hosting service. 9 | const isValidOpengraphUrl = (url) => { 10 | return url && !url.startsWith('https://i.imgur.com/') 11 | } 12 | 13 | // We don't want to retry if we get these errors. 14 | const PERMANENT_ERRORS = [ 15 | 'Page not found', 16 | 'Must scrape an HTML page', 17 | 'Page must return a header content-type with text/html', 18 | 'certificate has expired', 19 | 'Hostname/IP does not match certificate', 20 | 'Invalid URL', 21 | 'Response code 999 (Request denied)', 22 | 'connect ECONNREFUSED', 23 | 'self signed certificate', 24 | 'write EPROTO', 25 | 'Web server is returning error', 26 | 'Encoding not recognized:', 27 | 'unable to verify the first certificate', 28 | 'Redirected ', // Redirected 10 times. Aborting. 29 | 'Protocol ', // Protocol not supported 30 | ] 31 | // We want to retry if we get these errors. 32 | const TEMP_ERRORS = [ 33 | 'socket hang up', 34 | 'Time out', 35 | 'Client network socket disconnected before secure TLS connection was established', 36 | 'Exceeded the download limit of', 37 | ] 38 | // open graph scraper options: 39 | // https://www.npmjs.com/package/open-graph-scraper 40 | // Maximum size of the content downloaded from the server, in bytes 41 | const SCRAPE_DOWNLOAD_LIMIT = 20000000 // 10MB 42 | const TIMEOUT = 10000 // 10 seconds 43 | 44 | const URL_REGEX = urlRegex() 45 | 46 | const extractUrls = (text) => { 47 | const urls = text.match(URL_REGEX)?.filter(isValidOpengraphUrl) || [] 48 | return new Set(urls.map((url) => url.trim().replace(/\.+$/, ''))) 49 | } 50 | 51 | const getOpengraphFromUrl = async (url) => { 52 | try { 53 | console.log(`Scraping ${url}`) 54 | const { result } = await ogs({ 55 | url: url, 56 | downloadLimit: SCRAPE_DOWNLOAD_LIMIT, 57 | timeout: TIMEOUT, 58 | }) 59 | return utils.convertToDbOpengraph(result) 60 | } catch (e) { 61 | const errorMsg = e.result?.error 62 | if (errorMsg) { 63 | if (PERMANENT_ERRORS.some((msg) => errorMsg.startsWith(msg))) { 64 | throw new PermanentError(errorMsg) 65 | } else if (TEMP_ERRORS.some((msg) => errorMsg.startsWith(msg))) { 66 | throw new TemporaryError(errorMsg) 67 | } 68 | } 69 | // Unknown error 70 | throw new Error(errorMsg) 71 | } 72 | } 73 | 74 | const getOpengraphsFromActivity = (activity) => { 75 | const { raw_data } = activity 76 | return ( 77 | raw_data?.attachments?.openGraph 78 | ?.filter((og) => isValidOpengraphUrl(og.url)) 79 | .map(utils.convertToDbOpengraph) || [] 80 | ) 81 | } 82 | 83 | export default { 84 | PermanentError, 85 | TemporaryError, 86 | extractUrls, 87 | getOpengraphFromUrl, 88 | getOpengraphsFromActivity, 89 | } 90 | -------------------------------------------------------------------------------- /functions/lib/utils.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import normalizeUrl from 'normalize-url' 3 | 4 | const fetchWithLog = async (url) => { 5 | try { 6 | const res = await fetch(url) 7 | if (!res.ok) { 8 | console.warn(`Could not fetch ${url}: ${res.statusText}`) 9 | return null 10 | } 11 | return await res.json() 12 | } catch (e) { 13 | console.warn(`Could not fetch ${url}: ${e.message}`) 14 | return null 15 | } 16 | } 17 | 18 | const convertGraphAccountToDbAccount = (account) => { 19 | return { 20 | username: account.id, 21 | address: account.address, 22 | url: account.url, 23 | initialized: account.initialized, 24 | entry_created_at: parseInt(account.createdAt), 25 | entry_updated_at: parseInt(account.updatedAt), 26 | } 27 | } 28 | 29 | const convertToDbDirectory = (accountId, directory) => { 30 | const { body, merkleRoot, signature } = directory 31 | const { addressActivityUrl, avatarUrl, displayName, proofUrl } = body 32 | return { 33 | account: accountId, 34 | activity_url: addressActivityUrl || '', 35 | avatar_url: avatarUrl || '', 36 | display_name: displayName || '', 37 | proof_url: proofUrl || '', 38 | merkle_root: merkleRoot || '', 39 | signature: signature || '', 40 | raw_data: directory, 41 | } 42 | } 43 | 44 | const convertToDbProof = (accountId, proof) => { 45 | const { signedMessage, signerAddress, farcasterAddress, originalMessage } = 46 | proof 47 | return { 48 | account: accountId, 49 | signed_message: signedMessage || '', 50 | signer_address: signerAddress || '', 51 | farcaster_address: farcasterAddress || '', 52 | original_message: originalMessage || '', 53 | raw_data: proof, 54 | } 55 | } 56 | 57 | const convertToDbProfile = (accountId, profile) => { 58 | const { user } = profile.result 59 | return { 60 | account: accountId, 61 | bio: user?.profile?.bio?.text || '', 62 | num_followers: user?.followerCount || 0, 63 | num_following: user?.followingCount || 0, 64 | raw_data: user, 65 | } 66 | } 67 | 68 | const _getRecastMerkleRoot = (text) => { 69 | const parts = text.split('recast:farcaster://casts/') 70 | if (parts.length > 1) { 71 | return parts[1] 72 | } 73 | return '' 74 | } 75 | 76 | const _getDeleteMerkleRoot = (text) => { 77 | const parts = text.split('delete:farcaster://casts/') 78 | // Prevent delete:farcaster://casts/undefined to get through 79 | if (parts.length > 1 && parts[1] !== 'undefined') { 80 | return parts[1] 81 | } 82 | return '' 83 | } 84 | 85 | const convertToDbActivity = (accountId, activity) => { 86 | const { body, merkleRoot, signature, meta } = activity 87 | return { 88 | account: accountId, 89 | merkle_root: merkleRoot || '', 90 | signature: signature || '', 91 | published_at: body.publishedAt, 92 | sequence: body.sequence, 93 | text: body.data.text || '', 94 | reply_parent_merkle_root: body.data.replyParentMerkleRoot || '', 95 | prev_merkle_root: body.prevMerkleRoot || '', 96 | recast_merkle_root: _getRecastMerkleRoot(body.data.text), 97 | delete_merkle_root: _getDeleteMerkleRoot(body.data.text), 98 | num_reply_children: meta?.numReplyChildren || 0, 99 | reactions_count: meta?.reactions?.count || 0, 100 | recasts_count: meta?.recasts?.count || 0, 101 | watches_count: meta?.watches?.count || 0, 102 | deleted: false, 103 | raw_data: activity, 104 | } 105 | } 106 | 107 | const normalizeUrlWithHttps = (url) => { 108 | return normalizeUrl(url, { forceHttps: true }) 109 | } 110 | 111 | const convertToDbOpengraph = (opengraph) => { 112 | if (opengraph.requestUrl) { 113 | // Extracted using open-graph-scraper 114 | const { requestUrl, ogTitle, ogType, ogUrl, ogDescription, ogImage } = 115 | opengraph 116 | const normalizedUrl = normalizeUrlWithHttps(requestUrl) 117 | return { 118 | normalized_url: normalizedUrl, 119 | scraped_url: requestUrl, 120 | domain: new URL(normalizedUrl).hostname || '', 121 | url: ogUrl || '', 122 | type: ogType || '', 123 | title: ogTitle || '', 124 | description: ogDescription || '', 125 | image: ogImage || null, 126 | raw_data: opengraph, 127 | } 128 | } else { 129 | // From activity 130 | const normalizedUrl = normalizeUrlWithHttps(opengraph.url) 131 | return { 132 | normalized_url: normalizedUrl, 133 | scraped_url: opengraph.url, 134 | domain: new URL(normalizedUrl).hostname || '', 135 | url: opengraph.url || '', 136 | type: '', 137 | title: opengraph.title || '', 138 | description: opengraph.description || '', 139 | image: opengraph.image ? { url: opengraph.image || '' } : null, 140 | raw_data: opengraph, 141 | } 142 | } 143 | } 144 | 145 | const getDaysAgoInTime = (days) => { 146 | const now = new Date() 147 | return new Date(now.getTime() - days * 24 * 60 * 60 * 1000).getTime() 148 | } 149 | 150 | export default { 151 | fetchWithLog, 152 | convertGraphAccountToDbAccount, 153 | convertToDbDirectory, 154 | convertToDbProof, 155 | convertToDbProfile, 156 | convertToDbActivity, 157 | convertToDbOpengraph, 158 | normalizeUrlWithHttps, 159 | getDaysAgoInTime, 160 | } 161 | -------------------------------------------------------------------------------- /functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "farcaster-indexer", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "main": "main.js", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@ethersproject/keccak256": "^5.6.1", 9 | "@ethersproject/strings": "^5.6.1", 10 | "@ethersproject/wallet": "^5.6.2", 11 | "@supabase/supabase-js": "^1.35.6", 12 | "@urql/core": "^2.6.1", 13 | "graphql": "^16.5.0", 14 | "node-fetch": "^3.2.10", 15 | "normalize-url": "^7.0.3", 16 | "open-graph-scraper": "^4.11.1", 17 | "url-regex": "^5.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /functions/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ethersproject/abstract-provider@^5.6.1": 6 | version "5.6.1" 7 | resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59" 8 | integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ== 9 | dependencies: 10 | "@ethersproject/bignumber" "^5.6.2" 11 | "@ethersproject/bytes" "^5.6.1" 12 | "@ethersproject/logger" "^5.6.0" 13 | "@ethersproject/networks" "^5.6.3" 14 | "@ethersproject/properties" "^5.6.0" 15 | "@ethersproject/transactions" "^5.6.2" 16 | "@ethersproject/web" "^5.6.1" 17 | 18 | "@ethersproject/abstract-signer@^5.6.2": 19 | version "5.6.2" 20 | resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33" 21 | integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ== 22 | dependencies: 23 | "@ethersproject/abstract-provider" "^5.6.1" 24 | "@ethersproject/bignumber" "^5.6.2" 25 | "@ethersproject/bytes" "^5.6.1" 26 | "@ethersproject/logger" "^5.6.0" 27 | "@ethersproject/properties" "^5.6.0" 28 | 29 | "@ethersproject/address@^5.6.1": 30 | version "5.6.1" 31 | resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d" 32 | integrity sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q== 33 | dependencies: 34 | "@ethersproject/bignumber" "^5.6.2" 35 | "@ethersproject/bytes" "^5.6.1" 36 | "@ethersproject/keccak256" "^5.6.1" 37 | "@ethersproject/logger" "^5.6.0" 38 | "@ethersproject/rlp" "^5.6.1" 39 | 40 | "@ethersproject/base64@^5.6.1": 41 | version "5.6.1" 42 | resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb" 43 | integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw== 44 | dependencies: 45 | "@ethersproject/bytes" "^5.6.1" 46 | 47 | "@ethersproject/basex@^5.6.1": 48 | version "5.6.1" 49 | resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.1.tgz#badbb2f1d4a6f52ce41c9064f01eab19cc4c5305" 50 | integrity sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA== 51 | dependencies: 52 | "@ethersproject/bytes" "^5.6.1" 53 | "@ethersproject/properties" "^5.6.0" 54 | 55 | "@ethersproject/bignumber@^5.6.2": 56 | version "5.6.2" 57 | resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66" 58 | integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw== 59 | dependencies: 60 | "@ethersproject/bytes" "^5.6.1" 61 | "@ethersproject/logger" "^5.6.0" 62 | bn.js "^5.2.1" 63 | 64 | "@ethersproject/bytes@^5.6.1": 65 | version "5.6.1" 66 | resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" 67 | integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== 68 | dependencies: 69 | "@ethersproject/logger" "^5.6.0" 70 | 71 | "@ethersproject/constants@^5.6.1": 72 | version "5.6.1" 73 | resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370" 74 | integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg== 75 | dependencies: 76 | "@ethersproject/bignumber" "^5.6.2" 77 | 78 | "@ethersproject/hash@^5.6.1": 79 | version "5.6.1" 80 | resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4" 81 | integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA== 82 | dependencies: 83 | "@ethersproject/abstract-signer" "^5.6.2" 84 | "@ethersproject/address" "^5.6.1" 85 | "@ethersproject/bignumber" "^5.6.2" 86 | "@ethersproject/bytes" "^5.6.1" 87 | "@ethersproject/keccak256" "^5.6.1" 88 | "@ethersproject/logger" "^5.6.0" 89 | "@ethersproject/properties" "^5.6.0" 90 | "@ethersproject/strings" "^5.6.1" 91 | 92 | "@ethersproject/hdnode@^5.6.2": 93 | version "5.6.2" 94 | resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.2.tgz#26f3c83a3e8f1b7985c15d1db50dc2903418b2d2" 95 | integrity sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q== 96 | dependencies: 97 | "@ethersproject/abstract-signer" "^5.6.2" 98 | "@ethersproject/basex" "^5.6.1" 99 | "@ethersproject/bignumber" "^5.6.2" 100 | "@ethersproject/bytes" "^5.6.1" 101 | "@ethersproject/logger" "^5.6.0" 102 | "@ethersproject/pbkdf2" "^5.6.1" 103 | "@ethersproject/properties" "^5.6.0" 104 | "@ethersproject/sha2" "^5.6.1" 105 | "@ethersproject/signing-key" "^5.6.2" 106 | "@ethersproject/strings" "^5.6.1" 107 | "@ethersproject/transactions" "^5.6.2" 108 | "@ethersproject/wordlists" "^5.6.1" 109 | 110 | "@ethersproject/json-wallets@^5.6.1": 111 | version "5.6.1" 112 | resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz#3f06ba555c9c0d7da46756a12ac53483fe18dd91" 113 | integrity sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ== 114 | dependencies: 115 | "@ethersproject/abstract-signer" "^5.6.2" 116 | "@ethersproject/address" "^5.6.1" 117 | "@ethersproject/bytes" "^5.6.1" 118 | "@ethersproject/hdnode" "^5.6.2" 119 | "@ethersproject/keccak256" "^5.6.1" 120 | "@ethersproject/logger" "^5.6.0" 121 | "@ethersproject/pbkdf2" "^5.6.1" 122 | "@ethersproject/properties" "^5.6.0" 123 | "@ethersproject/random" "^5.6.1" 124 | "@ethersproject/strings" "^5.6.1" 125 | "@ethersproject/transactions" "^5.6.2" 126 | aes-js "3.0.0" 127 | scrypt-js "3.0.1" 128 | 129 | "@ethersproject/keccak256@^5.6.1": 130 | version "5.6.1" 131 | resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc" 132 | integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA== 133 | dependencies: 134 | "@ethersproject/bytes" "^5.6.1" 135 | js-sha3 "0.8.0" 136 | 137 | "@ethersproject/logger@^5.6.0": 138 | version "5.6.0" 139 | resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" 140 | integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== 141 | 142 | "@ethersproject/networks@^5.6.3": 143 | version "5.6.4" 144 | resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.4.tgz#51296d8fec59e9627554f5a8a9c7791248c8dc07" 145 | integrity sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ== 146 | dependencies: 147 | "@ethersproject/logger" "^5.6.0" 148 | 149 | "@ethersproject/pbkdf2@^5.6.1": 150 | version "5.6.1" 151 | resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz#f462fe320b22c0d6b1d72a9920a3963b09eb82d1" 152 | integrity sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ== 153 | dependencies: 154 | "@ethersproject/bytes" "^5.6.1" 155 | "@ethersproject/sha2" "^5.6.1" 156 | 157 | "@ethersproject/properties@^5.6.0": 158 | version "5.6.0" 159 | resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" 160 | integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== 161 | dependencies: 162 | "@ethersproject/logger" "^5.6.0" 163 | 164 | "@ethersproject/random@^5.6.1": 165 | version "5.6.1" 166 | resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.1.tgz#66915943981bcd3e11bbd43733f5c3ba5a790255" 167 | integrity sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA== 168 | dependencies: 169 | "@ethersproject/bytes" "^5.6.1" 170 | "@ethersproject/logger" "^5.6.0" 171 | 172 | "@ethersproject/rlp@^5.6.1": 173 | version "5.6.1" 174 | resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8" 175 | integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ== 176 | dependencies: 177 | "@ethersproject/bytes" "^5.6.1" 178 | "@ethersproject/logger" "^5.6.0" 179 | 180 | "@ethersproject/sha2@^5.6.1": 181 | version "5.6.1" 182 | resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.1.tgz#211f14d3f5da5301c8972a8827770b6fd3e51656" 183 | integrity sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g== 184 | dependencies: 185 | "@ethersproject/bytes" "^5.6.1" 186 | "@ethersproject/logger" "^5.6.0" 187 | hash.js "1.1.7" 188 | 189 | "@ethersproject/signing-key@^5.6.2": 190 | version "5.6.2" 191 | resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3" 192 | integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ== 193 | dependencies: 194 | "@ethersproject/bytes" "^5.6.1" 195 | "@ethersproject/logger" "^5.6.0" 196 | "@ethersproject/properties" "^5.6.0" 197 | bn.js "^5.2.1" 198 | elliptic "6.5.4" 199 | hash.js "1.1.7" 200 | 201 | "@ethersproject/strings@^5.6.1": 202 | version "5.6.1" 203 | resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952" 204 | integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw== 205 | dependencies: 206 | "@ethersproject/bytes" "^5.6.1" 207 | "@ethersproject/constants" "^5.6.1" 208 | "@ethersproject/logger" "^5.6.0" 209 | 210 | "@ethersproject/transactions@^5.6.2": 211 | version "5.6.2" 212 | resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b" 213 | integrity sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q== 214 | dependencies: 215 | "@ethersproject/address" "^5.6.1" 216 | "@ethersproject/bignumber" "^5.6.2" 217 | "@ethersproject/bytes" "^5.6.1" 218 | "@ethersproject/constants" "^5.6.1" 219 | "@ethersproject/keccak256" "^5.6.1" 220 | "@ethersproject/logger" "^5.6.0" 221 | "@ethersproject/properties" "^5.6.0" 222 | "@ethersproject/rlp" "^5.6.1" 223 | "@ethersproject/signing-key" "^5.6.2" 224 | 225 | "@ethersproject/wallet@^5.6.2": 226 | version "5.6.2" 227 | resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.2.tgz#cd61429d1e934681e413f4bc847a5f2f87e3a03c" 228 | integrity sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg== 229 | dependencies: 230 | "@ethersproject/abstract-provider" "^5.6.1" 231 | "@ethersproject/abstract-signer" "^5.6.2" 232 | "@ethersproject/address" "^5.6.1" 233 | "@ethersproject/bignumber" "^5.6.2" 234 | "@ethersproject/bytes" "^5.6.1" 235 | "@ethersproject/hash" "^5.6.1" 236 | "@ethersproject/hdnode" "^5.6.2" 237 | "@ethersproject/json-wallets" "^5.6.1" 238 | "@ethersproject/keccak256" "^5.6.1" 239 | "@ethersproject/logger" "^5.6.0" 240 | "@ethersproject/properties" "^5.6.0" 241 | "@ethersproject/random" "^5.6.1" 242 | "@ethersproject/signing-key" "^5.6.2" 243 | "@ethersproject/transactions" "^5.6.2" 244 | "@ethersproject/wordlists" "^5.6.1" 245 | 246 | "@ethersproject/web@^5.6.1": 247 | version "5.6.1" 248 | resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d" 249 | integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA== 250 | dependencies: 251 | "@ethersproject/base64" "^5.6.1" 252 | "@ethersproject/bytes" "^5.6.1" 253 | "@ethersproject/logger" "^5.6.0" 254 | "@ethersproject/properties" "^5.6.0" 255 | "@ethersproject/strings" "^5.6.1" 256 | 257 | "@ethersproject/wordlists@^5.6.1": 258 | version "5.6.1" 259 | resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.1.tgz#1e78e2740a8a21e9e99947e47979d72e130aeda1" 260 | integrity sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw== 261 | dependencies: 262 | "@ethersproject/bytes" "^5.6.1" 263 | "@ethersproject/hash" "^5.6.1" 264 | "@ethersproject/logger" "^5.6.0" 265 | "@ethersproject/properties" "^5.6.0" 266 | "@ethersproject/strings" "^5.6.1" 267 | 268 | "@graphql-typed-document-node/core@^3.1.1": 269 | version "3.1.1" 270 | resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" 271 | integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg== 272 | 273 | "@sindresorhus/is@^4.0.0": 274 | version "4.6.0" 275 | resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" 276 | integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== 277 | 278 | "@supabase/functions-js@^1.3.4": 279 | version "1.3.4" 280 | resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-1.3.4.tgz#44f86f7cf949baa7f1bb414f3b8c0985a19df633" 281 | integrity sha512-yYVgkECjv7IZEBKBI3EB5Q7R1p0FJ10g8Q9N7SWKIHUU6i6DnbEGHIMFLyQRm1hmiNWD8fL7bRVEYacmTRJhHw== 282 | dependencies: 283 | cross-fetch "^3.1.5" 284 | 285 | "@supabase/gotrue-js@^1.22.21": 286 | version "1.22.21" 287 | resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-1.22.21.tgz#99ac0f49d72dc64a362cbc740553841aa40936a7" 288 | integrity sha512-AhsbBU+5j7BKSqfpLDkEcxy3ruDD+J+dHaYxXGHNWiiIJBYtK2jmNcMYA7M30MYjajnhoILJFC7LtHWl1lWj2Q== 289 | dependencies: 290 | cross-fetch "^3.0.6" 291 | 292 | "@supabase/postgrest-js@^0.37.4": 293 | version "0.37.4" 294 | resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-0.37.4.tgz#8bc2a1353e139962dca931a8e7c8416d60b4a8ed" 295 | integrity sha512-x+c2rk1fz9s6f1PrGxCJ0QTUgXPDI0G3ngIqD5sSiXhhCyfl8Q5V92mXl2EYtlDhkiUkjFNrOZFhXVbXOHgvDw== 296 | dependencies: 297 | cross-fetch "^3.1.5" 298 | 299 | "@supabase/realtime-js@^1.7.4": 300 | version "1.7.4" 301 | resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-1.7.4.tgz#701a4f87b3068b239d9f937ccde8850a174acf88" 302 | integrity sha512-h/Jk3PCLkIVonsNavof/LvHbvF41UD+D+mWcA3m8yHzJ2TLbV3S4XDYId+A3AkvFOAork7Ns/9O8rK0uY4F4zw== 303 | dependencies: 304 | "@types/phoenix" "^1.5.4" 305 | websocket "^1.0.34" 306 | 307 | "@supabase/storage-js@^1.7.2": 308 | version "1.7.3" 309 | resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-1.7.3.tgz#b53cd6d289e2223919e6526364fd46977a643fbe" 310 | integrity sha512-jnIZWqOc9TGclOozgX9v/RWGFCgJAyW/yvmauexgRZhWknUXoA4b2i8tj7vfwE0WTvNRuA5JpXID98rfJeSG7Q== 311 | dependencies: 312 | cross-fetch "^3.1.0" 313 | 314 | "@supabase/supabase-js@^1.35.6": 315 | version "1.35.6" 316 | resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-1.35.6.tgz#df5a2c132035ab9e5462ed474587902b3e767a66" 317 | integrity sha512-KDRXRr+kdGwruIUizZPALbe5YccMYFVyZJf1sFWKLncaLYSFiM6iKFnqCrNeQ4JFoZZiICkiTl1FUuai62jVpg== 318 | dependencies: 319 | "@supabase/functions-js" "^1.3.4" 320 | "@supabase/gotrue-js" "^1.22.21" 321 | "@supabase/postgrest-js" "^0.37.4" 322 | "@supabase/realtime-js" "^1.7.4" 323 | "@supabase/storage-js" "^1.7.2" 324 | 325 | "@szmarczak/http-timer@^4.0.5": 326 | version "4.0.6" 327 | resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" 328 | integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== 329 | dependencies: 330 | defer-to-connect "^2.0.0" 331 | 332 | "@types/cacheable-request@^6.0.1": 333 | version "6.0.2" 334 | resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" 335 | integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA== 336 | dependencies: 337 | "@types/http-cache-semantics" "*" 338 | "@types/keyv" "*" 339 | "@types/node" "*" 340 | "@types/responselike" "*" 341 | 342 | "@types/http-cache-semantics@*": 343 | version "4.0.1" 344 | resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" 345 | integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== 346 | 347 | "@types/json-buffer@~3.0.0": 348 | version "3.0.0" 349 | resolved "https://registry.yarnpkg.com/@types/json-buffer/-/json-buffer-3.0.0.tgz#85c1ff0f0948fc159810d4b5be35bf8c20875f64" 350 | integrity sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ== 351 | 352 | "@types/keyv@*": 353 | version "3.1.4" 354 | resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" 355 | integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== 356 | dependencies: 357 | "@types/node" "*" 358 | 359 | "@types/node@*": 360 | version "18.6.5" 361 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.5.tgz#06caea822caf9e59d5034b695186ee74154d2802" 362 | integrity sha512-Xjt5ZGUa5WusGZJ4WJPbOT8QOqp6nDynVFRKcUt32bOgvXEoc6o085WNkYTMO7ifAj2isEfQQ2cseE+wT6jsRw== 363 | 364 | "@types/phoenix@^1.5.4": 365 | version "1.5.4" 366 | resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.5.4.tgz#c08a1da6d7b4e365f6a1fe1ff9aada55f5356d24" 367 | integrity sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ== 368 | 369 | "@types/responselike@*", "@types/responselike@^1.0.0": 370 | version "1.0.0" 371 | resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" 372 | integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== 373 | dependencies: 374 | "@types/node" "*" 375 | 376 | "@urql/core@^2.6.1": 377 | version "2.6.1" 378 | resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.6.1.tgz#c10ee972c5e81df6d7bf1e778ef1b5d30e2906e5" 379 | integrity sha512-gYrEHy3tViJhwIhauK6MIf2Qp09QTsgNHZRd0n71rS+hF6gdwjspf1oKljl4m25+272cJF7fPjBUGmjaiEr7Kg== 380 | dependencies: 381 | "@graphql-typed-document-node/core" "^3.1.1" 382 | wonka "^4.0.14" 383 | 384 | aes-js@3.0.0: 385 | version "3.0.0" 386 | resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" 387 | integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== 388 | 389 | bn.js@^4.11.9: 390 | version "4.12.0" 391 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" 392 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 393 | 394 | bn.js@^5.2.1: 395 | version "5.2.1" 396 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" 397 | integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== 398 | 399 | boolbase@^1.0.0: 400 | version "1.0.0" 401 | resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 402 | integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== 403 | 404 | brorand@^1.1.0: 405 | version "1.1.0" 406 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 407 | integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== 408 | 409 | bufferutil@^4.0.1: 410 | version "4.0.6" 411 | resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.6.tgz#ebd6c67c7922a0e902f053e5d8be5ec850e48433" 412 | integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== 413 | dependencies: 414 | node-gyp-build "^4.3.0" 415 | 416 | cacheable-lookup@^5.0.3: 417 | version "5.0.4" 418 | resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" 419 | integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== 420 | 421 | cacheable-request@^7.0.2: 422 | version "7.0.2" 423 | resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" 424 | integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== 425 | dependencies: 426 | clone-response "^1.0.2" 427 | get-stream "^5.1.0" 428 | http-cache-semantics "^4.0.0" 429 | keyv "^4.0.0" 430 | lowercase-keys "^2.0.0" 431 | normalize-url "^6.0.1" 432 | responselike "^2.0.0" 433 | 434 | chardet@^1.4.0: 435 | version "1.4.0" 436 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-1.4.0.tgz#278748f260219990fb2167dbfb1b253ca26b41ea" 437 | integrity sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A== 438 | 439 | cheerio-select@^2.1.0: 440 | version "2.1.0" 441 | resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" 442 | integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== 443 | dependencies: 444 | boolbase "^1.0.0" 445 | css-select "^5.1.0" 446 | css-what "^6.1.0" 447 | domelementtype "^2.3.0" 448 | domhandler "^5.0.3" 449 | domutils "^3.0.1" 450 | 451 | cheerio@^1.0.0-rc.11: 452 | version "1.0.0-rc.12" 453 | resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" 454 | integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== 455 | dependencies: 456 | cheerio-select "^2.1.0" 457 | dom-serializer "^2.0.0" 458 | domhandler "^5.0.3" 459 | domutils "^3.0.1" 460 | htmlparser2 "^8.0.1" 461 | parse5 "^7.0.0" 462 | parse5-htmlparser2-tree-adapter "^7.0.0" 463 | 464 | clone-response@^1.0.2: 465 | version "1.0.3" 466 | resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" 467 | integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== 468 | dependencies: 469 | mimic-response "^1.0.0" 470 | 471 | compress-brotli@^1.3.8: 472 | version "1.3.8" 473 | resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" 474 | integrity sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ== 475 | dependencies: 476 | "@types/json-buffer" "~3.0.0" 477 | json-buffer "~3.0.1" 478 | 479 | cross-fetch@^3.0.6, cross-fetch@^3.1.0, cross-fetch@^3.1.5: 480 | version "3.1.5" 481 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" 482 | integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== 483 | dependencies: 484 | node-fetch "2.6.7" 485 | 486 | css-select@^5.1.0: 487 | version "5.1.0" 488 | resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" 489 | integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== 490 | dependencies: 491 | boolbase "^1.0.0" 492 | css-what "^6.1.0" 493 | domhandler "^5.0.2" 494 | domutils "^3.0.1" 495 | nth-check "^2.0.1" 496 | 497 | css-what@^6.1.0: 498 | version "6.1.0" 499 | resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" 500 | integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== 501 | 502 | d@1, d@^1.0.1: 503 | version "1.0.1" 504 | resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" 505 | integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== 506 | dependencies: 507 | es5-ext "^0.10.50" 508 | type "^1.0.1" 509 | 510 | data-uri-to-buffer@^4.0.0: 511 | version "4.0.0" 512 | resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" 513 | integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== 514 | 515 | debug@^2.2.0: 516 | version "2.6.9" 517 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 518 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 519 | dependencies: 520 | ms "2.0.0" 521 | 522 | decompress-response@^6.0.0: 523 | version "6.0.0" 524 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" 525 | integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== 526 | dependencies: 527 | mimic-response "^3.1.0" 528 | 529 | defer-to-connect@^2.0.0: 530 | version "2.0.1" 531 | resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" 532 | integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== 533 | 534 | dom-serializer@^2.0.0: 535 | version "2.0.0" 536 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" 537 | integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== 538 | dependencies: 539 | domelementtype "^2.3.0" 540 | domhandler "^5.0.2" 541 | entities "^4.2.0" 542 | 543 | domelementtype@^2.3.0: 544 | version "2.3.0" 545 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" 546 | integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 547 | 548 | domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: 549 | version "5.0.3" 550 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" 551 | integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== 552 | dependencies: 553 | domelementtype "^2.3.0" 554 | 555 | domutils@^3.0.1: 556 | version "3.0.1" 557 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" 558 | integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== 559 | dependencies: 560 | dom-serializer "^2.0.0" 561 | domelementtype "^2.3.0" 562 | domhandler "^5.0.1" 563 | 564 | elliptic@6.5.4: 565 | version "6.5.4" 566 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" 567 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 568 | dependencies: 569 | bn.js "^4.11.9" 570 | brorand "^1.1.0" 571 | hash.js "^1.0.0" 572 | hmac-drbg "^1.0.1" 573 | inherits "^2.0.4" 574 | minimalistic-assert "^1.0.1" 575 | minimalistic-crypto-utils "^1.0.1" 576 | 577 | end-of-stream@^1.1.0: 578 | version "1.4.4" 579 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 580 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 581 | dependencies: 582 | once "^1.4.0" 583 | 584 | entities@^4.2.0, entities@^4.3.0: 585 | version "4.3.1" 586 | resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.1.tgz#c34062a94c865c322f9d67b4384e4169bcede6a4" 587 | integrity sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg== 588 | 589 | es5-ext@^0.10.35, es5-ext@^0.10.50: 590 | version "0.10.62" 591 | resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" 592 | integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== 593 | dependencies: 594 | es6-iterator "^2.0.3" 595 | es6-symbol "^3.1.3" 596 | next-tick "^1.1.0" 597 | 598 | es6-iterator@^2.0.3: 599 | version "2.0.3" 600 | resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" 601 | integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== 602 | dependencies: 603 | d "1" 604 | es5-ext "^0.10.35" 605 | es6-symbol "^3.1.1" 606 | 607 | es6-symbol@^3.1.1, es6-symbol@^3.1.3: 608 | version "3.1.3" 609 | resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" 610 | integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== 611 | dependencies: 612 | d "^1.0.1" 613 | ext "^1.1.2" 614 | 615 | ext@^1.1.2: 616 | version "1.6.0" 617 | resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" 618 | integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== 619 | dependencies: 620 | type "^2.5.0" 621 | 622 | fetch-blob@^3.1.2, fetch-blob@^3.1.4: 623 | version "3.2.0" 624 | resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" 625 | integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== 626 | dependencies: 627 | node-domexception "^1.0.0" 628 | web-streams-polyfill "^3.0.3" 629 | 630 | formdata-polyfill@^4.0.10: 631 | version "4.0.10" 632 | resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" 633 | integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== 634 | dependencies: 635 | fetch-blob "^3.1.2" 636 | 637 | get-stream@^5.1.0: 638 | version "5.2.0" 639 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" 640 | integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== 641 | dependencies: 642 | pump "^3.0.0" 643 | 644 | got@^11.8.5: 645 | version "11.8.5" 646 | resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" 647 | integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== 648 | dependencies: 649 | "@sindresorhus/is" "^4.0.0" 650 | "@szmarczak/http-timer" "^4.0.5" 651 | "@types/cacheable-request" "^6.0.1" 652 | "@types/responselike" "^1.0.0" 653 | cacheable-lookup "^5.0.3" 654 | cacheable-request "^7.0.2" 655 | decompress-response "^6.0.0" 656 | http2-wrapper "^1.0.0-beta.5.2" 657 | lowercase-keys "^2.0.0" 658 | p-cancelable "^2.0.0" 659 | responselike "^2.0.0" 660 | 661 | graphql@^16.5.0: 662 | version "16.5.0" 663 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" 664 | integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== 665 | 666 | hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: 667 | version "1.1.7" 668 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" 669 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 670 | dependencies: 671 | inherits "^2.0.3" 672 | minimalistic-assert "^1.0.1" 673 | 674 | hmac-drbg@^1.0.1: 675 | version "1.0.1" 676 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 677 | integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== 678 | dependencies: 679 | hash.js "^1.0.3" 680 | minimalistic-assert "^1.0.0" 681 | minimalistic-crypto-utils "^1.0.1" 682 | 683 | htmlparser2@^8.0.1: 684 | version "8.0.1" 685 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" 686 | integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== 687 | dependencies: 688 | domelementtype "^2.3.0" 689 | domhandler "^5.0.2" 690 | domutils "^3.0.1" 691 | entities "^4.3.0" 692 | 693 | http-cache-semantics@^4.0.0: 694 | version "4.1.0" 695 | resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" 696 | integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== 697 | 698 | http2-wrapper@^1.0.0-beta.5.2: 699 | version "1.0.3" 700 | resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" 701 | integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== 702 | dependencies: 703 | quick-lru "^5.1.1" 704 | resolve-alpn "^1.0.0" 705 | 706 | iconv-lite@^0.6.3: 707 | version "0.6.3" 708 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 709 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 710 | dependencies: 711 | safer-buffer ">= 2.1.2 < 3.0.0" 712 | 713 | inherits@^2.0.3, inherits@^2.0.4: 714 | version "2.0.4" 715 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 716 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 717 | 718 | ip-regex@^4.1.0: 719 | version "4.3.0" 720 | resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" 721 | integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== 722 | 723 | is-typedarray@^1.0.0: 724 | version "1.0.0" 725 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 726 | integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== 727 | 728 | js-sha3@0.8.0: 729 | version "0.8.0" 730 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" 731 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== 732 | 733 | json-buffer@3.0.1, json-buffer@~3.0.1: 734 | version "3.0.1" 735 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 736 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 737 | 738 | keyv@^4.0.0: 739 | version "4.3.3" 740 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.3.3.tgz#6c1bcda6353a9e96fc1b4e1aeb803a6e35090ba9" 741 | integrity sha512-AcysI17RvakTh8ir03+a3zJr5r0ovnAH/XTXei/4HIv3bL2K/jzvgivLK9UuI/JbU1aJjM3NSAnVvVVd3n+4DQ== 742 | dependencies: 743 | compress-brotli "^1.3.8" 744 | json-buffer "3.0.1" 745 | 746 | lowercase-keys@^2.0.0: 747 | version "2.0.0" 748 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" 749 | integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== 750 | 751 | mimic-response@^1.0.0: 752 | version "1.0.1" 753 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 754 | integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== 755 | 756 | mimic-response@^3.1.0: 757 | version "3.1.0" 758 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" 759 | integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== 760 | 761 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 762 | version "1.0.1" 763 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 764 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 765 | 766 | minimalistic-crypto-utils@^1.0.1: 767 | version "1.0.1" 768 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 769 | integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== 770 | 771 | ms@2.0.0: 772 | version "2.0.0" 773 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 774 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 775 | 776 | next-tick@^1.1.0: 777 | version "1.1.0" 778 | resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" 779 | integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== 780 | 781 | node-domexception@^1.0.0: 782 | version "1.0.0" 783 | resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" 784 | integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== 785 | 786 | node-fetch@2.6.7: 787 | version "2.6.7" 788 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 789 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 790 | dependencies: 791 | whatwg-url "^5.0.0" 792 | 793 | node-fetch@^3.2.10: 794 | version "3.2.10" 795 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.10.tgz#e8347f94b54ae18b57c9c049ef641cef398a85c8" 796 | integrity sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA== 797 | dependencies: 798 | data-uri-to-buffer "^4.0.0" 799 | fetch-blob "^3.1.4" 800 | formdata-polyfill "^4.0.10" 801 | 802 | node-gyp-build@^4.3.0: 803 | version "4.5.0" 804 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" 805 | integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== 806 | 807 | normalize-url@^6.0.1: 808 | version "6.1.0" 809 | resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" 810 | integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== 811 | 812 | normalize-url@^7.0.3: 813 | version "7.0.3" 814 | resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-7.0.3.tgz#12e56889f7a54b2d5b09616f36c442a9063f61af" 815 | integrity sha512-RiCOdwdPnzvwcBFJE4iI1ss3dMVRIrEzFpn8ftje6iBfzBInqlnRrNhxcLwBEKjPPXQKzm1Ptlxtaiv9wdcj5w== 816 | 817 | nth-check@^2.0.1: 818 | version "2.1.1" 819 | resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" 820 | integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== 821 | dependencies: 822 | boolbase "^1.0.0" 823 | 824 | once@^1.3.1, once@^1.4.0: 825 | version "1.4.0" 826 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 827 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 828 | dependencies: 829 | wrappy "1" 830 | 831 | open-graph-scraper@^4.11.1: 832 | version "4.11.1" 833 | resolved "https://registry.yarnpkg.com/open-graph-scraper/-/open-graph-scraper-4.11.1.tgz#cf52bb8f5703840a6723e8a8911ddbf1628752b2" 834 | integrity sha512-cGffZ6MtlEj6e46MqEnRU0qf+OmQDG3YTZOaEI15lhZMGAoUbu0bUsDFaq4QOz3lc9DHC7JprQeyJkTNqs7HjA== 835 | dependencies: 836 | chardet "^1.4.0" 837 | cheerio "^1.0.0-rc.11" 838 | got "^11.8.5" 839 | iconv-lite "^0.6.3" 840 | validator "^13.7.0" 841 | 842 | p-cancelable@^2.0.0: 843 | version "2.1.1" 844 | resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" 845 | integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== 846 | 847 | parse5-htmlparser2-tree-adapter@^7.0.0: 848 | version "7.0.0" 849 | resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" 850 | integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== 851 | dependencies: 852 | domhandler "^5.0.2" 853 | parse5 "^7.0.0" 854 | 855 | parse5@^7.0.0: 856 | version "7.0.0" 857 | resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a" 858 | integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== 859 | dependencies: 860 | entities "^4.3.0" 861 | 862 | pump@^3.0.0: 863 | version "3.0.0" 864 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 865 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 866 | dependencies: 867 | end-of-stream "^1.1.0" 868 | once "^1.3.1" 869 | 870 | quick-lru@^5.1.1: 871 | version "5.1.1" 872 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" 873 | integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== 874 | 875 | resolve-alpn@^1.0.0: 876 | version "1.2.1" 877 | resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" 878 | integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== 879 | 880 | responselike@^2.0.0: 881 | version "2.0.1" 882 | resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" 883 | integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== 884 | dependencies: 885 | lowercase-keys "^2.0.0" 886 | 887 | "safer-buffer@>= 2.1.2 < 3.0.0": 888 | version "2.1.2" 889 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 890 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 891 | 892 | scrypt-js@3.0.1: 893 | version "3.0.1" 894 | resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" 895 | integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== 896 | 897 | tlds@^1.203.0: 898 | version "1.231.0" 899 | resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.231.0.tgz#93880175cd0a06fdf7b5b5b9bcadff9d94813e39" 900 | integrity sha512-L7UQwueHSkGxZHQBXHVmXW64oi+uqNtzFt2x6Ssk7NVnpIbw16CRs4eb/jmKOZ9t2JnqZ/b3Cfvo97lnXqKrhw== 901 | 902 | tr46@~0.0.3: 903 | version "0.0.3" 904 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 905 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 906 | 907 | type@^1.0.1: 908 | version "1.2.0" 909 | resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" 910 | integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== 911 | 912 | type@^2.5.0: 913 | version "2.7.2" 914 | resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" 915 | integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== 916 | 917 | typedarray-to-buffer@^3.1.5: 918 | version "3.1.5" 919 | resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" 920 | integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== 921 | dependencies: 922 | is-typedarray "^1.0.0" 923 | 924 | url-regex@^5.0.0: 925 | version "5.0.0" 926 | resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-5.0.0.tgz#8f5456ab83d898d18b2f91753a702649b873273a" 927 | integrity sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g== 928 | dependencies: 929 | ip-regex "^4.1.0" 930 | tlds "^1.203.0" 931 | 932 | utf-8-validate@^5.0.2: 933 | version "5.0.9" 934 | resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.9.tgz#ba16a822fbeedff1a58918f2a6a6b36387493ea3" 935 | integrity sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q== 936 | dependencies: 937 | node-gyp-build "^4.3.0" 938 | 939 | validator@^13.7.0: 940 | version "13.7.0" 941 | resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" 942 | integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== 943 | 944 | web-streams-polyfill@^3.0.3: 945 | version "3.2.1" 946 | resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" 947 | integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== 948 | 949 | webidl-conversions@^3.0.0: 950 | version "3.0.1" 951 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 952 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 953 | 954 | websocket@^1.0.34: 955 | version "1.0.34" 956 | resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" 957 | integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== 958 | dependencies: 959 | bufferutil "^4.0.1" 960 | debug "^2.2.0" 961 | es5-ext "^0.10.50" 962 | typedarray-to-buffer "^3.1.5" 963 | utf-8-validate "^5.0.2" 964 | yaeti "^0.0.6" 965 | 966 | whatwg-url@^5.0.0: 967 | version "5.0.0" 968 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 969 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 970 | dependencies: 971 | tr46 "~0.0.3" 972 | webidl-conversions "^3.0.0" 973 | 974 | wonka@^4.0.14: 975 | version "4.0.15" 976 | resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.15.tgz#9aa42046efa424565ab8f8f451fcca955bf80b89" 977 | integrity sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg== 978 | 979 | wrappy@1: 980 | version "1.0.2" 981 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 982 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 983 | 984 | yaeti@^0.0.6: 985 | version "0.0.6" 986 | resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" 987 | integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== 988 | -------------------------------------------------------------------------------- /subgraph/registry-v2/abis/IdRegistry.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { "internalType": "address", "name": "_forwarder", "type": "address" } 5 | ], 6 | "stateMutability": "nonpayable", 7 | "type": "constructor" 8 | }, 9 | { "inputs": [], "name": "Escrow", "type": "error" }, 10 | { "inputs": [], "name": "HasId", "type": "error" }, 11 | { "inputs": [], "name": "HasNoId", "type": "error" }, 12 | { "inputs": [], "name": "Invitable", "type": "error" }, 13 | { "inputs": [], "name": "NoRecovery", "type": "error" }, 14 | { "inputs": [], "name": "Registrable", "type": "error" }, 15 | { "inputs": [], "name": "Unauthorized", "type": "error" }, 16 | { 17 | "anonymous": false, 18 | "inputs": [ 19 | { 20 | "indexed": true, 21 | "internalType": "address", 22 | "name": "by", 23 | "type": "address" 24 | }, 25 | { 26 | "indexed": true, 27 | "internalType": "uint256", 28 | "name": "id", 29 | "type": "uint256" 30 | } 31 | ], 32 | "name": "CancelRecovery", 33 | "type": "event" 34 | }, 35 | { 36 | "anonymous": false, 37 | "inputs": [ 38 | { 39 | "indexed": true, 40 | "internalType": "uint256", 41 | "name": "id", 42 | "type": "uint256" 43 | }, 44 | { 45 | "indexed": false, 46 | "internalType": "string", 47 | "name": "url", 48 | "type": "string" 49 | } 50 | ], 51 | "name": "ChangeHome", 52 | "type": "event" 53 | }, 54 | { 55 | "anonymous": false, 56 | "inputs": [ 57 | { 58 | "indexed": true, 59 | "internalType": "uint256", 60 | "name": "id", 61 | "type": "uint256" 62 | }, 63 | { 64 | "indexed": true, 65 | "internalType": "address", 66 | "name": "recovery", 67 | "type": "address" 68 | } 69 | ], 70 | "name": "ChangeRecoveryAddress", 71 | "type": "event" 72 | }, 73 | { 74 | "anonymous": false, 75 | "inputs": [ 76 | { 77 | "indexed": true, 78 | "internalType": "address", 79 | "name": "trustedCaller", 80 | "type": "address" 81 | } 82 | ], 83 | "name": "ChangeTrustedCaller", 84 | "type": "event" 85 | }, 86 | { 87 | "anonymous": false, 88 | "inputs": [], 89 | "name": "DisableTrustedOnly", 90 | "type": "event" 91 | }, 92 | { 93 | "anonymous": false, 94 | "inputs": [ 95 | { 96 | "indexed": true, 97 | "internalType": "address", 98 | "name": "previousOwner", 99 | "type": "address" 100 | }, 101 | { 102 | "indexed": true, 103 | "internalType": "address", 104 | "name": "newOwner", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "OwnershipTransferred", 109 | "type": "event" 110 | }, 111 | { 112 | "anonymous": false, 113 | "inputs": [ 114 | { 115 | "indexed": true, 116 | "internalType": "address", 117 | "name": "to", 118 | "type": "address" 119 | }, 120 | { 121 | "indexed": true, 122 | "internalType": "uint256", 123 | "name": "id", 124 | "type": "uint256" 125 | }, 126 | { 127 | "indexed": false, 128 | "internalType": "address", 129 | "name": "recovery", 130 | "type": "address" 131 | }, 132 | { 133 | "indexed": false, 134 | "internalType": "string", 135 | "name": "url", 136 | "type": "string" 137 | } 138 | ], 139 | "name": "Register", 140 | "type": "event" 141 | }, 142 | { 143 | "anonymous": false, 144 | "inputs": [ 145 | { 146 | "indexed": true, 147 | "internalType": "address", 148 | "name": "from", 149 | "type": "address" 150 | }, 151 | { 152 | "indexed": true, 153 | "internalType": "address", 154 | "name": "to", 155 | "type": "address" 156 | }, 157 | { 158 | "indexed": true, 159 | "internalType": "uint256", 160 | "name": "id", 161 | "type": "uint256" 162 | } 163 | ], 164 | "name": "RequestRecovery", 165 | "type": "event" 166 | }, 167 | { 168 | "anonymous": false, 169 | "inputs": [ 170 | { 171 | "indexed": true, 172 | "internalType": "address", 173 | "name": "from", 174 | "type": "address" 175 | }, 176 | { 177 | "indexed": true, 178 | "internalType": "address", 179 | "name": "to", 180 | "type": "address" 181 | }, 182 | { 183 | "indexed": true, 184 | "internalType": "uint256", 185 | "name": "id", 186 | "type": "uint256" 187 | } 188 | ], 189 | "name": "Transfer", 190 | "type": "event" 191 | }, 192 | { 193 | "inputs": [ 194 | { "internalType": "address", "name": "from", "type": "address" } 195 | ], 196 | "name": "cancelRecovery", 197 | "outputs": [], 198 | "stateMutability": "nonpayable", 199 | "type": "function" 200 | }, 201 | { 202 | "inputs": [{ "internalType": "string", "name": "url", "type": "string" }], 203 | "name": "changeHome", 204 | "outputs": [], 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | }, 208 | { 209 | "inputs": [ 210 | { "internalType": "address", "name": "recovery", "type": "address" } 211 | ], 212 | "name": "changeRecoveryAddress", 213 | "outputs": [], 214 | "stateMutability": "nonpayable", 215 | "type": "function" 216 | }, 217 | { 218 | "inputs": [ 219 | { "internalType": "address", "name": "_trustedCaller", "type": "address" } 220 | ], 221 | "name": "changeTrustedCaller", 222 | "outputs": [], 223 | "stateMutability": "nonpayable", 224 | "type": "function" 225 | }, 226 | { 227 | "inputs": [ 228 | { "internalType": "address", "name": "from", "type": "address" } 229 | ], 230 | "name": "completeRecovery", 231 | "outputs": [], 232 | "stateMutability": "nonpayable", 233 | "type": "function" 234 | }, 235 | { 236 | "inputs": [], 237 | "name": "completeTransferOwnership", 238 | "outputs": [], 239 | "stateMutability": "nonpayable", 240 | "type": "function" 241 | }, 242 | { 243 | "inputs": [], 244 | "name": "disableTrustedOnly", 245 | "outputs": [], 246 | "stateMutability": "nonpayable", 247 | "type": "function" 248 | }, 249 | { 250 | "inputs": [{ "internalType": "address", "name": "", "type": "address" }], 251 | "name": "idOf", 252 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 253 | "stateMutability": "view", 254 | "type": "function" 255 | }, 256 | { 257 | "inputs": [ 258 | { "internalType": "address", "name": "forwarder", "type": "address" } 259 | ], 260 | "name": "isTrustedForwarder", 261 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], 262 | "stateMutability": "view", 263 | "type": "function" 264 | }, 265 | { 266 | "inputs": [], 267 | "name": "owner", 268 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 269 | "stateMutability": "view", 270 | "type": "function" 271 | }, 272 | { 273 | "inputs": [ 274 | { "internalType": "address", "name": "to", "type": "address" }, 275 | { "internalType": "address", "name": "recovery", "type": "address" }, 276 | { "internalType": "string", "name": "url", "type": "string" } 277 | ], 278 | "name": "register", 279 | "outputs": [], 280 | "stateMutability": "nonpayable", 281 | "type": "function" 282 | }, 283 | { 284 | "inputs": [], 285 | "name": "renounceOwnership", 286 | "outputs": [], 287 | "stateMutability": "nonpayable", 288 | "type": "function" 289 | }, 290 | { 291 | "inputs": [ 292 | { "internalType": "address", "name": "from", "type": "address" }, 293 | { "internalType": "address", "name": "to", "type": "address" } 294 | ], 295 | "name": "requestRecovery", 296 | "outputs": [], 297 | "stateMutability": "nonpayable", 298 | "type": "function" 299 | }, 300 | { 301 | "inputs": [ 302 | { "internalType": "address", "name": "newOwner", "type": "address" } 303 | ], 304 | "name": "requestTransferOwnership", 305 | "outputs": [], 306 | "stateMutability": "nonpayable", 307 | "type": "function" 308 | }, 309 | { 310 | "inputs": [{ "internalType": "address", "name": "to", "type": "address" }], 311 | "name": "transfer", 312 | "outputs": [], 313 | "stateMutability": "nonpayable", 314 | "type": "function" 315 | }, 316 | { 317 | "inputs": [{ "internalType": "address", "name": "", "type": "address" }], 318 | "name": "transferOwnership", 319 | "outputs": [], 320 | "stateMutability": "view", 321 | "type": "function" 322 | }, 323 | { 324 | "inputs": [ 325 | { "internalType": "address", "name": "to", "type": "address" }, 326 | { "internalType": "address", "name": "recovery", "type": "address" }, 327 | { "internalType": "string", "name": "url", "type": "string" } 328 | ], 329 | "name": "trustedRegister", 330 | "outputs": [], 331 | "stateMutability": "nonpayable", 332 | "type": "function" 333 | } 334 | ] 335 | -------------------------------------------------------------------------------- /subgraph/registry-v2/abis/NameRegistry.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"_forwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallFailed","type":"error"},{"inputs":[],"name":"CommitReplay","type":"error"},{"inputs":[],"name":"Escrow","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidCommit","type":"error"},{"inputs":[],"name":"InvalidName","type":"error"},{"inputs":[],"name":"InvalidRecovery","type":"error"},{"inputs":[],"name":"Invitable","type":"error"},{"inputs":[],"name":"NoRecovery","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotBiddable","type":"error"},{"inputs":[],"name":"NotInvitable","type":"error"},{"inputs":[],"name":"NotModerator","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotRenewable","type":"error"},{"inputs":[],"name":"NotTreasurer","type":"error"},{"inputs":[],"name":"Registered","type":"error"},{"inputs":[],"name":"Registrable","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"CancelRecovery","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"ChangeFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"ChangePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recovery","type":"address"}],"name":"ChangeRecoveryAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trustedCaller","type":"address"}],"name":"ChangeTrustedCaller","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"ChangeVault","type":"event"},{"anonymous":false,"inputs":[],"name":"DisableTrustedOnly","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"inviterId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"inviteeId","type":"uint256"},{"indexed":true,"internalType":"bytes16","name":"fname","type":"bytes16"}],"name":"Invite","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"Renew","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"RequestRecovery","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recovery","type":"address"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"cancelRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"changeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"changePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recovery","type":"address"}],"name":"changeRecoveryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"}],"name":"changeTrustedCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"changeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"completeRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableTrustedOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"expiryOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"fname","type":"bytes16"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"secret","type":"bytes32"},{"internalType":"address","name":"recovery","type":"address"}],"name":"generateCommit","outputs":[{"internalType":"bytes32","name":"commit","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_tokenName","type":"string"},{"internalType":"string","name":"_tokenSymbol","type":"string"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_pool","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commit","type":"bytes32"}],"name":"makeCommit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"reclaim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"recoveryClockOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"recoveryDestinationOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"recoveryOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"fname","type":"bytes16"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"secret","type":"bytes32"},{"internalType":"address","name":"recovery","type":"address"}],"name":"register","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"renew","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"requestRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"timestampOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedOnly","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"fname","type":"bytes16"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"recovery","type":"address"},{"internalType":"uint256","name":"inviter","type":"uint256"},{"internalType":"uint256","name":"invitee","type":"uint256"}],"name":"trustedRegister","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}] 2 | -------------------------------------------------------------------------------- /subgraph/registry-v2/networks.json: -------------------------------------------------------------------------------- 1 | { 2 | "goerli": { 3 | "IdRegistry": { 4 | "address": "0xDA107A1CAf36d198B12c16c7B6a1d1C795978C42" 5 | }, 6 | "NameRegistry": { 7 | "address": "0xe3Be01D99bAa8dB9905b33a3cA391238234B79D1" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /subgraph/registry-v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "farcaster-registry-v2", 3 | "license": "UNLICENSED", 4 | "scripts": { 5 | "codegen": "graph codegen", 6 | "build": "graph build", 7 | "deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ farcaster-registry-v2", 8 | "create-local": "graph create --node http://localhost:8020/ farcaster-registry-v2", 9 | "remove-local": "graph remove --node http://localhost:8020/ farcaster-registry-v2", 10 | "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 farcaster-registry-v2", 11 | "test": "graph test" 12 | }, 13 | "dependencies": { 14 | "@graphprotocol/graph-cli": "0.33.0", 15 | "@graphprotocol/graph-ts": "0.27.0" 16 | }, 17 | "devDependencies": { "matchstick-as": "0.5.0" } 18 | } 19 | -------------------------------------------------------------------------------- /subgraph/registry-v2/schema.graphql: -------------------------------------------------------------------------------- 1 | type Account @entity { 2 | id: ID! 3 | address: Bytes! # address 4 | url: String! 5 | createdAt: BigInt! 6 | updatedAt: BigInt! 7 | } 8 | 9 | type Name @entity { 10 | id: ID! 11 | address: Bytes! # address 12 | createdAt: BigInt! 13 | updatedAt: BigInt! 14 | } -------------------------------------------------------------------------------- /subgraph/registry-v2/src/id-registry.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeHome, 3 | Register, 4 | Transfer 5 | } from "../generated/IdRegistry/IdRegistry" 6 | import { Account } from "../generated/schema" 7 | 8 | export function handleRegister(event: Register): void { 9 | let account = new Account(event.params.id.toString()) 10 | account.address = event.params.to 11 | account.url = event.params.url 12 | account.createdAt = event.block.timestamp 13 | account.updatedAt = event.block.timestamp 14 | account.save() 15 | } 16 | 17 | export function handleChangeHome(event: ChangeHome): void { 18 | let account = Account.load(event.params.id.toString()) 19 | if (account) { 20 | account.url = event.params.url 21 | account.updatedAt = event.block.timestamp 22 | account.save() 23 | } 24 | } 25 | 26 | export function handleTransfer(event: Transfer): void { 27 | let account = Account.load(event.params.id.toString()) 28 | if (account) { 29 | account.address = event.params.to 30 | account.updatedAt = event.block.timestamp 31 | account.save() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subgraph/registry-v2/src/name-registry.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Transfer 3 | } from "../generated/NameRegistry/NameRegistry" 4 | import { 5 | Name 6 | } from "../generated/schema" 7 | 8 | export function handleTransfer( 9 | event: Transfer 10 | ): void { 11 | let name = Name.load(event.params.tokenId.toString()) 12 | if (name) { 13 | name.address = event.params.to 14 | } else { 15 | name = new Name(event.params.tokenId.toString()) 16 | name.address = event.params.to 17 | name.createdAt = event.block.timestamp 18 | } 19 | name.updatedAt = event.block.timestamp 20 | name.save() 21 | } -------------------------------------------------------------------------------- /subgraph/registry-v2/subgraph.yaml: -------------------------------------------------------------------------------- 1 | specVersion: 0.0.4 2 | schema: 3 | file: ./schema.graphql 4 | dataSources: 5 | - kind: ethereum 6 | name: IdRegistry 7 | network: goerli 8 | source: 9 | address: "0xDA107A1CAf36d198B12c16c7B6a1d1C795978C42" 10 | abi: IdRegistry 11 | mapping: 12 | kind: ethereum/events 13 | apiVersion: 0.0.6 14 | language: wasm/assemblyscript 15 | entities: 16 | - ChangeHome 17 | - Register 18 | - Transfer 19 | abis: 20 | - name: IdRegistry 21 | file: ./abis/IdRegistry.json 22 | eventHandlers: 23 | - event: ChangeHome(indexed uint256,string) 24 | handler: handleChangeHome 25 | - event: Register(indexed address,indexed uint256,address,string) 26 | handler: handleRegister 27 | - event: Transfer(indexed address,indexed address,indexed uint256) 28 | handler: handleTransfer 29 | file: ./src/id-registry.ts 30 | - kind: ethereum 31 | name: NameRegistry 32 | network: goerli 33 | source: 34 | address: "0xe3Be01D99bAa8dB9905b33a3cA391238234B79D1" 35 | abi: NameRegistry 36 | mapping: 37 | kind: ethereum/events 38 | apiVersion: 0.0.6 39 | language: wasm/assemblyscript 40 | entities: 41 | - Transfer 42 | abis: 43 | - name: NameRegistry 44 | file: ./abis/NameRegistry.json 45 | eventHandlers: 46 | - event: Transfer(indexed address,indexed address,indexed uint256) 47 | handler: handleTransfer 48 | file: ./src/name-registry.ts 49 | -------------------------------------------------------------------------------- /subgraph/registry-v2/tests/id-registry-utils.ts: -------------------------------------------------------------------------------- 1 | import { newMockEvent } from "matchstick-as" 2 | import { ethereum, Address, BigInt } from "@graphprotocol/graph-ts" 3 | import { 4 | CancelRecovery, 5 | ChangeHome, 6 | ChangeRecoveryAddress, 7 | ChangeTrustedCaller, 8 | DisableTrustedOnly, 9 | OwnershipTransferred, 10 | Register, 11 | RequestRecovery, 12 | Transfer 13 | } from "../generated/IdRegistry/IdRegistry" 14 | 15 | export function createCancelRecoveryEvent( 16 | by: Address, 17 | id: BigInt 18 | ): CancelRecovery { 19 | let cancelRecoveryEvent = changetype(newMockEvent()) 20 | 21 | cancelRecoveryEvent.parameters = new Array() 22 | 23 | cancelRecoveryEvent.parameters.push( 24 | new ethereum.EventParam("by", ethereum.Value.fromAddress(by)) 25 | ) 26 | cancelRecoveryEvent.parameters.push( 27 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 28 | ) 29 | 30 | return cancelRecoveryEvent 31 | } 32 | 33 | export function createChangeHomeEvent(id: BigInt, url: string): ChangeHome { 34 | let changeHomeEvent = changetype(newMockEvent()) 35 | 36 | changeHomeEvent.parameters = new Array() 37 | 38 | changeHomeEvent.parameters.push( 39 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 40 | ) 41 | changeHomeEvent.parameters.push( 42 | new ethereum.EventParam("url", ethereum.Value.fromString(url)) 43 | ) 44 | 45 | return changeHomeEvent 46 | } 47 | 48 | export function createChangeRecoveryAddressEvent( 49 | id: BigInt, 50 | recovery: Address 51 | ): ChangeRecoveryAddress { 52 | let changeRecoveryAddressEvent = changetype( 53 | newMockEvent() 54 | ) 55 | 56 | changeRecoveryAddressEvent.parameters = new Array() 57 | 58 | changeRecoveryAddressEvent.parameters.push( 59 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 60 | ) 61 | changeRecoveryAddressEvent.parameters.push( 62 | new ethereum.EventParam("recovery", ethereum.Value.fromAddress(recovery)) 63 | ) 64 | 65 | return changeRecoveryAddressEvent 66 | } 67 | 68 | export function createChangeTrustedCallerEvent( 69 | trustedCaller: Address 70 | ): ChangeTrustedCaller { 71 | let changeTrustedCallerEvent = changetype(newMockEvent()) 72 | 73 | changeTrustedCallerEvent.parameters = new Array() 74 | 75 | changeTrustedCallerEvent.parameters.push( 76 | new ethereum.EventParam( 77 | "trustedCaller", 78 | ethereum.Value.fromAddress(trustedCaller) 79 | ) 80 | ) 81 | 82 | return changeTrustedCallerEvent 83 | } 84 | 85 | export function createDisableTrustedOnlyEvent(): DisableTrustedOnly { 86 | let disableTrustedOnlyEvent = changetype(newMockEvent()) 87 | 88 | disableTrustedOnlyEvent.parameters = new Array() 89 | 90 | return disableTrustedOnlyEvent 91 | } 92 | 93 | export function createOwnershipTransferredEvent( 94 | previousOwner: Address, 95 | newOwner: Address 96 | ): OwnershipTransferred { 97 | let ownershipTransferredEvent = changetype( 98 | newMockEvent() 99 | ) 100 | 101 | ownershipTransferredEvent.parameters = new Array() 102 | 103 | ownershipTransferredEvent.parameters.push( 104 | new ethereum.EventParam( 105 | "previousOwner", 106 | ethereum.Value.fromAddress(previousOwner) 107 | ) 108 | ) 109 | ownershipTransferredEvent.parameters.push( 110 | new ethereum.EventParam("newOwner", ethereum.Value.fromAddress(newOwner)) 111 | ) 112 | 113 | return ownershipTransferredEvent 114 | } 115 | 116 | export function createRegisterEvent( 117 | to: Address, 118 | id: BigInt, 119 | recovery: Address, 120 | url: string 121 | ): Register { 122 | let registerEvent = changetype(newMockEvent()) 123 | 124 | registerEvent.parameters = new Array() 125 | 126 | registerEvent.parameters.push( 127 | new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) 128 | ) 129 | registerEvent.parameters.push( 130 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 131 | ) 132 | registerEvent.parameters.push( 133 | new ethereum.EventParam("recovery", ethereum.Value.fromAddress(recovery)) 134 | ) 135 | registerEvent.parameters.push( 136 | new ethereum.EventParam("url", ethereum.Value.fromString(url)) 137 | ) 138 | 139 | return registerEvent 140 | } 141 | 142 | export function createRequestRecoveryEvent( 143 | from: Address, 144 | to: Address, 145 | id: BigInt 146 | ): RequestRecovery { 147 | let requestRecoveryEvent = changetype(newMockEvent()) 148 | 149 | requestRecoveryEvent.parameters = new Array() 150 | 151 | requestRecoveryEvent.parameters.push( 152 | new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) 153 | ) 154 | requestRecoveryEvent.parameters.push( 155 | new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) 156 | ) 157 | requestRecoveryEvent.parameters.push( 158 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 159 | ) 160 | 161 | return requestRecoveryEvent 162 | } 163 | 164 | export function createTransferEvent( 165 | from: Address, 166 | to: Address, 167 | id: BigInt 168 | ): Transfer { 169 | let transferEvent = changetype(newMockEvent()) 170 | 171 | transferEvent.parameters = new Array() 172 | 173 | transferEvent.parameters.push( 174 | new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) 175 | ) 176 | transferEvent.parameters.push( 177 | new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) 178 | ) 179 | transferEvent.parameters.push( 180 | new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) 181 | ) 182 | 183 | return transferEvent 184 | } 185 | -------------------------------------------------------------------------------- /subgraph/registry-v2/tests/id-registry.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | assert, 3 | describe, 4 | test, 5 | clearStore, 6 | beforeAll, 7 | afterAll 8 | } from "matchstick-as/assembly/index" 9 | import { Address, BigInt } from "@graphprotocol/graph-ts" 10 | import { ExampleEntity } from "../generated/schema" 11 | import { CancelRecovery } from "../generated/IdRegistry/IdRegistry" 12 | import { handleCancelRecovery } from "../src/id-registry" 13 | import { createCancelRecoveryEvent } from "./id-registry-utils" 14 | 15 | // Tests structure (matchstick-as >=0.5.0) 16 | // https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 17 | 18 | describe("Describe entity assertions", () => { 19 | beforeAll(() => { 20 | let by = Address.fromString("0x0000000000000000000000000000000000000001") 21 | let id = BigInt.fromI32(234) 22 | let newCancelRecoveryEvent = createCancelRecoveryEvent(by, id) 23 | handleCancelRecovery(newCancelRecoveryEvent) 24 | }) 25 | 26 | afterAll(() => { 27 | clearStore() 28 | }) 29 | 30 | // For more test scenarios, see: 31 | // https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test 32 | 33 | test("ExampleEntity created and stored", () => { 34 | assert.entityCount("ExampleEntity", 1) 35 | 36 | // 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function 37 | assert.fieldEquals( 38 | "ExampleEntity", 39 | "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", 40 | "by", 41 | "0x0000000000000000000000000000000000000001" 42 | ) 43 | 44 | // More assert options: 45 | // https://thegraph.com/docs/en/developer/matchstick/#asserts 46 | }) 47 | }) 48 | -------------------------------------------------------------------------------- /subgraph/registry-v2/tests/name-registry-utils.ts: -------------------------------------------------------------------------------- 1 | import { newMockEvent } from "matchstick-as" 2 | import { ethereum, Address, BigInt, Bytes } from "@graphprotocol/graph-ts" 3 | import { 4 | AdminChanged, 5 | Approval, 6 | ApprovalForAll, 7 | BeaconUpgraded, 8 | NameRegistryCancelRecovery, 9 | ChangeFee, 10 | ChangePool, 11 | NameRegistryChangeRecoveryAddress, 12 | NameRegistryChangeTrustedCaller, 13 | ChangeVault, 14 | NameRegistryDisableTrustedOnly, 15 | Initialized, 16 | Invite, 17 | Paused, 18 | Renew, 19 | NameRegistryRequestRecovery, 20 | RoleAdminChanged, 21 | RoleGranted, 22 | RoleRevoked, 23 | NameRegistryTransfer, 24 | Unpaused, 25 | Upgraded 26 | } from "../generated/NameRegistry/NameRegistry" 27 | 28 | export function createAdminChangedEvent( 29 | previousAdmin: Address, 30 | newAdmin: Address 31 | ): AdminChanged { 32 | let adminChangedEvent = changetype(newMockEvent()) 33 | 34 | adminChangedEvent.parameters = new Array() 35 | 36 | adminChangedEvent.parameters.push( 37 | new ethereum.EventParam( 38 | "previousAdmin", 39 | ethereum.Value.fromAddress(previousAdmin) 40 | ) 41 | ) 42 | adminChangedEvent.parameters.push( 43 | new ethereum.EventParam("newAdmin", ethereum.Value.fromAddress(newAdmin)) 44 | ) 45 | 46 | return adminChangedEvent 47 | } 48 | 49 | export function createApprovalEvent( 50 | owner: Address, 51 | approved: Address, 52 | tokenId: BigInt 53 | ): Approval { 54 | let approvalEvent = changetype(newMockEvent()) 55 | 56 | approvalEvent.parameters = new Array() 57 | 58 | approvalEvent.parameters.push( 59 | new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner)) 60 | ) 61 | approvalEvent.parameters.push( 62 | new ethereum.EventParam("approved", ethereum.Value.fromAddress(approved)) 63 | ) 64 | approvalEvent.parameters.push( 65 | new ethereum.EventParam( 66 | "tokenId", 67 | ethereum.Value.fromUnsignedBigInt(tokenId) 68 | ) 69 | ) 70 | 71 | return approvalEvent 72 | } 73 | 74 | export function createApprovalForAllEvent( 75 | owner: Address, 76 | operator: Address, 77 | approved: boolean 78 | ): ApprovalForAll { 79 | let approvalForAllEvent = changetype(newMockEvent()) 80 | 81 | approvalForAllEvent.parameters = new Array() 82 | 83 | approvalForAllEvent.parameters.push( 84 | new ethereum.EventParam("owner", ethereum.Value.fromAddress(owner)) 85 | ) 86 | approvalForAllEvent.parameters.push( 87 | new ethereum.EventParam("operator", ethereum.Value.fromAddress(operator)) 88 | ) 89 | approvalForAllEvent.parameters.push( 90 | new ethereum.EventParam("approved", ethereum.Value.fromBoolean(approved)) 91 | ) 92 | 93 | return approvalForAllEvent 94 | } 95 | 96 | export function createBeaconUpgradedEvent(beacon: Address): BeaconUpgraded { 97 | let beaconUpgradedEvent = changetype(newMockEvent()) 98 | 99 | beaconUpgradedEvent.parameters = new Array() 100 | 101 | beaconUpgradedEvent.parameters.push( 102 | new ethereum.EventParam("beacon", ethereum.Value.fromAddress(beacon)) 103 | ) 104 | 105 | return beaconUpgradedEvent 106 | } 107 | 108 | export function createNameRegistryCancelRecoveryEvent( 109 | by: Address, 110 | tokenId: BigInt 111 | ): NameRegistryCancelRecovery { 112 | let nameRegistryCancelRecoveryEvent = changetype( 113 | newMockEvent() 114 | ) 115 | 116 | nameRegistryCancelRecoveryEvent.parameters = new Array() 117 | 118 | nameRegistryCancelRecoveryEvent.parameters.push( 119 | new ethereum.EventParam("by", ethereum.Value.fromAddress(by)) 120 | ) 121 | nameRegistryCancelRecoveryEvent.parameters.push( 122 | new ethereum.EventParam( 123 | "tokenId", 124 | ethereum.Value.fromUnsignedBigInt(tokenId) 125 | ) 126 | ) 127 | 128 | return nameRegistryCancelRecoveryEvent 129 | } 130 | 131 | export function createChangeFeeEvent(fee: BigInt): ChangeFee { 132 | let changeFeeEvent = changetype(newMockEvent()) 133 | 134 | changeFeeEvent.parameters = new Array() 135 | 136 | changeFeeEvent.parameters.push( 137 | new ethereum.EventParam("fee", ethereum.Value.fromUnsignedBigInt(fee)) 138 | ) 139 | 140 | return changeFeeEvent 141 | } 142 | 143 | export function createChangePoolEvent(pool: Address): ChangePool { 144 | let changePoolEvent = changetype(newMockEvent()) 145 | 146 | changePoolEvent.parameters = new Array() 147 | 148 | changePoolEvent.parameters.push( 149 | new ethereum.EventParam("pool", ethereum.Value.fromAddress(pool)) 150 | ) 151 | 152 | return changePoolEvent 153 | } 154 | 155 | export function createNameRegistryChangeRecoveryAddressEvent( 156 | tokenId: BigInt, 157 | recovery: Address 158 | ): NameRegistryChangeRecoveryAddress { 159 | let nameRegistryChangeRecoveryAddressEvent = changetype< 160 | NameRegistryChangeRecoveryAddress 161 | >(newMockEvent()) 162 | 163 | nameRegistryChangeRecoveryAddressEvent.parameters = new Array() 164 | 165 | nameRegistryChangeRecoveryAddressEvent.parameters.push( 166 | new ethereum.EventParam( 167 | "tokenId", 168 | ethereum.Value.fromUnsignedBigInt(tokenId) 169 | ) 170 | ) 171 | nameRegistryChangeRecoveryAddressEvent.parameters.push( 172 | new ethereum.EventParam("recovery", ethereum.Value.fromAddress(recovery)) 173 | ) 174 | 175 | return nameRegistryChangeRecoveryAddressEvent 176 | } 177 | 178 | export function createNameRegistryChangeTrustedCallerEvent( 179 | trustedCaller: Address 180 | ): NameRegistryChangeTrustedCaller { 181 | let nameRegistryChangeTrustedCallerEvent = changetype< 182 | NameRegistryChangeTrustedCaller 183 | >(newMockEvent()) 184 | 185 | nameRegistryChangeTrustedCallerEvent.parameters = new Array() 186 | 187 | nameRegistryChangeTrustedCallerEvent.parameters.push( 188 | new ethereum.EventParam( 189 | "trustedCaller", 190 | ethereum.Value.fromAddress(trustedCaller) 191 | ) 192 | ) 193 | 194 | return nameRegistryChangeTrustedCallerEvent 195 | } 196 | 197 | export function createChangeVaultEvent(vault: Address): ChangeVault { 198 | let changeVaultEvent = changetype(newMockEvent()) 199 | 200 | changeVaultEvent.parameters = new Array() 201 | 202 | changeVaultEvent.parameters.push( 203 | new ethereum.EventParam("vault", ethereum.Value.fromAddress(vault)) 204 | ) 205 | 206 | return changeVaultEvent 207 | } 208 | 209 | export function createNameRegistryDisableTrustedOnlyEvent(): NameRegistryDisableTrustedOnly { 210 | let nameRegistryDisableTrustedOnlyEvent = changetype< 211 | NameRegistryDisableTrustedOnly 212 | >(newMockEvent()) 213 | 214 | nameRegistryDisableTrustedOnlyEvent.parameters = new Array() 215 | 216 | return nameRegistryDisableTrustedOnlyEvent 217 | } 218 | 219 | export function createInitializedEvent(version: i32): Initialized { 220 | let initializedEvent = changetype(newMockEvent()) 221 | 222 | initializedEvent.parameters = new Array() 223 | 224 | initializedEvent.parameters.push( 225 | new ethereum.EventParam( 226 | "version", 227 | ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(version)) 228 | ) 229 | ) 230 | 231 | return initializedEvent 232 | } 233 | 234 | export function createInviteEvent( 235 | inviterId: BigInt, 236 | inviteeId: BigInt, 237 | fname: Bytes 238 | ): Invite { 239 | let inviteEvent = changetype(newMockEvent()) 240 | 241 | inviteEvent.parameters = new Array() 242 | 243 | inviteEvent.parameters.push( 244 | new ethereum.EventParam( 245 | "inviterId", 246 | ethereum.Value.fromUnsignedBigInt(inviterId) 247 | ) 248 | ) 249 | inviteEvent.parameters.push( 250 | new ethereum.EventParam( 251 | "inviteeId", 252 | ethereum.Value.fromUnsignedBigInt(inviteeId) 253 | ) 254 | ) 255 | inviteEvent.parameters.push( 256 | new ethereum.EventParam("fname", ethereum.Value.fromFixedBytes(fname)) 257 | ) 258 | 259 | return inviteEvent 260 | } 261 | 262 | export function createPausedEvent(account: Address): Paused { 263 | let pausedEvent = changetype(newMockEvent()) 264 | 265 | pausedEvent.parameters = new Array() 266 | 267 | pausedEvent.parameters.push( 268 | new ethereum.EventParam("account", ethereum.Value.fromAddress(account)) 269 | ) 270 | 271 | return pausedEvent 272 | } 273 | 274 | export function createRenewEvent(tokenId: BigInt, expiry: BigInt): Renew { 275 | let renewEvent = changetype(newMockEvent()) 276 | 277 | renewEvent.parameters = new Array() 278 | 279 | renewEvent.parameters.push( 280 | new ethereum.EventParam( 281 | "tokenId", 282 | ethereum.Value.fromUnsignedBigInt(tokenId) 283 | ) 284 | ) 285 | renewEvent.parameters.push( 286 | new ethereum.EventParam("expiry", ethereum.Value.fromUnsignedBigInt(expiry)) 287 | ) 288 | 289 | return renewEvent 290 | } 291 | 292 | export function createNameRegistryRequestRecoveryEvent( 293 | from: Address, 294 | to: Address, 295 | tokenId: BigInt 296 | ): NameRegistryRequestRecovery { 297 | let nameRegistryRequestRecoveryEvent = changetype< 298 | NameRegistryRequestRecovery 299 | >(newMockEvent()) 300 | 301 | nameRegistryRequestRecoveryEvent.parameters = new Array() 302 | 303 | nameRegistryRequestRecoveryEvent.parameters.push( 304 | new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) 305 | ) 306 | nameRegistryRequestRecoveryEvent.parameters.push( 307 | new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) 308 | ) 309 | nameRegistryRequestRecoveryEvent.parameters.push( 310 | new ethereum.EventParam( 311 | "tokenId", 312 | ethereum.Value.fromUnsignedBigInt(tokenId) 313 | ) 314 | ) 315 | 316 | return nameRegistryRequestRecoveryEvent 317 | } 318 | 319 | export function createRoleAdminChangedEvent( 320 | role: Bytes, 321 | previousAdminRole: Bytes, 322 | newAdminRole: Bytes 323 | ): RoleAdminChanged { 324 | let roleAdminChangedEvent = changetype(newMockEvent()) 325 | 326 | roleAdminChangedEvent.parameters = new Array() 327 | 328 | roleAdminChangedEvent.parameters.push( 329 | new ethereum.EventParam("role", ethereum.Value.fromFixedBytes(role)) 330 | ) 331 | roleAdminChangedEvent.parameters.push( 332 | new ethereum.EventParam( 333 | "previousAdminRole", 334 | ethereum.Value.fromFixedBytes(previousAdminRole) 335 | ) 336 | ) 337 | roleAdminChangedEvent.parameters.push( 338 | new ethereum.EventParam( 339 | "newAdminRole", 340 | ethereum.Value.fromFixedBytes(newAdminRole) 341 | ) 342 | ) 343 | 344 | return roleAdminChangedEvent 345 | } 346 | 347 | export function createRoleGrantedEvent( 348 | role: Bytes, 349 | account: Address, 350 | sender: Address 351 | ): RoleGranted { 352 | let roleGrantedEvent = changetype(newMockEvent()) 353 | 354 | roleGrantedEvent.parameters = new Array() 355 | 356 | roleGrantedEvent.parameters.push( 357 | new ethereum.EventParam("role", ethereum.Value.fromFixedBytes(role)) 358 | ) 359 | roleGrantedEvent.parameters.push( 360 | new ethereum.EventParam("account", ethereum.Value.fromAddress(account)) 361 | ) 362 | roleGrantedEvent.parameters.push( 363 | new ethereum.EventParam("sender", ethereum.Value.fromAddress(sender)) 364 | ) 365 | 366 | return roleGrantedEvent 367 | } 368 | 369 | export function createRoleRevokedEvent( 370 | role: Bytes, 371 | account: Address, 372 | sender: Address 373 | ): RoleRevoked { 374 | let roleRevokedEvent = changetype(newMockEvent()) 375 | 376 | roleRevokedEvent.parameters = new Array() 377 | 378 | roleRevokedEvent.parameters.push( 379 | new ethereum.EventParam("role", ethereum.Value.fromFixedBytes(role)) 380 | ) 381 | roleRevokedEvent.parameters.push( 382 | new ethereum.EventParam("account", ethereum.Value.fromAddress(account)) 383 | ) 384 | roleRevokedEvent.parameters.push( 385 | new ethereum.EventParam("sender", ethereum.Value.fromAddress(sender)) 386 | ) 387 | 388 | return roleRevokedEvent 389 | } 390 | 391 | export function createNameRegistryTransferEvent( 392 | from: Address, 393 | to: Address, 394 | tokenId: BigInt 395 | ): NameRegistryTransfer { 396 | let nameRegistryTransferEvent = changetype( 397 | newMockEvent() 398 | ) 399 | 400 | nameRegistryTransferEvent.parameters = new Array() 401 | 402 | nameRegistryTransferEvent.parameters.push( 403 | new ethereum.EventParam("from", ethereum.Value.fromAddress(from)) 404 | ) 405 | nameRegistryTransferEvent.parameters.push( 406 | new ethereum.EventParam("to", ethereum.Value.fromAddress(to)) 407 | ) 408 | nameRegistryTransferEvent.parameters.push( 409 | new ethereum.EventParam( 410 | "tokenId", 411 | ethereum.Value.fromUnsignedBigInt(tokenId) 412 | ) 413 | ) 414 | 415 | return nameRegistryTransferEvent 416 | } 417 | 418 | export function createUnpausedEvent(account: Address): Unpaused { 419 | let unpausedEvent = changetype(newMockEvent()) 420 | 421 | unpausedEvent.parameters = new Array() 422 | 423 | unpausedEvent.parameters.push( 424 | new ethereum.EventParam("account", ethereum.Value.fromAddress(account)) 425 | ) 426 | 427 | return unpausedEvent 428 | } 429 | 430 | export function createUpgradedEvent(implementation: Address): Upgraded { 431 | let upgradedEvent = changetype(newMockEvent()) 432 | 433 | upgradedEvent.parameters = new Array() 434 | 435 | upgradedEvent.parameters.push( 436 | new ethereum.EventParam( 437 | "implementation", 438 | ethereum.Value.fromAddress(implementation) 439 | ) 440 | ) 441 | 442 | return upgradedEvent 443 | } 444 | -------------------------------------------------------------------------------- /subgraph/registry-v2/tests/name-registry.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | assert, 3 | describe, 4 | test, 5 | clearStore, 6 | beforeAll, 7 | afterAll 8 | } from "matchstick-as/assembly/index" 9 | import { Address, BigInt, Bytes } from "@graphprotocol/graph-ts" 10 | import { AdminChanged } from "../generated/schema" 11 | import { AdminChanged as AdminChangedEvent } from "../generated/NameRegistry/NameRegistry" 12 | import { handleAdminChanged } from "../src/name-registry" 13 | import { createAdminChangedEvent } from "./name-registry-utils" 14 | 15 | // Tests structure (matchstick-as >=0.5.0) 16 | // https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 17 | 18 | describe("Describe entity assertions", () => { 19 | beforeAll(() => { 20 | let previousAdmin = Address.fromString( 21 | "0x0000000000000000000000000000000000000001" 22 | ) 23 | let newAdmin = Address.fromString( 24 | "0x0000000000000000000000000000000000000001" 25 | ) 26 | let newAdminChangedEvent = createAdminChangedEvent(previousAdmin, newAdmin) 27 | handleAdminChanged(newAdminChangedEvent) 28 | }) 29 | 30 | afterAll(() => { 31 | clearStore() 32 | }) 33 | 34 | // For more test scenarios, see: 35 | // https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test 36 | 37 | test("AdminChanged created and stored", () => { 38 | assert.entityCount("AdminChanged", 1) 39 | 40 | // 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function 41 | assert.fieldEquals( 42 | "AdminChanged", 43 | "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1", 44 | "previousAdmin", 45 | "0x0000000000000000000000000000000000000001" 46 | ) 47 | assert.fieldEquals( 48 | "AdminChanged", 49 | "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1", 50 | "newAdmin", 51 | "0x0000000000000000000000000000000000000001" 52 | ) 53 | 54 | // More assert options: 55 | // https://thegraph.com/docs/en/developer/matchstick/#asserts 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /subgraph/registry-v2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", 3 | "include": ["src"] 4 | } 5 | --------------------------------------------------------------------------------