From 06315ec84c5b9d8c82c462674ffc2ddbc7f4a66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Rouleau?= Date: Mon, 16 Dec 2024 11:54:49 -0500 Subject: [PATCH] Update locales (remove those not in Crowdin) (#840) --- packages/nextra-theme/package.json | 6 +- packages/og-image/package.json | 4 +- pnpm-lock.yaml | 1976 +++++++++-------- website/i18n.ts | 6 - website/package.json | 6 +- website/pages/ha/_meta.js | 5 - website/pages/ha/about.mdx | 47 - website/pages/ha/arbitrum/_meta.js | 5 - website/pages/ha/arbitrum/arbitrum-faq.mdx | 78 - .../ha/arbitrum/l2-transfer-tools-faq.mdx | 411 ---- .../ha/arbitrum/l2-transfer-tools-guide.mdx | 165 -- website/pages/ha/billing.mdx | 208 -- .../pages/ha/chain-integration-overview.mdx | 49 - website/pages/ha/cookbook/_meta.js | 5 - website/pages/ha/cookbook/arweave.mdx | 239 -- website/pages/ha/cookbook/avoid-eth-calls.mdx | 116 - website/pages/ha/cookbook/cosmos.mdx | 259 --- website/pages/ha/cookbook/derivedfrom.mdx | 87 - website/pages/ha/cookbook/enums.mdx | 274 --- website/pages/ha/cookbook/grafting-hotfix.mdx | 186 -- website/pages/ha/cookbook/grafting.mdx | 202 -- ...pi-keys-using-nextjs-server-components.mdx | 123 - .../immutable-entities-bytes-as-ids.mdx | 190 -- website/pages/ha/cookbook/near.mdx | 284 --- website/pages/ha/cookbook/pruning.mdx | 55 - .../ha/cookbook/subgraph-debug-forking.mdx | 102 - .../ha/cookbook/subgraph-uncrashable.mdx | 29 - .../cookbook/substreams-powered-subgraphs.mdx | 227 -- website/pages/ha/cookbook/timeseries.mdx | 194 -- .../ha/cookbook/transfer-to-the-graph.mdx | 104 - website/pages/ha/deploying/_meta.js | 5 - .../deploy-using-subgraph-studio.mdx | 139 -- .../pages/ha/deploying/multiple-networks.mdx | 241 -- .../ha/deploying/subgraph-studio-faqs.mdx | 31 - website/pages/ha/developing/_meta.js | 5 - .../developing/creating-a-subgraph/_meta.js | 5 - .../creating-a-subgraph/advanced.mdx | 555 ----- .../assemblyscript-mappings.mdx | 113 - .../creating-a-subgraph/install-the-cli.mdx | 119 - .../creating-a-subgraph/ql-schema.mdx | 312 --- .../starting-your-subgraph.mdx | 21 - .../creating-a-subgraph/subgraph-manifest.mdx | 534 ----- .../pages/ha/developing/developer-faqs.mdx | 138 -- website/pages/ha/developing/graph-ts/_meta.js | 5 - website/pages/ha/developing/graph-ts/api.mdx | 854 ------- .../ha/developing/graph-ts/common-issues.mdx | 8 - .../substreams-powered-subgraphs-faq.mdx | 91 - .../ha/developing/supported-networks.json | 8 - .../ha/developing/supported-networks.mdx | 29 - .../ha/developing/unit-testing-framework.mdx | 1099 --------- website/pages/ha/docsearch.json | 42 - website/pages/ha/firehose.mdx | 22 - website/pages/ha/global.json | 14 - website/pages/ha/glossary.mdx | 85 - website/pages/ha/graphcast.mdx | 21 - website/pages/ha/index.json | 72 - website/pages/ha/managing/_meta.js | 5 - .../pages/ha/managing/delete-a-subgraph.mdx | 29 - .../pages/ha/managing/transfer-a-subgraph.mdx | 65 - website/pages/ha/network/_meta.js | 5 - website/pages/ha/network/benefits.mdx | 96 - website/pages/ha/network/contracts.mdx | 29 - website/pages/ha/network/curating.mdx | 96 - website/pages/ha/network/delegating.mdx | 98 - website/pages/ha/network/developing.mdx | 53 - website/pages/ha/network/explorer.mdx | 203 -- website/pages/ha/network/indexing.mdx | 801 ------- website/pages/ha/network/overview.mdx | 15 - website/pages/ha/new-chain-integration.mdx | 75 - website/pages/ha/operating-graph-node.mdx | 345 --- website/pages/ha/publishing/_meta.js | 5 - .../ha/publishing/publishing-a-subgraph.mdx | 33 - website/pages/ha/querying/_meta.js | 5 - .../pages/ha/querying/distributed-systems.mdx | 134 -- .../pages/ha/querying/graph-client/_meta.js | 5 - website/pages/ha/querying/graphql-api.mdx | 419 ---- .../pages/ha/querying/managing-api-keys.mdx | 26 - .../ha/querying/querying-best-practices.mdx | 463 ---- ...erying-by-subgraph-id-vs-deployment-id.mdx | 27 - .../querying/querying-from-an-application.mdx | 267 --- .../pages/ha/querying/querying-the-graph.mdx | 32 - .../ha/querying/querying-with-python.mdx | 56 - website/pages/ha/quick-start.mdx | 168 -- website/pages/ha/release-notes/_meta.js | 5 - .../assemblyscript-migration-guide.mdx | 524 ----- .../graphql-validations-migration-guide.mdx | 540 ----- website/pages/ha/sps/_meta.js | 5 - website/pages/ha/sps/introduction.mdx | 19 - website/pages/ha/sps/triggers-example.mdx | 137 -- website/pages/ha/sps/triggers.mdx | 37 - website/pages/ha/subgraphs.mdx | 41 - website/pages/ha/substreams.mdx | 44 - website/pages/ha/sunrise.mdx | 113 - .../ha/supported-network-requirements.mdx | 17 - website/pages/ha/tap.mdx | 193 -- website/pages/ha/tokenomics.mdx | 110 - website/pages/ha/translations.ts | 13 - website/pages/yo/_meta.js | 5 - website/pages/yo/about.mdx | 47 - website/pages/yo/arbitrum/_meta.js | 5 - website/pages/yo/arbitrum/arbitrum-faq.mdx | 86 - .../yo/arbitrum/l2-transfer-tools-faq.mdx | 411 ---- .../yo/arbitrum/l2-transfer-tools-guide.mdx | 165 -- website/pages/yo/billing.mdx | 213 -- .../pages/yo/chain-integration-overview.mdx | 49 - website/pages/yo/cookbook/_meta.js | 5 - website/pages/yo/cookbook/arweave.mdx | 239 -- website/pages/yo/cookbook/avoid-eth-calls.mdx | 102 - website/pages/yo/cookbook/cosmos.mdx | 257 --- website/pages/yo/cookbook/derivedfrom.mdx | 74 - website/pages/yo/cookbook/enums.mdx | 274 --- website/pages/yo/cookbook/grafting-hotfix.mdx | 186 -- website/pages/yo/cookbook/grafting.mdx | 202 -- ...pi-keys-using-nextjs-server-components.mdx | 123 - .../immutable-entities-bytes-as-ids.mdx | 176 -- website/pages/yo/cookbook/near.mdx | 283 --- website/pages/yo/cookbook/pruning.mdx | 41 - .../yo/cookbook/subgraph-debug-forking.mdx | 101 - .../yo/cookbook/subgraph-uncrashable.mdx | 29 - .../cookbook/substreams-powered-subgraphs.mdx | 226 -- website/pages/yo/cookbook/timeseries.mdx | 194 -- .../yo/cookbook/transfer-to-the-graph.mdx | 104 - website/pages/yo/deploying/_meta.js | 5 - .../deploy-using-subgraph-studio.mdx | 139 -- .../pages/yo/deploying/multiple-networks.mdx | 241 -- .../yo/deploying/subgraph-studio-faqs.mdx | 31 - website/pages/yo/developing/_meta.js | 5 - .../developing/creating-a-subgraph/_meta.js | 5 - .../creating-a-subgraph/advanced.mdx | 555 ----- .../assemblyscript-mappings.mdx | 113 - .../creating-a-subgraph/install-the-cli.mdx | 119 - .../creating-a-subgraph/ql-schema.mdx | 312 --- .../starting-your-subgraph.mdx | 21 - .../creating-a-subgraph/subgraph-manifest.mdx | 534 ----- .../pages/yo/developing/developer-faqs.mdx | 145 -- website/pages/yo/developing/graph-ts/_meta.js | 5 - website/pages/yo/developing/graph-ts/api.mdx | 881 -------- .../yo/developing/graph-ts/common-issues.mdx | 8 - .../substreams-powered-subgraphs-faq.mdx | 93 - .../yo/developing/supported-networks.json | 9 - .../yo/developing/supported-networks.mdx | 24 - .../yo/developing/unit-testing-framework.mdx | 1389 ------------ website/pages/yo/docsearch.json | 42 - website/pages/yo/firehose.mdx | 24 - website/pages/yo/global.json | 14 - website/pages/yo/glossary.mdx | 87 - website/pages/yo/graphcast.mdx | 21 - website/pages/yo/index.json | 71 - website/pages/yo/managing/_meta.js | 5 - .../pages/yo/managing/delete-a-subgraph.mdx | 29 - .../pages/yo/managing/transfer-a-subgraph.mdx | 65 - website/pages/yo/network/_meta.js | 5 - website/pages/yo/network/benefits.mdx | 92 - website/pages/yo/network/contracts.mdx | 29 - website/pages/yo/network/curating.mdx | 127 -- website/pages/yo/network/delegating.mdx | 104 - website/pages/yo/network/developing.mdx | 53 - website/pages/yo/network/explorer.mdx | 203 -- website/pages/yo/network/indexing.mdx | 819 ------- website/pages/yo/network/overview.mdx | 15 - website/pages/yo/new-chain-integration.mdx | 75 - website/pages/yo/operating-graph-node.mdx | 345 --- website/pages/yo/publishing/_meta.js | 5 - .../yo/publishing/publishing-a-subgraph.mdx | 94 - website/pages/yo/querying/_meta.js | 5 - .../pages/yo/querying/distributed-systems.mdx | 134 -- .../pages/yo/querying/graph-client/_meta.js | 5 - website/pages/yo/querying/graphql-api.mdx | 419 ---- .../pages/yo/querying/managing-api-keys.mdx | 24 - .../yo/querying/querying-best-practices.mdx | 493 ---- ...erying-by-subgraph-id-vs-deployment-id.mdx | 27 - .../querying/querying-from-an-application.mdx | 267 --- .../pages/yo/querying/querying-the-graph.mdx | 19 - .../yo/querying/querying-with-python.mdx | 56 - website/pages/yo/quick-start.mdx | 167 -- website/pages/yo/release-notes/_meta.js | 5 - .../assemblyscript-migration-guide.mdx | 524 ----- .../graphql-validations-migration-guide.mdx | 538 ----- website/pages/yo/sps/_meta.js | 5 - website/pages/yo/sps/introduction.mdx | 19 - website/pages/yo/sps/triggers-example.mdx | 137 -- website/pages/yo/sps/triggers.mdx | 37 - website/pages/yo/subgraphs.mdx | 41 - website/pages/yo/substreams.mdx | 46 - website/pages/yo/sunrise.mdx | 233 -- .../yo/supported-network-requirements.mdx | 18 - website/pages/yo/tap.mdx | 193 -- website/pages/yo/tokenomics.mdx | 110 - website/pages/yo/translations.ts | 13 - website/route-lockfile.txt | 146 -- website/src/_app.tsx | 1 - 191 files changed, 997 insertions(+), 28803 deletions(-) delete mode 100644 website/pages/ha/_meta.js delete mode 100644 website/pages/ha/about.mdx delete mode 100644 website/pages/ha/arbitrum/_meta.js delete mode 100644 website/pages/ha/arbitrum/arbitrum-faq.mdx delete mode 100644 website/pages/ha/arbitrum/l2-transfer-tools-faq.mdx delete mode 100644 website/pages/ha/arbitrum/l2-transfer-tools-guide.mdx delete mode 100644 website/pages/ha/billing.mdx delete mode 100644 website/pages/ha/chain-integration-overview.mdx delete mode 100644 website/pages/ha/cookbook/_meta.js delete mode 100644 website/pages/ha/cookbook/arweave.mdx delete mode 100644 website/pages/ha/cookbook/avoid-eth-calls.mdx delete mode 100644 website/pages/ha/cookbook/cosmos.mdx delete mode 100644 website/pages/ha/cookbook/derivedfrom.mdx delete mode 100644 website/pages/ha/cookbook/enums.mdx delete mode 100644 website/pages/ha/cookbook/grafting-hotfix.mdx delete mode 100644 website/pages/ha/cookbook/grafting.mdx delete mode 100644 website/pages/ha/cookbook/how-to-secure-api-keys-using-nextjs-server-components.mdx delete mode 100644 website/pages/ha/cookbook/immutable-entities-bytes-as-ids.mdx delete mode 100644 website/pages/ha/cookbook/near.mdx delete mode 100644 website/pages/ha/cookbook/pruning.mdx delete mode 100644 website/pages/ha/cookbook/subgraph-debug-forking.mdx delete mode 100644 website/pages/ha/cookbook/subgraph-uncrashable.mdx delete mode 100644 website/pages/ha/cookbook/substreams-powered-subgraphs.mdx delete mode 100644 website/pages/ha/cookbook/timeseries.mdx delete mode 100644 website/pages/ha/cookbook/transfer-to-the-graph.mdx delete mode 100644 website/pages/ha/deploying/_meta.js delete mode 100644 website/pages/ha/deploying/deploy-using-subgraph-studio.mdx delete mode 100644 website/pages/ha/deploying/multiple-networks.mdx delete mode 100644 website/pages/ha/deploying/subgraph-studio-faqs.mdx delete mode 100644 website/pages/ha/developing/_meta.js delete mode 100644 website/pages/ha/developing/creating-a-subgraph/_meta.js delete mode 100644 website/pages/ha/developing/creating-a-subgraph/advanced.mdx delete mode 100644 website/pages/ha/developing/creating-a-subgraph/assemblyscript-mappings.mdx delete mode 100644 website/pages/ha/developing/creating-a-subgraph/install-the-cli.mdx delete mode 100644 website/pages/ha/developing/creating-a-subgraph/ql-schema.mdx delete mode 100644 website/pages/ha/developing/creating-a-subgraph/starting-your-subgraph.mdx delete mode 100644 website/pages/ha/developing/creating-a-subgraph/subgraph-manifest.mdx delete mode 100644 website/pages/ha/developing/developer-faqs.mdx delete mode 100644 website/pages/ha/developing/graph-ts/_meta.js delete mode 100644 website/pages/ha/developing/graph-ts/api.mdx delete mode 100644 website/pages/ha/developing/graph-ts/common-issues.mdx delete mode 100644 website/pages/ha/developing/substreams-powered-subgraphs-faq.mdx delete mode 100644 website/pages/ha/developing/supported-networks.json delete mode 100644 website/pages/ha/developing/supported-networks.mdx delete mode 100644 website/pages/ha/developing/unit-testing-framework.mdx delete mode 100644 website/pages/ha/docsearch.json delete mode 100644 website/pages/ha/firehose.mdx delete mode 100644 website/pages/ha/global.json delete mode 100644 website/pages/ha/glossary.mdx delete mode 100644 website/pages/ha/graphcast.mdx delete mode 100644 website/pages/ha/index.json delete mode 100644 website/pages/ha/managing/_meta.js delete mode 100644 website/pages/ha/managing/delete-a-subgraph.mdx delete mode 100644 website/pages/ha/managing/transfer-a-subgraph.mdx delete mode 100644 website/pages/ha/network/_meta.js delete mode 100644 website/pages/ha/network/benefits.mdx delete mode 100644 website/pages/ha/network/contracts.mdx delete mode 100644 website/pages/ha/network/curating.mdx delete mode 100644 website/pages/ha/network/delegating.mdx delete mode 100644 website/pages/ha/network/developing.mdx delete mode 100644 website/pages/ha/network/explorer.mdx delete mode 100644 website/pages/ha/network/indexing.mdx delete mode 100644 website/pages/ha/network/overview.mdx delete mode 100644 website/pages/ha/new-chain-integration.mdx delete mode 100644 website/pages/ha/operating-graph-node.mdx delete mode 100644 website/pages/ha/publishing/_meta.js delete mode 100644 website/pages/ha/publishing/publishing-a-subgraph.mdx delete mode 100644 website/pages/ha/querying/_meta.js delete mode 100644 website/pages/ha/querying/distributed-systems.mdx delete mode 100644 website/pages/ha/querying/graph-client/_meta.js delete mode 100644 website/pages/ha/querying/graphql-api.mdx delete mode 100644 website/pages/ha/querying/managing-api-keys.mdx delete mode 100644 website/pages/ha/querying/querying-best-practices.mdx delete mode 100644 website/pages/ha/querying/querying-by-subgraph-id-vs-deployment-id.mdx delete mode 100644 website/pages/ha/querying/querying-from-an-application.mdx delete mode 100644 website/pages/ha/querying/querying-the-graph.mdx delete mode 100644 website/pages/ha/querying/querying-with-python.mdx delete mode 100644 website/pages/ha/quick-start.mdx delete mode 100644 website/pages/ha/release-notes/_meta.js delete mode 100644 website/pages/ha/release-notes/assemblyscript-migration-guide.mdx delete mode 100644 website/pages/ha/release-notes/graphql-validations-migration-guide.mdx delete mode 100644 website/pages/ha/sps/_meta.js delete mode 100644 website/pages/ha/sps/introduction.mdx delete mode 100644 website/pages/ha/sps/triggers-example.mdx delete mode 100644 website/pages/ha/sps/triggers.mdx delete mode 100644 website/pages/ha/subgraphs.mdx delete mode 100644 website/pages/ha/substreams.mdx delete mode 100644 website/pages/ha/sunrise.mdx delete mode 100644 website/pages/ha/supported-network-requirements.mdx delete mode 100644 website/pages/ha/tap.mdx delete mode 100644 website/pages/ha/tokenomics.mdx delete mode 100644 website/pages/ha/translations.ts delete mode 100644 website/pages/yo/_meta.js delete mode 100644 website/pages/yo/about.mdx delete mode 100644 website/pages/yo/arbitrum/_meta.js delete mode 100644 website/pages/yo/arbitrum/arbitrum-faq.mdx delete mode 100644 website/pages/yo/arbitrum/l2-transfer-tools-faq.mdx delete mode 100644 website/pages/yo/arbitrum/l2-transfer-tools-guide.mdx delete mode 100644 website/pages/yo/billing.mdx delete mode 100644 website/pages/yo/chain-integration-overview.mdx delete mode 100644 website/pages/yo/cookbook/_meta.js delete mode 100644 website/pages/yo/cookbook/arweave.mdx delete mode 100644 website/pages/yo/cookbook/avoid-eth-calls.mdx delete mode 100644 website/pages/yo/cookbook/cosmos.mdx delete mode 100644 website/pages/yo/cookbook/derivedfrom.mdx delete mode 100644 website/pages/yo/cookbook/enums.mdx delete mode 100644 website/pages/yo/cookbook/grafting-hotfix.mdx delete mode 100644 website/pages/yo/cookbook/grafting.mdx delete mode 100644 website/pages/yo/cookbook/how-to-secure-api-keys-using-nextjs-server-components.mdx delete mode 100644 website/pages/yo/cookbook/immutable-entities-bytes-as-ids.mdx delete mode 100644 website/pages/yo/cookbook/near.mdx delete mode 100644 website/pages/yo/cookbook/pruning.mdx delete mode 100644 website/pages/yo/cookbook/subgraph-debug-forking.mdx delete mode 100644 website/pages/yo/cookbook/subgraph-uncrashable.mdx delete mode 100644 website/pages/yo/cookbook/substreams-powered-subgraphs.mdx delete mode 100644 website/pages/yo/cookbook/timeseries.mdx delete mode 100644 website/pages/yo/cookbook/transfer-to-the-graph.mdx delete mode 100644 website/pages/yo/deploying/_meta.js delete mode 100644 website/pages/yo/deploying/deploy-using-subgraph-studio.mdx delete mode 100644 website/pages/yo/deploying/multiple-networks.mdx delete mode 100644 website/pages/yo/deploying/subgraph-studio-faqs.mdx delete mode 100644 website/pages/yo/developing/_meta.js delete mode 100644 website/pages/yo/developing/creating-a-subgraph/_meta.js delete mode 100644 website/pages/yo/developing/creating-a-subgraph/advanced.mdx delete mode 100644 website/pages/yo/developing/creating-a-subgraph/assemblyscript-mappings.mdx delete mode 100644 website/pages/yo/developing/creating-a-subgraph/install-the-cli.mdx delete mode 100644 website/pages/yo/developing/creating-a-subgraph/ql-schema.mdx delete mode 100644 website/pages/yo/developing/creating-a-subgraph/starting-your-subgraph.mdx delete mode 100644 website/pages/yo/developing/creating-a-subgraph/subgraph-manifest.mdx delete mode 100644 website/pages/yo/developing/developer-faqs.mdx delete mode 100644 website/pages/yo/developing/graph-ts/_meta.js delete mode 100644 website/pages/yo/developing/graph-ts/api.mdx delete mode 100644 website/pages/yo/developing/graph-ts/common-issues.mdx delete mode 100644 website/pages/yo/developing/substreams-powered-subgraphs-faq.mdx delete mode 100644 website/pages/yo/developing/supported-networks.json delete mode 100644 website/pages/yo/developing/supported-networks.mdx delete mode 100644 website/pages/yo/developing/unit-testing-framework.mdx delete mode 100644 website/pages/yo/docsearch.json delete mode 100644 website/pages/yo/firehose.mdx delete mode 100644 website/pages/yo/global.json delete mode 100644 website/pages/yo/glossary.mdx delete mode 100644 website/pages/yo/graphcast.mdx delete mode 100644 website/pages/yo/index.json delete mode 100644 website/pages/yo/managing/_meta.js delete mode 100644 website/pages/yo/managing/delete-a-subgraph.mdx delete mode 100644 website/pages/yo/managing/transfer-a-subgraph.mdx delete mode 100644 website/pages/yo/network/_meta.js delete mode 100644 website/pages/yo/network/benefits.mdx delete mode 100644 website/pages/yo/network/contracts.mdx delete mode 100644 website/pages/yo/network/curating.mdx delete mode 100644 website/pages/yo/network/delegating.mdx delete mode 100644 website/pages/yo/network/developing.mdx delete mode 100644 website/pages/yo/network/explorer.mdx delete mode 100644 website/pages/yo/network/indexing.mdx delete mode 100644 website/pages/yo/network/overview.mdx delete mode 100644 website/pages/yo/new-chain-integration.mdx delete mode 100644 website/pages/yo/operating-graph-node.mdx delete mode 100644 website/pages/yo/publishing/_meta.js delete mode 100644 website/pages/yo/publishing/publishing-a-subgraph.mdx delete mode 100644 website/pages/yo/querying/_meta.js delete mode 100644 website/pages/yo/querying/distributed-systems.mdx delete mode 100644 website/pages/yo/querying/graph-client/_meta.js delete mode 100644 website/pages/yo/querying/graphql-api.mdx delete mode 100644 website/pages/yo/querying/managing-api-keys.mdx delete mode 100644 website/pages/yo/querying/querying-best-practices.mdx delete mode 100644 website/pages/yo/querying/querying-by-subgraph-id-vs-deployment-id.mdx delete mode 100644 website/pages/yo/querying/querying-from-an-application.mdx delete mode 100644 website/pages/yo/querying/querying-the-graph.mdx delete mode 100644 website/pages/yo/querying/querying-with-python.mdx delete mode 100644 website/pages/yo/quick-start.mdx delete mode 100644 website/pages/yo/release-notes/_meta.js delete mode 100644 website/pages/yo/release-notes/assemblyscript-migration-guide.mdx delete mode 100644 website/pages/yo/release-notes/graphql-validations-migration-guide.mdx delete mode 100644 website/pages/yo/sps/_meta.js delete mode 100644 website/pages/yo/sps/introduction.mdx delete mode 100644 website/pages/yo/sps/triggers-example.mdx delete mode 100644 website/pages/yo/sps/triggers.mdx delete mode 100644 website/pages/yo/subgraphs.mdx delete mode 100644 website/pages/yo/substreams.mdx delete mode 100644 website/pages/yo/sunrise.mdx delete mode 100644 website/pages/yo/supported-network-requirements.mdx delete mode 100644 website/pages/yo/tap.mdx delete mode 100644 website/pages/yo/tokenomics.mdx delete mode 100644 website/pages/yo/translations.ts diff --git a/packages/nextra-theme/package.json b/packages/nextra-theme/package.json index c8ebe64383a8..bc410dd6d7c8 100644 --- a/packages/nextra-theme/package.json +++ b/packages/nextra-theme/package.json @@ -35,11 +35,11 @@ "theme-ui": "^0.16" }, "dependencies": { - "@docsearch/react": "^3.8.0", + "@docsearch/react": "^3.8.1", "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-visually-hidden": "^1.1.1", "lodash": "^4.17.21", - "react-intersection-observer": "^9.13.1", + "react-intersection-observer": "^9.14.0", "react-use": "^17.6.0" }, "devDependencies": { @@ -47,7 +47,7 @@ "@edgeandnode/go": "^6.74.0", "@emotion/react": "^11.14.0", "@types/lodash": "^4.17.13", - "@types/react": "^18.3.16", + "@types/react": "^18.3.17", "@types/react-dom": "^18.3.5", "next": "^14.2.20", "next-seo": "^6.6.0", diff --git a/packages/og-image/package.json b/packages/og-image/package.json index 345ba0ad437c..14f0aebacb98 100644 --- a/packages/og-image/package.json +++ b/packages/og-image/package.json @@ -16,8 +16,8 @@ "yoga-wasm-web": "0.3.3" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20241205.0", - "@types/react": "^18.3.16", + "@cloudflare/workers-types": "^4.20241216.0", + "@types/react": "^18.3.17", "jest-image-snapshot": "^6.4.0", "tsx": "^4.19.2", "typescript": "^5.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1376974eb47..1acd88a0cacf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,42 +48,42 @@ importers: packages/nextra-theme: dependencies: '@docsearch/react': - specifier: ^3.8.0 - version: 3.8.0(@algolia/client-search@5.17.1)(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) + specifier: ^3.8.1 + version: 3.8.1(@algolia/client-search@5.17.1)(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) '@radix-ui/react-collapsible': specifier: ^1.1.2 - version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-visually-hidden': specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash: specifier: ^4.17.21 version: 4.17.21 react-intersection-observer: - specifier: ^9.13.1 - version: 9.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^9.14.0 + version: 9.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-use: specifier: ^17.6.0 version: 17.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@edgeandnode/gds': specifier: ^5.39.1 - version: 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) + version: 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) '@edgeandnode/go': specifier: ^6.74.0 - version: 6.74.0(pvvz7w46g6d2da5mez3pi63ihq) + version: 6.74.0(k3a5ck5km3cbp2dg3adcgi6xwe) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.16)(react@18.3.1) + version: 11.14.0(@types/react@18.3.17)(react@18.3.1) '@types/lodash': specifier: ^4.17.13 version: 4.17.13 '@types/react': - specifier: ^18.3.16 - version: 18.3.16 + specifier: ^18.3.17 + version: 18.3.17 '@types/react-dom': specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.16) + version: 18.3.5(@types/react@18.3.17) next: specifier: ^14.2.20 version: 14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -101,7 +101,7 @@ importers: version: 18.3.1(react@18.3.1) theme-ui: specifier: ^0.17.1 - version: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + version: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) tsup: specifier: ^8.3.5 version: 8.3.5(jiti@1.21.6)(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.6.1) @@ -122,11 +122,11 @@ importers: version: 0.3.3 devDependencies: '@cloudflare/workers-types': - specifier: ^4.20241205.0 - version: 4.20241205.0 + specifier: ^4.20241216.0 + version: 4.20241216.0 '@types/react': - specifier: ^18.3.16 - version: 18.3.16 + specifier: ^18.3.17 + version: 18.3.17 jest-image-snapshot: specifier: ^6.4.0 version: 6.4.0 @@ -141,7 +141,7 @@ importers: version: 1.6.0(@types/node@22.10.2)(jsdom@24.1.3) wrangler: specifier: ^3.95.0 - version: 3.95.0(@cloudflare/workers-types@4.20241205.0) + version: 3.95.0(@cloudflare/workers-types@4.20241216.0) packages/remark-lint-restrict-elements: dependencies: @@ -159,13 +159,13 @@ importers: version: 6.38.0(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2)) '@edgeandnode/gds': specifier: ^5.39.1 - version: 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) + version: 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) '@edgeandnode/go': specifier: ^6.74.0 - version: 6.74.0(pvvz7w46g6d2da5mez3pi63ihq) + version: 6.74.0(k3a5ck5km3cbp2dg3adcgi6xwe) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.16)(react@18.3.1) + version: 11.14.0(@types/react@18.3.17)(react@18.3.1) '@graphprotocol/contracts': specifier: 6.2.1 version: 6.2.1(encoding@0.1.13)(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) @@ -201,14 +201,14 @@ importers: version: 2.1.0 theme-ui: specifier: ^0.17.1 - version: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + version: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) unist-util-visit: specifier: ^5.0.0 version: 5.0.0 devDependencies: '@graphprotocol/client-cli': specifier: 3.0.3 - version: 3.0.3(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/merge@9.0.13(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0) + version: 3.0.3(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/merge@9.0.14(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0) '@types/mdast': specifier: ^4.0.4 version: 4.0.4 @@ -216,20 +216,20 @@ importers: specifier: ^2.50.2 version: 2.50.2 '@types/react': - specifier: ^18.3.16 - version: 18.3.16 + specifier: ^18.3.17 + version: 18.3.17 '@types/react-dom': specifier: ^18.3.5 - version: 18.3.5(@types/react@18.3.16) + version: 18.3.5(@types/react@18.3.17) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.49) fast-xml-parser: - specifier: ^4.5.0 - version: 4.5.0 + specifier: ^4.5.1 + version: 4.5.1 graphql: - specifier: ^16.9.0 - version: 16.9.0 + specifier: ^16.10.0 + version: 16.10.0 postcss: specifier: ^8.4.49 version: 8.4.49 @@ -669,8 +669,8 @@ packages: resolution: {integrity: sha512-A+lQ8xp7992qSeMmuQ0ssL6CPmm+ZmAv6Ddikan0n1jjpMAic+97l7xtVIsswSn9iLMFPYQ9uNN/8Fl0AgARIQ==} engines: {node: '>=16.7.0'} - '@cloudflare/workers-types@4.20241205.0': - resolution: {integrity: sha512-pj1VKRHT/ScQbHOIMFODZaNAlJHQHdBSZXNIdr9ebJzwBff9Qz8VdqhbhggV7f+aUEh8WSbrsPIo4a+WtgjUvw==} + '@cloudflare/workers-types@4.20241216.0': + resolution: {integrity: sha512-PGIINXS+aE9vD2GYyWXfRG+VyxxceRkGDCoPxqwUweh1Bfv75HVotyL/adJ7mRVwh3XZDifGBdTaLReTT+Fcog==} '@corex/deepmerge@4.0.43': resolution: {integrity: sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==} @@ -679,11 +679,11 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@docsearch/css@3.8.0': - resolution: {integrity: sha512-pieeipSOW4sQ0+bE5UFC51AOZp9NGxg89wAlZ1BAQFaiRAGK1IKUaPQ0UGZeNctJXyqZ1UvBtOQh2HH+U5GtmA==} + '@docsearch/css@3.8.1': + resolution: {integrity: sha512-XiPhKT+ghUi4pEi/ACE9iDmwWsLA6d6xSwtR5ab48iB63OtYWFLZHUKdH7jHKTmwOs0Eg22TX4Kb3H5liFm5bQ==} - '@docsearch/react@3.8.0': - resolution: {integrity: sha512-WnFK720+iwTVt94CxY3u+FgX6exb3BfN5kE9xUY6uuAH/9W/UFboBZFLlrw/zxFRHoHZCOXRtOylsXF+6LHI+Q==} + '@docsearch/react@3.8.1': + resolution: {integrity: sha512-7vgQuktQNBQdNWO1jbkiwgIrTZ0r5nPIHqcO3Z2neAWgkdUuldvvMfEOEaPXT5lqcezEv7i0h+tC285nD3jpZg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -1803,8 +1803,8 @@ packages: graphql: '*' tslib: ^2.4.0 - '@graphql-mesh/store@0.103.8': - resolution: {integrity: sha512-uiE2E7Tu74WldpTMV8qH0FOor6CcjOG0rydQNSTAIIQ/QNsz0+yLw0AcybgNygNqqB3iFqjiIod1gOgTlKlhOQ==} + '@graphql-mesh/store@0.103.9': + resolution: {integrity: sha512-10xTcI3Dconu/6aQDwQSeSbYlFUWI7Sx4JdEU/BnjVRNGMF2+bRMaRPuKk7dvQm37SD9WDBvPGQRMlkzapTxOg==} engines: {node: '>=16.0.0'} peerDependencies: graphql: '*' @@ -1850,8 +1850,8 @@ packages: graphql: '*' tslib: ^2.4.0 - '@graphql-mesh/types@0.103.8': - resolution: {integrity: sha512-cdbAa2ZEYnMq+fgioHfXUEuR5yu+zh5aaFtAbHnld9CDZr+9uQ9Cot0loAUH1b1zVatptBLgzC//KqKiwr6hLA==} + '@graphql-mesh/types@0.103.9': + resolution: {integrity: sha512-7aWD88vgcueDnWfndR74lkHiOS5a6s6Ze4bPLDWxJ6z9ix4F1aHnPt7h5wNe0DbhU9cygNxLmlrdtvt2M3yNhA==} engines: {node: '>=16.0.0'} peerDependencies: graphql: '*' @@ -1875,8 +1875,8 @@ packages: graphql: '*' tslib: ^2.4.0 - '@graphql-mesh/utils@0.103.8': - resolution: {integrity: sha512-9Pfi0MikmQQdzQLt14Fu+KPwl91poEN0ue5A9MmbtznTgfqUg35IZY1DWtA/rZcmxFpxOe7zM3tJcCpSvpxJiA==} + '@graphql-mesh/utils@0.103.9': + resolution: {integrity: sha512-pdRC5V6WVEb4CnwqKTkgmD2dyX1SO495lS5kKfiZhJ9UbJo+v49f8ZXu2Idf/4BqVor8go611NeYSm6qvVnFPw==} engines: {node: '>=16.0.0'} peerDependencies: graphql: '*' @@ -1903,8 +1903,8 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/code-file-loader@8.1.9': - resolution: {integrity: sha512-i2Trxb84OvDRFdTb0dURmCFyeNwDpXVZYCLShtjTnGLij4Cjwb7Q4FOWLWgwdFaBvebfRTUVrpl1HX1PxAc7cQ==} + '@graphql-tools/code-file-loader@8.1.10': + resolution: {integrity: sha512-f/AVZCh4LWFDYOYNAscHiT1BvldaG1FTVn58jBNdWOx56IK1qdyLEayWDfBBxs1WRZ2+dpvsqoyay7ClGtlDKA==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -1927,14 +1927,14 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/executor-legacy-ws@1.1.6': - resolution: {integrity: sha512-kKP5iVAaaXTjdAHyJFGGtXOjBWKer+IDI4pF9nJuU1FM9bxvZQQtZ0aW8NO/sBZlJus+bbLHzVgywkP4Y8E01w==} + '@graphql-tools/executor-legacy-ws@1.1.7': + resolution: {integrity: sha512-F118QBHCbqybFwvyljcn4XKp7wWdVK5At9Aljfedn/U+OTKz3SFTCrzk2/oy9WK8yLHgdeh3aKKHY9lHtfrP7Q==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/executor@1.3.8': - resolution: {integrity: sha512-tiZ8/PaQ+wkdZeCSyHa7vOUqCJndnpnN5ilUpi5UwsFrFFyN71sr4NJeib7Txf1VdufJNB4ed/0yFd39O0L3AQ==} + '@graphql-tools/executor@1.3.9': + resolution: {integrity: sha512-BpBWW6WMgIQeLQIFHJ9HHPaCX9mzEn4sv2qP0mb4acW4z45HB4znRFf3vxq83jMOOhWjrvY0vE2UjMVYnsvvSQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -1945,32 +1945,32 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/graphql-file-loader@8.0.7': - resolution: {integrity: sha512-WZD4bMbI/WhRY4dUQNzTKAr15M2Ayr1bhxacejp4dhYzZq7WUGZw1CfPnphYhptkAUZWdaydhJmq7CnIYJO2sA==} + '@graphql-tools/graphql-file-loader@8.0.8': + resolution: {integrity: sha512-aGmUI/ds7uo0dvE3Re1gD6a++fKy1wX8vw2N/cz9w9uq8mq+LFt9UFj8F3YCAwaqlum0/UDDmDHY16QrT8beww==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/graphql-tag-pluck@8.3.8': - resolution: {integrity: sha512-qo6dhmOFsEoiUI9EDNVd2GbOCkshHLPpofdCpHZ3QfRvpwa1/tNlHqMjbZ7gGTQSGKqngi9LZoQp4D6nXvxEpg==} + '@graphql-tools/graphql-tag-pluck@8.3.9': + resolution: {integrity: sha512-DwyGblVRx8eTRbPkp1srNd5UuqCvzz5kDwYSCxlaIyCm2PhXjMglAC9BcYwXfyHz8ehURIl44wfMyTGJQ/s+fw==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/import@7.0.7': - resolution: {integrity: sha512-UAlN3zlKLYmzBZoUtL64TwzrxFzGJDBO3Ut6cz7eGa7V2m6b4rm9U/8ospz9TrXOtqX9TCawyTh93fPr2bEfvQ==} + '@graphql-tools/import@7.0.8': + resolution: {integrity: sha512-1/3gNFEaRdehwnlxHBgCPSw3kO4dSm7MQj9b/UOXAHGXjzSB+ezE4oudpensd2p41WnoeFFC0S5SZmjThNByWQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/load@8.0.8': - resolution: {integrity: sha512-5B96YiUs4i6UyzVHZJFSP4k8PCj0LS5P5KnZ2HIoSHyMpbzoWueTIlZ4sEorQwBjHkQj6TEoXIPfjivxwPNr7Q==} + '@graphql-tools/load@8.0.9': + resolution: {integrity: sha512-ty0Lhdc9uUCl8zLc3kfcWXLFEdK2ixJA1XPkiATxGh76K/C53vgatJ3RjpVk07f8yPyzL5IV2fvHc4c9XK3eMg==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/merge@9.0.13': - resolution: {integrity: sha512-OSEOaFOjdkAwR6umRHrTrKjYANbh/0OBb1W8B21dxu8XPaOeoCuShDGXY6ZpragiO8Ke0qFXZGwJGg8ZbDPfvQ==} + '@graphql-tools/merge@9.0.14': + resolution: {integrity: sha512-MO7VXnm3ShpdG51hs4hYsLyu+8o/tSLjNYQmLmR4rkHoFi3kQCDu2r8B4IVwd+Ve39cechj0NyCmMsg+mRvwDQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -1991,14 +1991,14 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/relay-operation-optimizer@7.0.7': - resolution: {integrity: sha512-8hWMbcRn7gjLFhp9GsCuYqtL8qIt/bwTnK1MynuQWz0NetvVVNCUckILy/5vk4qFoJIobtNJd7XW6Xvv4TN+Ug==} + '@graphql-tools/relay-operation-optimizer@7.0.8': + resolution: {integrity: sha512-9DBRiKg/r8EQ6XybfZMPJZSrj4c+UQ9ATm1KmJPsfFpcvRKTkydzPPaqwGEolsbDelHkAQV6YP85JYNfxQkTcQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/schema@10.0.12': - resolution: {integrity: sha512-ukIZBdD4jI94ren5GK6nnHe+YvDVOfoI8cz50pdE1+FYf9NSFUu7HJXmIBHGIIWFbE5lz4qb5MfUeuBkffs3lw==} + '@graphql-tools/schema@10.0.13': + resolution: {integrity: sha512-1gvTTuSKej9bR5O2SP9dCKSHaQkVmg9fWU0Aia34HMsAZl2bzosUfXjwBu3ze8MWqb+gRVjdhukDpGA5ZC+5nA==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -2021,14 +2021,14 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/url-loader@8.0.19': - resolution: {integrity: sha512-D1AhYr75ho/A+bvxSH3+SUpGRcpYmWFBZIEe0TahkHXUBX1uVUDpUnGP7zz525tBMG9/CJhZcXqlDANqmsCm7Q==} + '@graphql-tools/url-loader@8.0.20': + resolution: {integrity: sha512-4gC3lcHPHRI3WbYoMFVcZO1mk7haCPmgOqvqXqdirotjsM0/gxa/17IaorwDZjXq40EHzwzUgSx55CMeuEy+QQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/utils@10.6.3': - resolution: {integrity: sha512-hEaQTGyQUG3DJqCaIsiu4M+jUgWUf+h6kDwC8MtGElwkL1HWi+qX2qyynw8h9WoV7STmmHDSwkk2ET1IC3nRPw==} + '@graphql-tools/utils@10.6.4': + resolution: {integrity: sha512-itCgjwVxbO+3uI/K73G9heedG8KelNFzgn368rUhPjTrkJX6NyLQwT5EMq/A8tvazMXyJYdtnN5nD+tT4DUpbQ==} engines: {node: '>=16.0.0'} peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -2058,12 +2058,12 @@ packages: resolution: {integrity: sha512-Mg8psdkAp+YTG1OGmvU+xa6xpsAmSir0hhr3yFYPyLNwzUj95DdIwsMpKadDj9xDpYgJcH3Hp/4JMal9DhQimA==} engines: {node: '>=18.0.0'} - '@graphql-yoga/plugin-persisted-operations@3.10.5': - resolution: {integrity: sha512-a9pHMolJSYo3ONEkpKkgTI5eh64uwxc+fNXaUrntN72dTiiimRdF7LSatVTy5BRE0MeUpJe6mdnKH93GUjo0hw==} + '@graphql-yoga/plugin-persisted-operations@3.10.6': + resolution: {integrity: sha512-RGG5RhvK9cX+gtP4WY/aS5rh2cWIY4Fc6pg1i/nljPuOTxBqxPyeHFl19CA/Op19c+nCX0l6A+hI6JoCqLQo7w==} engines: {node: '>=18.0.0'} peerDependencies: graphql: ^15.2.0 || ^16.0.0 - graphql-yoga: ^5.10.5 + graphql-yoga: ^5.10.6 '@graphql-yoga/subscription@5.0.2': resolution: {integrity: sha512-KGacW1FtUXR5e3qk4YmEFQRGTov8lOkpW7syjTD3EN2t5HRWrSsut2LwjVdK+HcP3H9UEuZ9RXw/+shqV+1exQ==} @@ -3636,14 +3636,14 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@tanstack/react-virtual@3.11.1': - resolution: {integrity: sha512-orn2QNe5tF6SqjucHJ6cKTKcRDe3GG7bcYqPNn72Yejj7noECdzgAyRfGt2pGDPemhYim3d1HIR/dgruCnLfUA==} + '@tanstack/react-virtual@3.11.2': + resolution: {integrity: sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/virtual-core@3.10.9': - resolution: {integrity: sha512-kBknKOKzmeR7lN+vSadaKWXaLS0SZZG+oqpQ/k80Q6g9REn6zRHS/ZYdrIzHnpHgy/eWs00SujveUN/GJT2qTw==} + '@tanstack/virtual-core@3.11.2': + resolution: {integrity: sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==} '@theguild/remark-mermaid@0.0.5': resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} @@ -3875,8 +3875,8 @@ packages: peerDependencies: '@types/react': ^18.0.0 - '@types/react@18.3.16': - resolution: {integrity: sha512-oh8AMIC4Y2ciKufU8hnKgs+ufgbA/dhPTACaZPM86AbwX9QwnFtSoPWEeRUj8fge+v6kFt78BXcDhAU1SrrAsw==} + '@types/react@18.3.17': + resolution: {integrity: sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==} '@types/readable-stream@2.3.15': resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} @@ -4275,20 +4275,20 @@ packages: resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} engines: {node: '>= 0.4'} - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} array.prototype.tosorted@1.1.4: resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} as-table@1.0.55: @@ -4519,8 +4519,8 @@ packages: resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} engines: {node: '>= 0.4'} - call-bound@1.0.2: - resolution: {integrity: sha512-0lk0PHFe/uz0vl527fG9CgdE9WdafjDbCXvBbs+LUv000TVt2Jjhqbs4Jwm8gz070w8xXyEAxrPOMullsxXeGg==} + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} engines: {node: '>= 0.4'} callsites@3.1.0: @@ -4545,8 +4545,8 @@ packages: camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001688: - resolution: {integrity: sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==} + caniuse-lite@1.0.30001689: + resolution: {integrity: sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==} capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -5322,8 +5322,8 @@ packages: error-stack-parser@2.1.4: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} - es-abstract@1.23.5: - resolution: {integrity: sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==} + es-abstract@1.23.6: + resolution: {integrity: sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -5670,8 +5670,8 @@ packages: fast-uri@3.0.3: resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - fast-xml-parser@4.5.0: - resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + fast-xml-parser@4.5.1: + resolution: {integrity: sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==} hasBin: true fastest-stable-stringify@2.0.2: @@ -5796,8 +5796,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@11.14.4: - resolution: {integrity: sha512-NQuzr9JbeJDMQmy0FFLhLzk9h1kAjVC1tGE/HY4ubF02B95EBm2lpA21LE3Od/OpXqXgp0zl5Hdqu25hliBRsA==} + framer-motion@11.15.0: + resolution: {integrity: sha512-MLk8IvZntxOMg7lDBLw2qgTHHv664bYoYmnFTmE0Gm/FW67aOJk0WM3ctMcG+Xhcv+vh5uyyXwxvxhSeJzSe+w==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -5848,8 +5848,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + function.prototype.name@1.1.7: + resolution: {integrity: sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA==} engines: {node: '>= 0.4'} functional-red-black-tree@1.0.1: @@ -6006,18 +6006,18 @@ packages: peerDependencies: graphql: '>=0.11 <=16' - graphql-yoga@5.10.5: - resolution: {integrity: sha512-W5bpXHRb6S3H3Th8poDm6b+ZMRjke8hsy9WVFgRriDTGh0AenIkpJzZT5VgXUD+j1yLCMrvhUNc6MNmgaRExsw==} + graphql-yoga@5.10.6: + resolution: {integrity: sha512-RqKTNN4ii/pnUhGBuFF3WyNy52AMs5ArTY/lGQUYH/1FQk5t2RgAZE5OxWRgobhmr+cuN066bvgVIlt4mnnRNA==} engines: {node: '>=18.0.0'} peerDependencies: graphql: ^15.2.0 || ^16.0.0 - graphql@16.8.0: - resolution: {integrity: sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==} + graphql@16.10.0: + resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - graphql@16.9.0: - resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} + graphql@16.8.0: + resolution: {integrity: sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} gray-matter@4.0.3: @@ -6424,8 +6424,8 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-number-object@1.1.0: - resolution: {integrity: sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} is-number@7.0.0: @@ -6485,8 +6485,8 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-string@1.1.0: - resolution: {integrity: sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} is-symbol@1.1.1: @@ -6832,8 +6832,8 @@ packages: magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.30.15: - resolution: {integrity: sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} @@ -7315,8 +7315,8 @@ packages: motion-utils@11.14.3: resolution: {integrity: sha512-Xg+8xnqIJTpr0L/cidfTTBFkvRw26ZtGGuIhA94J9PQ2p4mEa06Xx7QVYZH0BP+EpMSaDlu+q0I0mmvwADPsaQ==} - motion@11.14.4: - resolution: {integrity: sha512-ZIaw6ko88B8rSmBEFzqbTCQMbo9xMu8f4PSXSGdb9DTDy8R0sXcbwMEKmTEYkrj9TmZ4n+Ebd0KYjtqHgzRkRQ==} + motion@11.15.0: + resolution: {integrity: sha512-iZ7dwADQJWGsqsSkBhNHdI2LyYWU+hA1Nhy357wCLZq1yHxGImgt3l7Yv0HT/WOskcYDq9nxdedyl4zUv7UFFw==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -8155,11 +8155,11 @@ packages: react-ga4@2.1.0: resolution: {integrity: sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==} - react-intersection-observer@9.13.1: - resolution: {integrity: sha512-tSzDaTy0qwNPLJHg8XZhlyHTgGW6drFKTtvjdL+p6um12rcnp8Z5XstE+QNBJ7c64n5o0Lj4ilUleA41bmDoMw==} + react-intersection-observer@9.14.0: + resolution: {integrity: sha512-AYqlmDZn85VUmlODwYym9y5OlqY2cFyIu41dkN0GJWvhdbd19Mh16mz5IH6fO1gp5V4FfQOO4m0zGc04Tj13rQ==} peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: react-dom: optional: true @@ -8175,12 +8175,12 @@ packages: peerDependencies: react: '>=15.0.0' - react-remove-scroll-bar@2.3.6: - resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true @@ -8201,12 +8201,12 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-style-singleton@2.2.1: - resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -9316,8 +9316,9 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} unc-path-regex@0.1.2: resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} @@ -9485,12 +9486,12 @@ packages: '@types/react': optional: true - use-sidecar@1.1.2: - resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -9676,8 +9677,8 @@ packages: whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which-boxed-primitive@1.1.0: - resolution: {integrity: sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} which-builtin-type@1.2.1: @@ -10025,7 +10026,7 @@ snapshots: - bufferutil - utf-8-validate - '@ardatan/relay-compiler@12.0.0(encoding@0.1.13)(graphql@16.9.0)': + '@ardatan/relay-compiler@12.0.0(encoding@0.1.13)(graphql@16.10.0)': dependencies: '@babel/core': 7.26.0 '@babel/generator': 7.26.3 @@ -10038,7 +10039,7 @@ snapshots: fb-watchman: 2.0.2 fbjs: 3.0.5(encoding@0.1.13) glob: 7.2.3 - graphql: 16.9.0 + graphql: 16.10.0 immutable: 3.7.6 invariant: 2.2.4 nullthrows: 1.1.1 @@ -10440,7 +10441,7 @@ snapshots: mime: 3.0.0 zod: 3.24.1 - '@cloudflare/workers-types@4.20241205.0': {} + '@cloudflare/workers-types@4.20241216.0': {} '@corex/deepmerge@4.0.43': {} @@ -10448,16 +10449,16 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@docsearch/css@3.8.0': {} + '@docsearch/css@3.8.1': {} - '@docsearch/react@3.8.0(@algolia/client-search@5.17.1)(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': + '@docsearch/react@3.8.1(@algolia/client-search@5.17.1)(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': dependencies: '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1)(search-insights@2.17.3) '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.17.1)(algoliasearch@5.17.1) - '@docsearch/css': 3.8.0 + '@docsearch/css': 3.8.1 algoliasearch: 5.17.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) search-insights: 2.17.3 @@ -10475,8 +10476,8 @@ snapshots: dayjs: 1.11.13 decimal.js: 10.4.3 ethers: 5.7.2 - graphql: 16.9.0 - graphql-tag: 2.12.6(graphql@16.9.0) + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) numeral: 2.0.6 pluralize: 8.0.0 transitivePeerDependencies: @@ -10507,34 +10508,34 @@ snapshots: - eslint-plugin-import-x - supports-color - '@edgeandnode/gds@5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2)': + '@edgeandnode/gds@5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2)': dependencies: '@edgeandnode/common': 6.38.0(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2)) - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) '@figma/code-connect': 1.2.4 '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@headlessui/react': 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@phosphor-icons/react': 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-accordion': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-alert-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dropdown-menu': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-label': 2.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popover': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slider': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-switch': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-toast': 1.2.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tooltip': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-accordion': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-alert-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dropdown-menu': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-label': 2.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-popover': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slider': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-switch': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toast': 1.2.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-tooltip': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.26.0(react@18.3.1) '@tailwindcss/container-queries': 0.1.1(tailwindcss@3.4.16(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))) '@tanem/react-nprogress': 5.0.53(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) - '@theme-ui/match-media': 0.17.1(@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)))(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) + '@theme-ui/match-media': 0.17.1(@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)))(react@18.3.1) '@web3icons/react': 3.13.2(react@18.3.1)(typescript@5.7.2) - '@xstate/react': 3.2.2(@types/react@18.3.16)(react@18.3.1)(xstate@4.38.3) + '@xstate/react': 3.2.2(@types/react@18.3.17)(react@18.3.1)(xstate@4.38.3) classnames: 2.5.1 color: 4.2.3 dayjs: 1.11.13 @@ -10542,7 +10543,7 @@ snapshots: ethers: 5.7.2 lodash: 4.17.21 md5: 2.3.0 - motion: 11.14.4(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + motion: 11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) numeral: 2.0.6 prism-react-renderer: 2.4.1(react@18.3.1) prismjs: 1.29.0 @@ -10558,7 +10559,7 @@ snapshots: recharts: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) shiki: 1.24.2 tailwindcss: 3.4.16(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2)) - theme-ui: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + theme-ui: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) typy: 3.3.0 universal-cookie: 7.2.2 xstate: 4.38.3 @@ -10577,23 +10578,23 @@ snapshots: - typescript - utf-8-validate - '@edgeandnode/go@6.74.0(pvvz7w46g6d2da5mez3pi63ihq)': + '@edgeandnode/go@6.74.0(k3a5ck5km3cbp2dg3adcgi6xwe)': dependencies: '@edgeandnode/common': 6.38.0(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2)) - '@edgeandnode/gds': 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-collapsible': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-navigation-menu': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + '@edgeandnode/gds': 5.39.1(@emotion/is-prop-valid@0.8.8)(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(dayjs@1.11.13)(hardhat@2.14.1(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2))(typescript@5.7.2) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-collapsible': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-navigation-menu': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) classnames: 2.5.1 escape-string-regexp: 5.0.0 - motion: 11.14.4(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + motion: 11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tailwindcss: 3.4.16(ts-node@10.9.2(@types/node@22.10.2)(typescript@5.7.2)) - theme-ui: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + theme-ui: 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) optionalDependencies: next: 14.2.20(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: @@ -10638,7 +10639,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)': + '@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)': dependencies: '@babel/runtime': 7.26.0 '@emotion/babel-plugin': 11.13.5 @@ -10650,7 +10651,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 transitivePeerDependencies: - supports-color @@ -10679,18 +10680,18 @@ snapshots: '@envelop/types': 5.0.0 tslib: 2.8.1 - '@envelop/extended-validation@4.1.0(@envelop/core@5.0.2)(graphql@16.9.0)': + '@envelop/extended-validation@4.1.0(@envelop/core@5.0.2)(graphql@16.10.0)': dependencies: '@envelop/core': 5.0.2 - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@envelop/graphql-jit@8.0.4(@envelop/core@5.0.2)(graphql@16.9.0)': + '@envelop/graphql-jit@8.0.4(@envelop/core@5.0.2)(graphql@16.10.0)': dependencies: '@envelop/core': 5.0.2 - graphql: 16.9.0 - graphql-jit: 0.8.7(graphql@16.9.0) + graphql: 16.10.0 + graphql-jit: 0.8.7(graphql@16.10.0) tslib: 2.8.1 value-or-promise: 1.0.12 @@ -11404,57 +11405,57 @@ snapshots: dependencies: tslib: 2.8.1 - '@graphprotocol/client-add-source-name@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(graphql@16.9.0)': + '@graphprotocol/client-add-source-name@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(graphql@16.10.0)': dependencies: - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) + graphql: 16.10.0 lodash: 4.17.21 tslib: 2.8.1 - '@graphprotocol/client-auto-pagination@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(graphql@16.9.0)': + '@graphprotocol/client-auto-pagination@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(graphql@16.10.0)': dependencies: - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) + graphql: 16.10.0 lodash: 4.17.21 tslib: 2.8.1 - '@graphprotocol/client-auto-type-merging@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(graphql@16.9.0)': + '@graphprotocol/client-auto-type-merging@2.0.7(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(graphql@16.10.0)': dependencies: - '@graphql-mesh/transform-type-merging': 0.102.13(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/transform-type-merging': 0.102.13(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - '@graphql-mesh/utils' - '@graphprotocol/client-block-tracking@2.0.6(@graphql-mesh/store@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@types/node@22.10.2)(graphql@16.9.0)': + '@graphprotocol/client-block-tracking@2.0.6(@graphql-mesh/store@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@types/node@22.10.2)(graphql@16.10.0)': dependencies: - '@graphql-mesh/fusion-runtime': 0.8.14(@graphql-mesh/store@0.98.10)(@types/node@22.10.2)(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/fusion-runtime': 0.8.14(@graphql-mesh/store@0.98.10)(@types/node@22.10.2)(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - '@graphql-mesh/store' - '@types/node' - '@graphprotocol/client-cli@3.0.3(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/merge@9.0.13(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0)': + '@graphprotocol/client-cli@3.0.3(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/merge@9.0.14(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0)': dependencies: - '@graphprotocol/client-add-source-name': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(graphql@16.9.0) - '@graphprotocol/client-auto-pagination': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@graphql-tools/wrap@10.0.26(graphql@16.9.0))(graphql@16.9.0) - '@graphprotocol/client-auto-type-merging': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(graphql@16.9.0) - '@graphprotocol/client-block-tracking': 2.0.6(@graphql-mesh/store@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.9.0))(@types/node@22.10.2)(graphql@16.9.0) - '@graphprotocol/client-polling-live': 2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.13(graphql@16.9.0))(graphql@16.9.0) - '@graphql-mesh/cli': 0.90.12(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0) - '@graphql-mesh/graphql': 0.98.11(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.9.0)(tslib@2.8.1) - graphql: 16.9.0 + '@graphprotocol/client-add-source-name': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(graphql@16.10.0) + '@graphprotocol/client-auto-pagination': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@graphql-tools/wrap@10.0.26(graphql@16.10.0))(graphql@16.10.0) + '@graphprotocol/client-auto-type-merging': 2.0.7(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(graphql@16.10.0) + '@graphprotocol/client-block-tracking': 2.0.6(@graphql-mesh/store@0.98.10)(@graphql-tools/delegate@10.2.8(graphql@16.10.0))(@types/node@22.10.2)(graphql@16.10.0) + '@graphprotocol/client-polling-live': 2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.14(graphql@16.10.0))(graphql@16.10.0) + '@graphql-mesh/cli': 0.90.12(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0) + '@graphql-mesh/graphql': 0.98.11(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.10.0)(tslib@2.8.1) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - '@envelop/core' @@ -11476,12 +11477,12 @@ snapshots: - supports-color - utf-8-validate - '@graphprotocol/client-polling-live@2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.13(graphql@16.9.0))(graphql@16.9.0)': + '@graphprotocol/client-polling-live@2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.14(graphql@16.10.0))(graphql@16.10.0)': dependencies: '@envelop/core': 5.0.2 - '@graphql-tools/merge': 9.0.13(graphql@16.9.0) + '@graphql-tools/merge': 9.0.14(graphql@16.10.0) '@repeaterjs/repeater': 3.0.6 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 '@graphprotocol/common-ts@2.0.11(encoding@0.1.13)': @@ -11589,140 +11590,140 @@ snapshots: - typescript - utf-8-validate - '@graphql-codegen/core@4.0.2(graphql@16.9.0)': + '@graphql-codegen/core@4.0.2(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.6.3 - '@graphql-codegen/plugin-helpers@2.7.2(graphql@16.9.0)': + '@graphql-codegen/plugin-helpers@2.7.2(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 8.13.1(graphql@16.9.0) + '@graphql-tools/utils': 8.13.1(graphql@16.10.0) change-case-all: 1.0.14 common-tags: 1.8.2 - graphql: 16.9.0 + graphql: 16.10.0 import-from: 4.0.0 lodash: 4.17.21 tslib: 2.4.1 - '@graphql-codegen/plugin-helpers@3.1.2(graphql@16.9.0)': + '@graphql-codegen/plugin-helpers@3.1.2(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 9.2.1(graphql@16.9.0) + '@graphql-tools/utils': 9.2.1(graphql@16.10.0) change-case-all: 1.0.15 common-tags: 1.8.2 - graphql: 16.9.0 + graphql: 16.10.0 import-from: 4.0.0 lodash: 4.17.21 tslib: 2.4.1 - '@graphql-codegen/plugin-helpers@5.1.0(graphql@16.9.0)': + '@graphql-codegen/plugin-helpers@5.1.0(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) change-case-all: 1.0.15 common-tags: 1.8.2 - graphql: 16.9.0 + graphql: 16.10.0 import-from: 4.0.0 lodash: 4.17.21 tslib: 2.6.3 - '@graphql-codegen/schema-ast@4.1.0(graphql@16.9.0)': + '@graphql-codegen/schema-ast@4.1.0(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.6.3 - '@graphql-codegen/typed-document-node@5.0.12(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/typed-document-node@5.0.12(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.10.0) auto-bind: 4.0.0 change-case-all: 1.0.15 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.6.3 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/typescript-generic-sdk@3.1.0(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql@16.9.0)': + '@graphql-codegen/typescript-generic-sdk@3.1.0(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.9.0) - '@graphql-codegen/visitor-plugin-common': 2.13.1(encoding@0.1.13)(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.10.0) + '@graphql-codegen/visitor-plugin-common': 2.13.1(encoding@0.1.13)(graphql@16.10.0) auto-bind: 4.0.0 - graphql: 16.9.0 - graphql-tag: 2.12.6(graphql@16.9.0) + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) tslib: 2.4.1 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/typescript-operations@4.4.0(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/typescript-operations@4.4.0(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.9.0) - '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.10.0) + '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.10.0) auto-bind: 4.0.0 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.6.3 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/typescript-resolvers@4.4.1(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/typescript-resolvers@4.4.1(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.9.0) - '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.10.0) + '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) auto-bind: 4.0.0 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.6.3 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/typescript@4.1.2(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/typescript@4.1.2(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-codegen/schema-ast': 4.1.0(graphql@16.9.0) - '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-codegen/schema-ast': 4.1.0(graphql@16.10.0) + '@graphql-codegen/visitor-plugin-common': 5.6.0(encoding@0.1.13)(graphql@16.10.0) auto-bind: 4.0.0 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.6.3 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/visitor-plugin-common@2.13.1(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/visitor-plugin-common@2.13.1(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.9.0) - '@graphql-tools/optimize': 1.4.0(graphql@16.9.0) - '@graphql-tools/relay-operation-optimizer': 6.5.18(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 8.13.1(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.10.0) + '@graphql-tools/optimize': 1.4.0(graphql@16.10.0) + '@graphql-tools/relay-operation-optimizer': 6.5.18(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 8.13.1(graphql@16.10.0) auto-bind: 4.0.0 change-case-all: 1.0.14 dependency-graph: 0.11.0 - graphql: 16.9.0 - graphql-tag: 2.12.6(graphql@16.9.0) + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) parse-filepath: 1.0.2 tslib: 2.4.1 transitivePeerDependencies: - encoding - supports-color - '@graphql-codegen/visitor-plugin-common@5.6.0(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-codegen/visitor-plugin-common@5.6.0(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.9.0) - '@graphql-tools/optimize': 2.0.0(graphql@16.9.0) - '@graphql-tools/relay-operation-optimizer': 7.0.7(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) + '@graphql-tools/optimize': 2.0.0(graphql@16.10.0) + '@graphql-tools/relay-operation-optimizer': 7.0.8(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) auto-bind: 4.0.0 change-case-all: 1.0.15 dependency-graph: 0.11.0 - graphql: 16.9.0 - graphql-tag: 2.12.6(graphql@16.9.0) + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) parse-filepath: 1.0.2 tslib: 2.6.3 transitivePeerDependencies: @@ -11733,51 +11734,51 @@ snapshots: dependencies: tslib: 2.8.1 - '@graphql-inspector/core@6.1.0(graphql@16.9.0)': + '@graphql-inspector/core@6.1.0(graphql@16.10.0)': dependencies: dependency-graph: 1.0.0 - graphql: 16.9.0 + graphql: 16.10.0 object-inspect: 1.13.1 tslib: 2.6.2 - '@graphql-inspector/core@6.2.1(graphql@16.9.0)': + '@graphql-inspector/core@6.2.1(graphql@16.10.0)': dependencies: dependency-graph: 1.0.0 - graphql: 16.9.0 + graphql: 16.10.0 object-inspect: 1.13.2 tslib: 2.6.2 - '@graphql-mesh/cache-localforage@0.98.10(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/cache-localforage@0.98.10(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - graphql: 16.9.0 + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + graphql: 16.10.0 localforage: 1.10.0 tslib: 2.8.1 - '@graphql-mesh/cli@0.90.12(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0)': - dependencies: - '@graphql-codegen/core': 4.0.2(graphql@16.9.0) - '@graphql-codegen/typed-document-node': 5.0.12(encoding@0.1.13)(graphql@16.9.0) - '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.9.0) - '@graphql-codegen/typescript-generic-sdk': 3.1.0(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.9.0))(graphql@16.9.0) - '@graphql-codegen/typescript-operations': 4.4.0(encoding@0.1.13)(graphql@16.9.0) - '@graphql-codegen/typescript-resolvers': 4.4.1(encoding@0.1.13)(graphql@16.9.0) - '@graphql-mesh/config': 0.100.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/http': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-mesh/cli@0.90.12(@types/node@22.10.2)(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0)': + dependencies: + '@graphql-codegen/core': 4.0.2(graphql@16.10.0) + '@graphql-codegen/typed-document-node': 5.0.12(encoding@0.1.13)(graphql@16.10.0) + '@graphql-codegen/typescript': 4.1.2(encoding@0.1.13)(graphql@16.10.0) + '@graphql-codegen/typescript-generic-sdk': 3.1.0(encoding@0.1.13)(graphql-tag@2.12.6(graphql@16.10.0))(graphql@16.10.0) + '@graphql-codegen/typescript-operations': 4.4.0(encoding@0.1.13)(graphql@16.10.0) + '@graphql-codegen/typescript-resolvers': 4.4.1(encoding@0.1.13)(graphql@16.10.0) + '@graphql-mesh/config': 0.100.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/http': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) ajv: 8.17.1 change-case: 4.1.2 cosmiconfig: 9.0.0(typescript@5.7.2) dotenv: 16.4.7 - graphql: 16.9.0 - graphql-import-node: 0.0.5(graphql@16.9.0) - graphql-ws: 5.16.0(graphql@16.9.0) + graphql: 16.10.0 + graphql-import-node: 0.0.5(graphql@16.10.0) + graphql-ws: 5.16.0(graphql@16.10.0) json-bigint-patch: 0.0.8 json5: 2.2.3 mkdirp: 3.0.1 @@ -11804,25 +11805,25 @@ snapshots: - supports-color - utf-8-validate - '@graphql-mesh/config@0.100.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/config@0.100.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: '@envelop/core': 5.0.2 - '@graphql-mesh/cache-localforage': 0.98.10(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/merger-bare': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/merger-stitching': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/code-file-loader': 8.1.9(graphql@16.9.0) - '@graphql-tools/graphql-file-loader': 8.0.7(graphql@16.9.0) - '@graphql-tools/load': 8.0.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-yoga/plugin-persisted-operations': 3.10.5(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0) + '@graphql-mesh/cache-localforage': 0.98.10(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/merger-bare': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/merger-stitching': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/code-file-loader': 8.1.10(graphql@16.10.0) + '@graphql-tools/graphql-file-loader': 8.0.8(graphql@16.10.0) + '@graphql-tools/load': 8.0.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-yoga/plugin-persisted-operations': 3.10.6(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0) '@whatwg-node/fetch': 0.9.23 camel-case: 4.1.2 - graphql: 16.9.0 + graphql: 16.10.0 param-case: 3.0.4 pascal-case: 3.1.2 tslib: 2.8.1 @@ -11830,48 +11831,48 @@ snapshots: - graphql-yoga - supports-color - '@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0)': + '@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 path-browserify: 1.0.1 - '@graphql-mesh/fusion-runtime@0.8.14(@graphql-mesh/store@0.98.10)(@types/node@22.10.2)(graphql@16.9.0)': + '@graphql-mesh/fusion-runtime@0.8.14(@graphql-mesh/store@0.98.10)(@types/node@22.10.2)(graphql@16.10.0)': dependencies: '@envelop/core': 5.0.2 - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/runtime': 0.103.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/transport-common': 0.7.23(graphql@16.9.0) - '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/federation': 2.2.40(@types/node@22.10.2)(graphql@16.9.0) - '@graphql-tools/stitch': 9.4.10(graphql@16.9.0) - '@graphql-tools/stitching-directives': 3.1.23(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/runtime': 0.103.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/transport-common': 0.7.23(graphql@16.10.0) + '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/federation': 2.2.40(@types/node@22.10.2)(graphql@16.10.0) + '@graphql-tools/stitch': 9.4.10(graphql@16.10.0) + '@graphql-tools/stitching-directives': 3.1.23(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@whatwg-node/disposablestack': 0.0.5 change-case: 4.1.2 - graphql: 16.9.0 - graphql-yoga: 5.10.5(graphql@16.9.0) + graphql: 16.10.0 + graphql-yoga: 5.10.6(graphql@16.10.0) tslib: 2.8.1 transitivePeerDependencies: - '@graphql-mesh/store' - '@types/node' - '@graphql-mesh/graphql@0.98.11(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.9.0)(tslib@2.8.1)': - dependencies: - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/federation': 2.2.40(@types/node@22.10.2)(graphql@16.9.0) - '@graphql-tools/url-loader': 8.0.19(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/graphql@0.98.11(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.10.0)(tslib@2.8.1)': + dependencies: + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/federation': 2.2.40(@types/node@22.10.2)(graphql@16.10.0) + '@graphql-tools/url-loader': 8.0.20(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 lodash.get: 4.4.2 tslib: 2.8.1 transitivePeerDependencies: @@ -11880,254 +11881,254 @@ snapshots: - encoding - utf-8-validate - '@graphql-mesh/http@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/http@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/runtime': 0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@whatwg-node/server': 0.9.63 - graphql: 16.9.0 - graphql-yoga: 5.10.5(graphql@16.9.0) + graphql: 16.10.0 + graphql-yoga: 5.10.6(graphql@16.10.0) tslib: 2.8.1 - '@graphql-mesh/merger-bare@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/merger-bare@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/merger-stitching': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/schema': 10.0.4(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/merger-stitching': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/schema': 10.0.4(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - '@graphql-mesh/store' - '@graphql-mesh/merger-stitching@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/merger-stitching@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/stitch': 9.4.10(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/stitch': 9.4.10(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/runtime@0.103.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/runtime@0.103.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: '@envelop/core': 5.0.2 - '@envelop/extended-validation': 4.1.0(@envelop/core@5.0.2)(graphql@16.9.0) - '@envelop/graphql-jit': 8.0.4(@envelop/core@5.0.2)(graphql@16.9.0) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@envelop/extended-validation': 4.1.0(@envelop/core@5.0.2)(graphql@16.10.0) + '@envelop/graphql-jit': 8.0.4(@envelop/core@5.0.2)(graphql@16.10.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@whatwg-node/fetch': 0.9.23 - graphql: 16.9.0 - graphql-jit: 0.8.7(graphql@16.9.0) + graphql: 16.10.0 + graphql-jit: 0.8.7(graphql@16.10.0) tslib: 2.8.1 - '@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/runtime@0.99.12(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: '@envelop/core': 5.0.2 - '@envelop/extended-validation': 4.1.0(@envelop/core@5.0.2)(graphql@16.9.0) - '@envelop/graphql-jit': 8.0.4(@envelop/core@5.0.2)(graphql@16.9.0) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@envelop/extended-validation': 4.1.0(@envelop/core@5.0.2)(graphql@16.10.0) + '@envelop/graphql-jit': 8.0.4(@envelop/core@5.0.2)(graphql@16.10.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@whatwg-node/fetch': 0.9.23 - graphql: 16.9.0 - graphql-jit: 0.8.2(graphql@16.9.0) + graphql: 16.10.0 + graphql-jit: 0.8.2(graphql@16.10.0) tslib: 2.8.1 - '@graphql-mesh/store@0.103.8(graphql@16.9.0)': + '@graphql-mesh/store@0.103.9(graphql@16.10.0)': dependencies: - '@graphql-inspector/core': 6.2.1(graphql@16.9.0) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/types': 0.103.8(graphql@16.9.0) - '@graphql-mesh/utils': 0.103.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-inspector/core': 6.2.1(graphql@16.10.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/types': 0.103.9(graphql@16.10.0) + '@graphql-mesh/utils': 0.103.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/store@0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/store@0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-inspector/core': 6.1.0(graphql@16.9.0) - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-inspector/core': 6.1.0(graphql@16.10.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/string-interpolation@0.5.7(graphql@16.9.0)': + '@graphql-mesh/string-interpolation@0.5.7(graphql@16.10.0)': dependencies: dayjs: 1.11.13 - graphql: 16.9.0 + graphql: 16.10.0 json-pointer: 0.6.2 lodash.get: 4.4.2 tslib: 2.8.1 - '@graphql-mesh/transform-type-merging@0.102.13(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/transform-type-merging@0.102.13(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/stitching-directives': 3.1.23(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-mesh/utils': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/stitching-directives': 3.1.23(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/transport-common@0.7.23(graphql@16.9.0)': + '@graphql-mesh/transport-common@0.7.23(graphql@16.10.0)': dependencies: '@envelop/core': 5.0.2 '@graphql-hive/gateway-abort-signal-any': 0.0.1 - '@graphql-mesh/types': 0.103.8(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/types': 0.103.9(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/types@0.103.8(graphql@16.9.0)': + '@graphql-mesh/types@0.103.9(graphql@16.10.0)': dependencies: - '@graphql-mesh/store': 0.103.8(graphql@16.9.0) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/store': 0.103.9(graphql@16.10.0) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/types@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/types@0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-mesh/store': 0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-mesh/utils@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/utils@0.102.13(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1))(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.102.13(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@whatwg-node/disposablestack': 0.0.5 '@whatwg-node/fetch': 0.10.1 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 js-yaml: 4.1.0 lodash.get: 4.4.2 lodash.topath: 4.5.2 tiny-lru: 11.2.11 tslib: 2.8.1 - '@graphql-mesh/utils@0.103.8(graphql@16.9.0)': + '@graphql-mesh/utils@0.103.9(graphql@16.10.0)': dependencies: - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.103.8(graphql@16.9.0) - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.103.9(graphql@16.10.0) + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@whatwg-node/disposablestack': 0.0.5 '@whatwg-node/fetch': 0.10.1 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 js-yaml: 4.1.0 lodash.get: 4.4.2 lodash.topath: 4.5.2 tiny-lru: 11.2.11 tslib: 2.8.1 - '@graphql-mesh/utils@0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.9.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1)': + '@graphql-mesh/utils@0.98.10(@graphql-mesh/cross-helpers@0.4.9(graphql@16.10.0))(@graphql-mesh/types@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1)': dependencies: - '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.9.0) - '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.9.0) - '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.3(graphql@16.9.0))(graphql@16.9.0)(tslib@2.8.1) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.9(graphql@16.10.0) + '@graphql-mesh/string-interpolation': 0.5.7(graphql@16.10.0) + '@graphql-mesh/types': 0.98.10(@graphql-mesh/store@0.98.10)(@graphql-tools/utils@10.6.4(graphql@16.10.0))(graphql@16.10.0)(tslib@2.8.1) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@whatwg-node/fetch': 0.9.23 disposablestack: 1.1.7 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 js-yaml: 4.1.0 lodash.get: 4.4.2 lodash.topath: 4.5.2 tiny-lru: 11.2.11 tslib: 2.8.1 - '@graphql-tools/batch-delegate@9.0.24(graphql@16.9.0)': + '@graphql-tools/batch-delegate@9.0.24(graphql@16.10.0)': dependencies: - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) dataloader: 2.2.3 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/batch-execute@9.0.10(graphql@16.9.0)': + '@graphql-tools/batch-execute@9.0.10(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) dataloader: 2.2.3 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/code-file-loader@8.1.9(graphql@16.9.0)': + '@graphql-tools/code-file-loader@8.1.10(graphql@16.10.0)': dependencies: - '@graphql-tools/graphql-tag-pluck': 8.3.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/graphql-tag-pluck': 8.3.9(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) globby: 11.1.0 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 unixify: 1.0.0 transitivePeerDependencies: - supports-color - '@graphql-tools/delegate@10.2.8(graphql@16.9.0)': + '@graphql-tools/delegate@10.2.8(graphql@16.10.0)': dependencies: - '@graphql-tools/batch-execute': 9.0.10(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/batch-execute': 9.0.10(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@repeaterjs/repeater': 3.0.6 dataloader: 2.2.3 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/executor-graphql-ws@1.3.5(graphql@16.9.0)': + '@graphql-tools/executor-graphql-ws@1.3.5(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@whatwg-node/disposablestack': 0.0.5 - graphql: 16.9.0 - graphql-ws: 5.16.0(graphql@16.9.0) + graphql: 16.10.0 + graphql-ws: 5.16.0(graphql@16.10.0) isomorphic-ws: 5.0.0(ws@8.18.0) tslib: 2.8.1 ws: 8.18.0 @@ -12135,26 +12136,26 @@ snapshots: - bufferutil - utf-8-validate - '@graphql-tools/executor-http@1.2.1(@types/node@22.10.2)(graphql@16.9.0)': + '@graphql-tools/executor-http@1.2.1(@types/node@22.10.2)(graphql@16.10.0)': dependencies: '@graphql-hive/gateway-abort-signal-any': 0.0.1 - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@repeaterjs/repeater': 3.0.6 '@whatwg-node/disposablestack': 0.0.5 '@whatwg-node/fetch': 0.10.1 extract-files: 11.0.0 - graphql: 16.9.0 + graphql: 16.10.0 meros: 1.3.0(@types/node@22.10.2) tslib: 2.8.1 value-or-promise: 1.0.12 transitivePeerDependencies: - '@types/node' - '@graphql-tools/executor-legacy-ws@1.1.6(graphql@16.9.0)': + '@graphql-tools/executor-legacy-ws@1.1.7(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@types/ws': 8.5.13 - graphql: 16.9.0 + graphql: 16.10.0 isomorphic-ws: 5.0.0(ws@8.18.0) tslib: 2.8.1 ws: 8.18.0 @@ -12162,150 +12163,150 @@ snapshots: - bufferutil - utf-8-validate - '@graphql-tools/executor@1.3.8(graphql@16.9.0)': + '@graphql-tools/executor@1.3.9(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) '@repeaterjs/repeater': 3.0.6 '@whatwg-node/disposablestack': 0.0.5 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 value-or-promise: 1.0.12 - '@graphql-tools/federation@2.2.40(@types/node@22.10.2)(graphql@16.9.0)': + '@graphql-tools/federation@2.2.40(@types/node@22.10.2)(graphql@16.10.0)': dependencies: - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/executor-http': 1.2.1(@types/node@22.10.2)(graphql@16.9.0) - '@graphql-tools/merge': 9.0.13(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/stitch': 9.4.10(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/executor-http': 1.2.1(@types/node@22.10.2)(graphql@16.10.0) + '@graphql-tools/merge': 9.0.14(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/stitch': 9.4.10(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@whatwg-node/fetch': 0.10.1 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - '@types/node' - '@graphql-tools/graphql-file-loader@8.0.7(graphql@16.9.0)': + '@graphql-tools/graphql-file-loader@8.0.8(graphql@16.10.0)': dependencies: - '@graphql-tools/import': 7.0.7(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/import': 7.0.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) globby: 11.1.0 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 unixify: 1.0.0 - '@graphql-tools/graphql-tag-pluck@8.3.8(graphql@16.9.0)': + '@graphql-tools/graphql-tag-pluck@8.3.9(graphql@16.10.0)': dependencies: '@babel/core': 7.26.0 '@babel/parser': 7.26.3 '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.0) '@babel/traverse': 7.26.4 '@babel/types': 7.26.3 - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@graphql-tools/import@7.0.7(graphql@16.9.0)': + '@graphql-tools/import@7.0.8(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 resolve-from: 5.0.0 tslib: 2.8.1 - '@graphql-tools/load@8.0.8(graphql@16.9.0)': + '@graphql-tools/load@8.0.9(graphql@16.10.0)': dependencies: - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 p-limit: 3.1.0 tslib: 2.8.1 - '@graphql-tools/merge@9.0.13(graphql@16.9.0)': + '@graphql-tools/merge@9.0.14(graphql@16.10.0)': dependencies: - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/optimize@1.4.0(graphql@16.9.0)': + '@graphql-tools/optimize@1.4.0(graphql@16.10.0)': dependencies: - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/optimize@2.0.0(graphql@16.9.0)': + '@graphql-tools/optimize@2.0.0(graphql@16.10.0)': dependencies: - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/relay-operation-optimizer@6.5.18(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-tools/relay-operation-optimizer@6.5.18(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@ardatan/relay-compiler': 12.0.0(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 9.2.1(graphql@16.9.0) - graphql: 16.9.0 + '@ardatan/relay-compiler': 12.0.0(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 9.2.1(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - encoding - supports-color - '@graphql-tools/relay-operation-optimizer@7.0.7(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-tools/relay-operation-optimizer@7.0.8(encoding@0.1.13)(graphql@16.10.0)': dependencies: - '@ardatan/relay-compiler': 12.0.0(encoding@0.1.13)(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@ardatan/relay-compiler': 12.0.0(encoding@0.1.13)(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 transitivePeerDependencies: - encoding - supports-color - '@graphql-tools/schema@10.0.12(graphql@16.9.0)': + '@graphql-tools/schema@10.0.13(graphql@16.10.0)': dependencies: - '@graphql-tools/merge': 9.0.13(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/merge': 9.0.14(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 value-or-promise: 1.0.12 - '@graphql-tools/schema@10.0.4(graphql@16.9.0)': + '@graphql-tools/schema@10.0.4(graphql@16.10.0)': dependencies: - '@graphql-tools/merge': 9.0.13(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/merge': 9.0.14(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 value-or-promise: 1.0.12 - '@graphql-tools/stitch@9.4.10(graphql@16.9.0)': + '@graphql-tools/stitch@9.4.10(graphql@16.10.0)': dependencies: - '@graphql-tools/batch-delegate': 9.0.24(graphql@16.9.0) - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/merge': 9.0.13(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/batch-delegate': 9.0.24(graphql@16.10.0) + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/merge': 9.0.14(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/stitching-directives@3.1.23(graphql@16.9.0)': + '@graphql-tools/stitching-directives@3.1.23(graphql@16.10.0)': dependencies: - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/url-loader@8.0.19(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.9.0)': + '@graphql-tools/url-loader@8.0.20(@types/node@22.10.2)(encoding@0.1.13)(graphql@16.10.0)': dependencies: '@ardatan/sync-fetch': 0.0.1(encoding@0.1.13) - '@graphql-tools/executor-graphql-ws': 1.3.5(graphql@16.9.0) - '@graphql-tools/executor-http': 1.2.1(@types/node@22.10.2)(graphql@16.9.0) - '@graphql-tools/executor-legacy-ws': 1.1.6(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - '@graphql-tools/wrap': 10.0.26(graphql@16.9.0) + '@graphql-tools/executor-graphql-ws': 1.3.5(graphql@16.10.0) + '@graphql-tools/executor-http': 1.2.1(@types/node@22.10.2)(graphql@16.10.0) + '@graphql-tools/executor-legacy-ws': 1.1.7(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + '@graphql-tools/wrap': 10.0.26(graphql@16.10.0) '@types/ws': 8.5.13 '@whatwg-node/fetch': 0.10.1 - graphql: 16.9.0 + graphql: 16.10.0 isomorphic-ws: 5.0.0(ws@8.18.0) tslib: 2.8.1 value-or-promise: 1.0.12 @@ -12316,45 +12317,45 @@ snapshots: - encoding - utf-8-validate - '@graphql-tools/utils@10.6.3(graphql@16.9.0)': + '@graphql-tools/utils@10.6.4(graphql@16.10.0)': dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) cross-inspect: 1.0.1 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/utils@8.13.1(graphql@16.9.0)': + '@graphql-tools/utils@8.13.1(graphql@16.10.0)': dependencies: - graphql: 16.9.0 + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/utils@9.2.1(graphql@16.9.0)': + '@graphql-tools/utils@9.2.1(graphql@16.10.0)': dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-tools/wrap@10.0.26(graphql@16.9.0)': + '@graphql-tools/wrap@10.0.26(graphql@16.10.0)': dependencies: - '@graphql-tools/delegate': 10.2.8(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) - graphql: 16.9.0 + '@graphql-tools/delegate': 10.2.8(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) + graphql: 16.10.0 tslib: 2.8.1 - '@graphql-typed-document-node/core@3.2.0(graphql@16.9.0)': + '@graphql-typed-document-node/core@3.2.0(graphql@16.10.0)': dependencies: - graphql: 16.9.0 + graphql: 16.10.0 '@graphql-yoga/logger@2.0.0': dependencies: tslib: 2.8.1 - '@graphql-yoga/plugin-persisted-operations@3.10.5(graphql-yoga@5.10.5(graphql@16.9.0))(graphql@16.9.0)': + '@graphql-yoga/plugin-persisted-operations@3.10.6(graphql-yoga@5.10.6(graphql@16.10.0))(graphql@16.10.0)': dependencies: - graphql: 16.9.0 - graphql-yoga: 5.10.5(graphql@16.9.0) + graphql: 16.10.0 + graphql-yoga: 5.10.6(graphql@16.10.0) '@graphql-yoga/subscription@5.0.2': dependencies: @@ -12374,7 +12375,7 @@ snapshots: '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/react-virtual': 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-virtual': 3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) client-only: 0.0.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -12384,7 +12385,7 @@ snapshots: '@floating-ui/react': 0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.19.0(react@18.3.1) '@react-aria/interactions': 3.22.5(react@18.3.1) - '@tanstack/react-virtual': 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-virtual': 3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -12495,7 +12496,7 @@ snapshots: '@mdx-js/react@2.3.0(react@18.3.1)': dependencies: '@types/mdx': 2.0.13 - '@types/react': 18.3.16 + '@types/react': 18.3.17 react: 18.3.1 '@metamask/eth-sig-util@4.0.1': @@ -12841,445 +12842,445 @@ snapshots: '@radix-ui/primitive@1.1.1': {} - '@radix-ui/react-accordion@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-accordion@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collapsible': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-collapsible': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-alert-dialog@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-alert-dialog@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dialog': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-arrow@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-arrow@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-collapsible@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collapsible@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-collection@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collection@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-compose-refs@1.1.1(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-context@1.1.1(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-context@1.1.1(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-dialog@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dialog@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.0(@types/react@18.3.16)(react@18.3.1) + react-remove-scroll: 2.6.0(@types/react@18.3.17)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-direction@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-direction@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-dismissable-layer@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-dropdown-menu@2.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dropdown-menu@2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-menu': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-menu': 2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-id@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-id@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-label@2.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-label@2.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-menu@2.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-menu@2.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.0(@types/react@18.3.16)(react@18.3.1) + react-remove-scroll: 2.6.0(@types/react@18.3.17)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-navigation-menu@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-navigation-menu@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-popover@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popover@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.0(@types/react@18.3.16)(react@18.3.1) + react-remove-scroll: 2.6.0(@types/react@18.3.17)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-popper@1.2.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popper@1.2.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-arrow': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.17)(react@18.3.1) '@radix-ui/rect': 1.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-portal@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-primitive@2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-slider@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-slider@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-slot@1.1.1(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-slot@1.1.1(@types/react@18.3.17)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-switch@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-switch@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-toast@1.2.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-toast@1.2.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-tooltip@1.1.5(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tooltip@1.1.5(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-context': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.1(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.16)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.17)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: '@radix-ui/rect': 1.1.0 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-use-size@1.1.0(@types/react@18.3.16)(react@18.3.1)': + '@radix-ui/react-use-size@1.1.0(@types/react@18.3.17)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.16)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.17)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.16))(@types/react@18.3.16)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 - '@types/react-dom': 18.3.5(@types/react@18.3.16) + '@types/react': 18.3.17 + '@types/react-dom': 18.3.5(@types/react@18.3.17) '@radix-ui/rect@1.1.0': {} @@ -14466,13 +14467,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-virtual@3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/virtual-core': 3.10.9 + '@tanstack/virtual-core': 3.11.2 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/virtual-core@3.10.9': {} + '@tanstack/virtual-core@3.11.2': {} '@theguild/remark-mermaid@0.0.5(react@18.3.1)': dependencies: @@ -14487,57 +14488,57 @@ snapshots: npm-to-yarn: 2.2.1 unist-util-visit: 5.0.0 - '@theme-ui/color-modes@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)': + '@theme-ui/color-modes@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) deepmerge: 4.3.1 react: 18.3.1 - '@theme-ui/components@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@theme-ui/components@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) '@styled-system/color': 5.1.2 '@styled-system/should-forward-prop': 5.1.5 '@styled-system/space': 5.1.2 - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) - '@theme-ui/theme-provider': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) + '@theme-ui/theme-provider': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) '@types/styled-system': 5.1.23 react: 18.3.1 - '@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)': + '@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) deepmerge: 4.3.1 react: 18.3.1 - '@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))': + '@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) csstype: 3.1.3 - '@theme-ui/global@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)': + '@theme-ui/global@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) react: 18.3.1 - '@theme-ui/match-media@0.17.1(@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)))(react@18.3.1)': + '@theme-ui/match-media@0.17.1(@theme-ui/core@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(@theme-ui/css@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)))(react@18.3.1)': dependencies: - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) react: 18.3.1 - '@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1)': + '@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@theme-ui/color-modes': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@theme-ui/color-modes': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) react: 18.3.1 '@ts-morph/common@0.24.0': @@ -14723,11 +14724,11 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@18.3.5(@types/react@18.3.16)': + '@types/react-dom@18.3.5(@types/react@18.3.17)': dependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - '@types/react@18.3.16': + '@types/react@18.3.17': dependencies: '@types/prop-types': 15.7.14 csstype: 3.1.3 @@ -14953,7 +14954,7 @@ snapshots: '@vitest/snapshot@1.6.0': dependencies: - magic-string: 0.30.15 + magic-string: 0.30.17 pathe: 1.1.2 pretty-format: 29.7.0 @@ -15022,10 +15023,10 @@ snapshots: '@xstate/fsm@1.6.5': {} - '@xstate/react@3.2.2(@types/react@18.3.16)(react@18.3.1)(xstate@4.38.3)': + '@xstate/react@3.2.2(@types/react@18.3.17)(react@18.3.1)(xstate@4.38.3)': dependencies: react: 18.3.1 - use-isomorphic-layout-effect: 1.2.0(@types/react@18.3.16)(react@18.3.1) + use-isomorphic-layout-effect: 1.2.0(@types/react@18.3.17)(react@18.3.1) use-sync-external-store: 1.4.0(react@18.3.1) optionalDependencies: xstate: 4.38.3 @@ -15197,10 +15198,10 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-object-atoms: 1.0.0 get-intrinsic: 1.2.6 - is-string: 1.1.0 + is-string: 1.1.1 array-union@2.1.0: {} @@ -15208,7 +15209,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-object-atoms: 1.0.0 es-shim-unscopables: 1.0.2 @@ -15217,43 +15218,42 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-object-atoms: 1.0.0 es-shim-unscopables: 1.0.2 - array.prototype.flat@1.3.2: + array.prototype.flat@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-shim-unscopables: 1.0.2 - array.prototype.flatmap@1.3.2: + array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-shim-unscopables: 1.0.2 array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-shim-unscopables: 1.0.2 - arraybuffer.prototype.slice@1.0.3: + arraybuffer.prototype.slice@1.0.4: dependencies: array-buffer-byte-length: 1.0.1 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 get-intrinsic: 1.2.6 is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 as-table@1.0.55: dependencies: @@ -15286,7 +15286,7 @@ snapshots: autoprefixer@10.4.20(postcss@8.4.49): dependencies: browserslist: 4.24.3 - caniuse-lite: 1.0.30001688 + caniuse-lite: 1.0.30001689 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -15468,7 +15468,7 @@ snapshots: browserslist@4.24.3: dependencies: - caniuse-lite: 1.0.30001688 + caniuse-lite: 1.0.30001689 electron-to-chromium: 1.5.73 node-releases: 2.0.19 update-browserslist-db: 1.1.1(browserslist@4.24.3) @@ -15548,9 +15548,9 @@ snapshots: get-intrinsic: 1.2.6 set-function-length: 1.2.2 - call-bound@1.0.2: + call-bound@1.0.3: dependencies: - call-bind: 1.0.8 + call-bind-apply-helpers: 1.0.1 get-intrinsic: 1.2.6 callsites@3.1.0: {} @@ -15568,7 +15568,7 @@ snapshots: camelize@1.0.1: {} - caniuse-lite@1.0.30001688: {} + caniuse-lite@1.0.30001689: {} capital-case@1.0.4: dependencies: @@ -16268,9 +16268,9 @@ snapshots: disposablestack@1.1.7: dependencies: call-bind: 1.0.8 - call-bound: 1.0.2 + call-bound: 1.0.3 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-set-tostringtag: 2.0.3 get-intrinsic: 1.2.6 @@ -16398,12 +16398,13 @@ snapshots: dependencies: stackframe: 1.3.4 - es-abstract@1.23.5: + es-abstract@1.23.6: dependencies: array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 + arraybuffer.prototype.slice: 1.0.4 available-typed-arrays: 1.0.7 call-bind: 1.0.8 + call-bound: 1.0.3 data-view-buffer: 1.0.1 data-view-byte-length: 1.0.1 data-view-byte-offset: 1.0.0 @@ -16412,7 +16413,7 @@ snapshots: es-object-atoms: 1.0.0 es-set-tostringtag: 2.0.3 es-to-primitive: 1.3.0 - function.prototype.name: 1.1.6 + function.prototype.name: 1.1.7 get-intrinsic: 1.2.6 get-symbol-description: 1.0.2 globalthis: 1.0.4 @@ -16428,9 +16429,10 @@ snapshots: is-negative-zero: 2.0.3 is-regex: 1.2.1 is-shared-array-buffer: 1.0.3 - is-string: 1.1.0 + is-string: 1.1.1 is-typed-array: 1.1.13 is-weakref: 1.1.0 + math-intrinsics: 1.0.0 object-inspect: 1.13.3 object-keys: 1.1.1 object.assign: 4.1.5 @@ -16444,7 +16446,7 @@ snapshots: typed-array-byte-length: 1.0.1 typed-array-byte-offset: 1.0.3 typed-array-length: 1.0.7 - unbox-primitive: 1.0.2 + unbox-primitive: 1.1.0 which-typed-array: 1.1.16 es-define-property@1.0.1: {} @@ -16455,7 +16457,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-set-tostringtag: 2.0.3 function-bind: 1.1.2 @@ -16664,8 +16666,8 @@ snapshots: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 eslint: 8.57.1 @@ -16692,7 +16694,7 @@ snapshots: dependencies: aria-query: 5.3.2 array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 + array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 axe-core: 4.10.2 axobject-query: 4.1.0 @@ -16736,7 +16738,7 @@ snapshots: dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 + array.prototype.flatmap: 1.3.3 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.0 @@ -17128,7 +17130,7 @@ snapshots: fast-uri@3.0.3: {} - fast-xml-parser@4.5.0: + fast-xml-parser@4.5.1: dependencies: strnum: 1.0.5 @@ -17258,7 +17260,7 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@11.14.4(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + framer-motion@11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: motion-dom: 11.14.3 motion-utils: 11.14.3 @@ -17313,12 +17315,13 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.6: + function.prototype.name@1.1.7: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 functional-red-black-tree@1.0.1: {} @@ -17484,63 +17487,63 @@ snapshots: js-base64: 3.7.7 unicode-trie: 2.0.0 - graphql-import-node@0.0.5(graphql@16.9.0): + graphql-import-node@0.0.5(graphql@16.10.0): dependencies: - graphql: 16.9.0 + graphql: 16.10.0 - graphql-jit@0.8.2(graphql@16.9.0): + graphql-jit@0.8.2(graphql@16.10.0): dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) fast-json-stringify: 1.21.0 generate-function: 2.3.1 - graphql: 16.9.0 + graphql: 16.10.0 json-schema: 0.4.0 lodash.memoize: 4.1.2 lodash.merge: 4.6.2 lodash.mergewith: 4.6.2 - graphql-jit@0.8.7(graphql@16.9.0): + graphql-jit@0.8.7(graphql@16.10.0): dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) fast-json-stringify: 5.16.1 generate-function: 2.3.1 - graphql: 16.9.0 + graphql: 16.10.0 lodash.memoize: 4.1.2 lodash.merge: 4.6.2 lodash.mergewith: 4.6.2 - graphql-tag@2.12.6(graphql@16.8.0): + graphql-tag@2.12.6(graphql@16.10.0): dependencies: - graphql: 16.8.0 + graphql: 16.10.0 tslib: 2.8.1 - graphql-tag@2.12.6(graphql@16.9.0): + graphql-tag@2.12.6(graphql@16.8.0): dependencies: - graphql: 16.9.0 + graphql: 16.8.0 tslib: 2.8.1 - graphql-ws@5.16.0(graphql@16.9.0): + graphql-ws@5.16.0(graphql@16.10.0): dependencies: - graphql: 16.9.0 + graphql: 16.10.0 - graphql-yoga@5.10.5(graphql@16.9.0): + graphql-yoga@5.10.6(graphql@16.10.0): dependencies: '@envelop/core': 5.0.2 - '@graphql-tools/executor': 1.3.8(graphql@16.9.0) - '@graphql-tools/schema': 10.0.12(graphql@16.9.0) - '@graphql-tools/utils': 10.6.3(graphql@16.9.0) + '@graphql-tools/executor': 1.3.9(graphql@16.10.0) + '@graphql-tools/schema': 10.0.13(graphql@16.10.0) + '@graphql-tools/utils': 10.6.4(graphql@16.10.0) '@graphql-yoga/logger': 2.0.0 '@graphql-yoga/subscription': 5.0.2 '@whatwg-node/fetch': 0.10.1 '@whatwg-node/server': 0.9.63 dset: 3.1.4 - graphql: 16.9.0 + graphql: 16.10.0 lru-cache: 10.4.3 tslib: 2.8.1 - graphql@16.8.0: {} + graphql@16.10.0: {} - graphql@16.9.0: {} + graphql@16.8.0: {} gray-matter@4.0.3: dependencies: @@ -17998,7 +18001,7 @@ snapshots: is-boolean-object@1.2.1: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 has-tostringtag: 1.0.2 is-buffer@1.1.6: {} @@ -18017,13 +18020,13 @@ snapshots: is-data-view@1.0.2: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 get-intrinsic: 1.2.6 is-typed-array: 1.1.13 is-date-object@1.1.0: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 has-tostringtag: 1.0.2 is-decimal@1.0.4: {} @@ -18071,9 +18074,9 @@ snapshots: is-negative-zero@2.0.3: {} - is-number-object@1.1.0: + is-number-object@1.1.1: dependencies: - call-bind: 1.0.8 + call-bound: 1.0.3 has-tostringtag: 1.0.2 is-number@7.0.0: {} @@ -18098,7 +18101,7 @@ snapshots: is-regex@1.2.1: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 gopd: 1.2.0 has-tostringtag: 1.0.2 hasown: 2.0.2 @@ -18117,14 +18120,14 @@ snapshots: is-stream@3.0.0: {} - is-string@1.1.0: + is-string@1.1.1: dependencies: - call-bind: 1.0.8 + call-bound: 1.0.3 has-tostringtag: 1.0.2 is-symbol@1.1.1: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 has-symbols: 1.1.0 safe-regex-test: 1.1.0 @@ -18146,7 +18149,7 @@ snapshots: is-weakref@1.1.0: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 is-weakset@2.0.3: dependencies: @@ -18307,7 +18310,7 @@ snapshots: jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.8 - array.prototype.flat: 1.3.2 + array.prototype.flat: 1.3.3 object.assign: 4.1.5 object.values: 1.2.0 @@ -18465,7 +18468,7 @@ snapshots: dependencies: sourcemap-codec: 1.4.8 - magic-string@0.30.15: + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -19395,9 +19398,9 @@ snapshots: motion-utils@11.14.3: {} - motion@11.14.4(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + motion@11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - framer-motion: 11.14.4(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + framer-motion: 11.15.0(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tslib: 2.8.1 optionalDependencies: '@emotion/is-prop-valid': 0.8.8 @@ -19477,7 +19480,7 @@ snapshots: '@next/env': 14.2.20 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001688 + caniuse-lite: 1.0.30001689 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 @@ -19668,14 +19671,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-object-atoms: 1.0.0 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 object.values@1.2.0: dependencies: @@ -20254,7 +20257,7 @@ snapshots: react-ga4@2.1.0: {} - react-intersection-observer@9.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-intersection-observer@9.14.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 optionalDependencies: @@ -20269,24 +20272,24 @@ snapshots: react: 18.3.1 react-is: 18.3.1 - react-remove-scroll-bar@2.3.6(@types/react@18.3.16)(react@18.3.1): + react-remove-scroll-bar@2.3.8(@types/react@18.3.17)(react@18.3.1): dependencies: react: 18.3.1 - react-style-singleton: 2.2.1(@types/react@18.3.16)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.17)(react@18.3.1) tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - react-remove-scroll@2.6.0(@types/react@18.3.16)(react@18.3.1): + react-remove-scroll@2.6.0(@types/react@18.3.17)(react@18.3.1): dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.16)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.16)(react@18.3.1) + react-remove-scroll-bar: 2.3.8(@types/react@18.3.17)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.17)(react@18.3.1) tslib: 2.8.1 - use-callback-ref: 1.3.2(@types/react@18.3.16)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.16)(react@18.3.1) + use-callback-ref: 1.3.2(@types/react@18.3.17)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@18.3.17)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 react-smooth@4.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -20296,14 +20299,13 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-style-singleton@2.2.1(@types/react@18.3.16)(react@18.3.1): + react-style-singleton@2.2.3(@types/react@18.3.17)(react@18.3.1): dependencies: get-nonce: 1.0.1 - invariant: 2.2.4 react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -20402,7 +20404,7 @@ snapshots: call-bind: 1.0.8 define-properties: 1.2.1 dunder-proto: 1.0.0 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 get-intrinsic: 1.2.6 gopd: 1.2.0 @@ -20708,7 +20710,7 @@ snapshots: safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 - call-bound: 1.0.2 + call-bound: 1.0.3 get-intrinsic: 1.2.6 has-symbols: 1.1.0 isarray: 2.0.5 @@ -20719,7 +20721,7 @@ snapshots: safe-regex-test@1.1.0: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 es-errors: 1.3.0 is-regex: 1.2.1 @@ -20903,14 +20905,14 @@ snapshots: side-channel-map@1.0.1: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 es-errors: 1.3.0 get-intrinsic: 1.2.6 object-inspect: 1.13.3 side-channel-weakmap@1.0.2: dependencies: - call-bound: 1.0.2 + call-bound: 1.0.3 es-errors: 1.3.0 get-intrinsic: 1.2.6 object-inspect: 1.13.3 @@ -21092,13 +21094,13 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 es-object-atoms: 1.0.0 get-intrinsic: 1.2.6 @@ -21112,22 +21114,22 @@ snapshots: string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 - call-bound: 1.0.2 + call-bound: 1.0.3 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-object-atoms: 1.0.0 has-property-descriptors: 1.0.2 string.prototype.trimend@1.0.9: dependencies: call-bind: 1.0.8 - call-bound: 1.0.2 + call-bound: 1.0.3 define-properties: 1.2.1 es-object-atoms: 1.0.0 @@ -21243,7 +21245,7 @@ snapshots: dependencies: define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.6 es-errors: 1.3.0 function-bind: 1.1.2 globalthis: 1.0.4 @@ -21312,15 +21314,15 @@ snapshots: text-table@0.2.0: {} - theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1): + theme-ui@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1): dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.16)(react@18.3.1) - '@theme-ui/color-modes': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/components': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1))(react@18.3.1) - '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1)) - '@theme-ui/global': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) - '@theme-ui/theme-provider': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.16)(react@18.3.1))(react@18.3.1) + '@emotion/react': 11.14.0(@types/react@18.3.17)(react@18.3.1) + '@theme-ui/color-modes': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/components': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(@theme-ui/theme-provider@0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1))(react@18.3.1) + '@theme-ui/core': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/css': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1)) + '@theme-ui/global': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) + '@theme-ui/theme-provider': 0.17.1(@emotion/react@11.14.0(@types/react@18.3.17)(react@18.3.1))(react@18.3.1) react: 18.3.1 thenify-all@1.6.0: @@ -21614,12 +21616,12 @@ snapshots: ufo@1.5.4: {} - unbox-primitive@1.0.2: + unbox-primitive@1.1.0: dependencies: - call-bind: 1.0.8 + call-bound: 1.0.3 has-bigints: 1.0.2 has-symbols: 1.1.0 - which-boxed-primitive: 1.1.0 + which-boxed-primitive: 1.1.1 unc-path-regex@0.1.2: {} @@ -21843,26 +21845,26 @@ snapshots: urlpattern-polyfill@10.0.0: {} - use-callback-ref@1.3.2(@types/react@18.3.16)(react@18.3.1): + use-callback-ref@1.3.2(@types/react@18.3.17)(react@18.3.1): dependencies: react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - use-isomorphic-layout-effect@1.2.0(@types/react@18.3.16)(react@18.3.1): + use-isomorphic-layout-effect@1.2.0(@types/react@18.3.17)(react@18.3.1): dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 - use-sidecar@1.1.2(@types/react@18.3.16)(react@18.3.1): + use-sidecar@1.1.3(@types/react@18.3.17)(react@18.3.1): dependencies: detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.16 + '@types/react': 18.3.17 use-sync-external-store@1.4.0(react@18.3.1): dependencies: @@ -22001,7 +22003,7 @@ snapshots: debug: 4.4.0(supports-color@8.1.1) execa: 8.0.1 local-pkg: 0.5.1 - magic-string: 0.30.15 + magic-string: 0.30.17 pathe: 1.1.2 picocolors: 1.1.1 std-env: 3.8.0 @@ -22070,18 +22072,18 @@ snapshots: tr46: 1.0.1 webidl-conversions: 4.0.2 - which-boxed-primitive@1.1.0: + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 is-boolean-object: 1.2.1 - is-number-object: 1.1.0 - is-string: 1.1.0 + is-number-object: 1.1.1 + is-string: 1.1.1 is-symbol: 1.1.1 which-builtin-type@1.2.1: dependencies: - call-bound: 1.0.2 - function.prototype.name: 1.1.6 + call-bound: 1.0.3 + function.prototype.name: 1.1.7 has-tostringtag: 1.0.2 is-async-function: 2.0.0 is-date-object: 1.1.0 @@ -22090,7 +22092,7 @@ snapshots: is-regex: 1.2.1 is-weakref: 1.1.0 isarray: 2.0.5 - which-boxed-primitive: 1.1.0 + which-boxed-primitive: 1.1.1 which-collection: 1.0.2 which-typed-array: 1.1.16 @@ -22156,7 +22158,7 @@ snapshots: workerpool@6.5.1: {} - wrangler@3.95.0(@cloudflare/workers-types@4.20241205.0): + wrangler@3.95.0(@cloudflare/workers-types@4.20241216.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 '@cloudflare/workers-shared': 0.11.0 @@ -22177,7 +22179,7 @@ snapshots: workerd: 1.20241205.0 xxhash-wasm: 1.1.0 optionalDependencies: - '@cloudflare/workers-types': 4.20241205.0 + '@cloudflare/workers-types': 4.20241216.0 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil diff --git a/website/i18n.ts b/website/i18n.ts index 197b69b95ce1..a5fb22b6e106 100644 --- a/website/i18n.ts +++ b/website/i18n.ts @@ -6,7 +6,6 @@ import de from '@/pages/de/translations' import en from '@/pages/en/translations' import es from '@/pages/es/translations' import fr from '@/pages/fr/translations' -import ha from '@/pages/ha/translations' import hi from '@/pages/hi/translations' import it from '@/pages/it/translations' import ja from '@/pages/ja/translations' @@ -22,7 +21,6 @@ import tr from '@/pages/tr/translations' import uk from '@/pages/uk/translations' import ur from '@/pages/ur/translations' import vi from '@/pages/vi/translations' -import yo from '@/pages/yo/translations' import zh from '@/pages/zh/translations' const appLocales = [ @@ -32,7 +30,6 @@ const appLocales = [ Locale.ENGLISH, Locale.SPANISH, Locale.FRENCH, - // Locale.HAUSA, Locale.HINDI, Locale.ITALIAN, Locale.JAPANESE, @@ -48,7 +45,6 @@ const appLocales = [ // Locale.UKRAINIAN, Locale.URDU, // Locale.VIETNAMESE, - // Locale.YORUBA, Locale.CHINESE, ] as const @@ -67,7 +63,6 @@ export const translations = { en, es, fr, - ha, hi, it, ja, @@ -83,7 +78,6 @@ export const translations = { uk, ur, vi, - yo, zh, } satisfies Translations & { [key in AppLocale]: { diff --git a/website/package.json b/website/package.json index 35e25ac8485e..6c206c45492f 100644 --- a/website/package.json +++ b/website/package.json @@ -36,11 +36,11 @@ "@graphprotocol/client-cli": "3.0.3", "@types/mdast": "^4.0.4", "@types/mixpanel-browser": "^2.50.2", - "@types/react": "^18.3.16", + "@types/react": "^18.3.17", "@types/react-dom": "^18.3.5", "autoprefixer": "^10.4.20", - "fast-xml-parser": "^4.5.0", - "graphql": "^16.9.0", + "fast-xml-parser": "^4.5.1", + "graphql": "^16.10.0", "postcss": "^8.4.49", "tailwindcss": "^3.4.16", "tsx": "^4.19.2", diff --git a/website/pages/ha/_meta.js b/website/pages/ha/_meta.js deleted file mode 100644 index f2f3b56163a5..000000000000 --- a/website/pages/ha/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../en/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/about.mdx b/website/pages/ha/about.mdx deleted file mode 100644 index c1f7c886900f..000000000000 --- a/website/pages/ha/about.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: About The Graph ---- - -This page will explain what The Graph is and how you can get started. - -## What is The Graph? - -The Graph is a decentralized protocol for indexing and querying blockchain data. The Graph makes it possible to query data that is difficult to query directly. - -Projects with complex smart contracts like [Uniswap](https://uniswap.org/) and NFTs initiatives like [Bored Ape Yacht Club](https://boredapeyachtclub.com/) store data on the Ethereum blockchain, making it really difficult to read anything other than basic data directly from the blockchain. - -In the case of Bored Ape Yacht Club, we can perform basic read operations on [the contract](https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code) like getting the owner of a certain Ape, getting the content URI of an Ape based on their ID, or the total supply, as these read operations are programmed directly into the smart contract, but more advanced real-world queries and operations like aggregation, search, relationships, and non-trivial filtering are not possible. For example, if we wanted to query for apes that are owned by a certain address, and filter by one of its characteristics, we would not be able to get that information by interacting directly with the contract itself. - -To get this data, you would have to process every single [`transfer`](https://etherscan.io/address/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d#code#L1746) event ever emitted, read the metadata from IPFS using the Token ID and IPFS hash, and then aggregate it. Even for these types of relatively simple questions, it would take **hours or even days** for a decentralized application (dapp) running in a browser to get an answer. - -You could also build out your own server, process the transactions there, save them to a database, and build an API endpoint on top of it all in order to query the data. However, this option is [resource intensive](/network/benefits/), needs maintenance, presents a single point of failure, and breaks important security properties required for decentralization. - -**Indexing blockchain data is really, really hard.** - -Blockchain properties like finality, chain reorganizations, or uncled blocks complicate this process further, and make it not just time consuming but conceptually hard to retrieve correct query results from blockchain data. - -The Graph solves this with a decentralized protocol that indexes and enables the performant and efficient querying of blockchain data. These APIs (indexed "subgraphs") can then be queried with a standard GraphQL API. Today, there is a hosted service as well as a decentralized protocol with the same capabilities. Both are backed by the open source implementation of [Graph Node](https://github.com/graphprotocol/graph-node). - -## How The Graph Works - -The Graph learns what and how to index Ethereum data based on subgraph descriptions, known as the subgraph manifest. The subgraph description defines the smart contracts of interest for a subgraph, the events in those contracts to pay attention to, and how to map event data to data that The Graph will store in its database. - -Once you have written a `subgraph manifest`, you use the Graph CLI to store the definition in IPFS and tell the indexer to start indexing data for that subgraph. - -This diagram gives more detail about the flow of data once a subgraph manifest has been deployed, dealing with Ethereum transactions: - -![A graphic explaining how The Graph uses Graph Node to serve queries to data consumers](/img/graph-dataflow.png) - -The flow follows these steps: - -1. A dapp adds data to Ethereum through a transaction on a smart contract. -2. The smart contract emits one or more events while processing the transaction. -3. Graph Node continually scans Ethereum for new blocks and the data for your subgraph they may contain. -4. Graph Node finds Ethereum events for your subgraph in these blocks and runs the mapping handlers you provided. The mapping is a WASM module that creates or updates the data entities that Graph Node stores in response to Ethereum events. -5. The dapp queries the Graph Node for data indexed from the blockchain, using the node's [GraphQL endpoint](https://graphql.org/learn/). The Graph Node in turn translates the GraphQL queries into queries for its underlying data store in order to fetch this data, making use of the store's indexing capabilities. The dapp displays this data in a rich UI for end-users, which they use to issue new transactions on Ethereum. The cycle repeats. - -## Next Steps - -In the following sections we will go into more detail on how to define subgraphs, how to deploy them, and how to query data from the indexes that Graph Node builds. - -Before you start writing your own subgraph, you might want to have a look at the Graph Explorer and explore some of the subgraphs that have already been deployed. The page for each subgraph contains a playground that lets you query that subgraph's data with GraphQL. diff --git a/website/pages/ha/arbitrum/_meta.js b/website/pages/ha/arbitrum/_meta.js deleted file mode 100644 index 321fe93849be..000000000000 --- a/website/pages/ha/arbitrum/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/arbitrum/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/arbitrum/arbitrum-faq.mdx b/website/pages/ha/arbitrum/arbitrum-faq.mdx deleted file mode 100644 index 849d08c92b93..000000000000 --- a/website/pages/ha/arbitrum/arbitrum-faq.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Arbitrum FAQ ---- - -Click [here](#billing-on-arbitrum-faqs) if you would like to skip to the Arbitrum Billing FAQs. - -## Why is The Graph implementing an L2 Solution? - -By scaling The Graph on L2, network participants can expect: - -- Upwards of 26x savings on gas fees - -- Faster transaction speed - -- Security inherited from Ethereum - -Scaling the protocol smart contracts onto L2 allows network participants to interact more frequently at a reduced cost in gas fees. For example, Indexers could open and close allocations to index a greater number of subgraphs with greater frequency, developers could deploy and update subgraphs with greater ease, Delegators could delegate GRT with increased frequency, and Curators could add or remove signal to a larger number of subgraphs–actions previously considered too cost-prohibitive to perform frequently due to gas. - -The Graph community decided to move forward with Arbitrum last year after the outcome of the [GIP-0031](https://forum.thegraph.com/t/gip-0031-arbitrum-grt-bridge/3305) discussion. - -## What do I need to do to use The Graph on L2? - -Users bridge their GRT and ETH  using one of the following methods: - -- [The Graph Bridge on Arbitrum](https://bridge.arbitrum.io/?l2ChainId=42161) -- [TransferTo](https://transferto.xyz/swap) -- [Connext Bridge](https://bridge.connext.network/) -- [Hop Exchange](https://app.hop.exchange/#/send?token=ETH) - -To take advantage of using The Graph on L2, use this dropdown switcher to toggle between chains. - -![Dropdown switcher to toggle Arbitrum](/img/arbitrum-screenshot-toggle.png) - -## As a subgraph developer, data consumer, Indexer, Curator, or Delegator, what do I need to do now? - -There is no immediate action required, however, network participants are encouraged to begin moving to Arbitrum to take advantage of the benefits of L2. - -Core developer teams are working to create L2 transfer tools that will make it significantly easier to move delegation, curation, and subgraphs to Arbitrum. Network participants can expect L2 transfer tools to be available by summer of 2023. - -As of April 10th, 2023, 5% of all indexing rewards are being minted on Arbitrum. As network participation increases, and as the Council approves it, indexing rewards will gradually shift from Ethereum to Arbitrum, eventually moving entirely to Arbitrum. - -## If I would like to participate in the network on L2, what should I do? - -Please help [test the network](https://testnet.thegraph.com/explorer) on L2 and report feedback about your experience in [Discord](https://discord.gg/graphprotocol). - -## Are there any risks associated with scaling the network to L2? - -All smart contracts have been thoroughly [audited](https://github.com/graphprotocol/contracts/blob/dev/audits/OpenZeppelin/2022-07-graph-arbitrum-bridge-audit.pdf). - -Everything has been tested thoroughly, and a contingency plan is in place to ensure a safe and seamless transition. Details can be found [here](https://forum.thegraph.com/t/gip-0037-the-graph-arbitrum-deployment-with-linear-rewards-minted-in-l2/3551#risks-and-security-considerations-20). - -## Will existing subgraphs on Ethereum continue to work? - -Yes, The Graph Network contracts will operate in parallel on both Ethereum and Arbitrum until moving fully to Arbitrum at a later date. - -## Will GRT have a new smart contract deployed on Arbitrum? - -Yes, GRT has an additional [smart contract on Arbitrum](https://arbiscan.io/address/0x9623063377ad1b27544c965ccd7342f7ea7e88c7). However, the Ethereum mainnet [GRT contract](https://etherscan.io/token/0xc944e90c64b2c07662a292be6244bdf05cda44a7) will remain operational. - -## Billing on Arbitrum FAQs - -## What do I need to do about the GRT in my billing balance? - -Nothing! Your GRT has been securely migrated to Arbitrum and is being used to pay for queries as you read this. - -## How do I know my funds have migrated securely to Arbitrum? - -All GRT billing balances have already been successfully migrated to Arbitrum. You can view the billing contract on Arbitrum [here](https://arbiscan.io/address/0x1B07D3344188908Fb6DEcEac381f3eE63C48477a). - -## How do I know the Arbitrum bridge is secure? - -The bridge has been [heavily audited](https://code4rena.com/contests/2022-10-the-graph-l2-bridge-contest) to ensure safety and security for all users. - -## What do I need to do if I'm adding fresh GRT from my Ethereum mainnet wallet? - -Adding GRT to your Arbitrum billing balance can be done with a one-click experience in [Subgraph Studio](https://thegraph.com/studio/). You'll be able to easily bridge your GRT to Arbitrum and fill your API keys in one transaction. - -Visit the [Billing page](https://thegraph.com/docs/en/billing/) for more detailed instructions on adding, withdrawing, or acquiring GRT. diff --git a/website/pages/ha/arbitrum/l2-transfer-tools-faq.mdx b/website/pages/ha/arbitrum/l2-transfer-tools-faq.mdx deleted file mode 100644 index bdb0053bdc70..000000000000 --- a/website/pages/ha/arbitrum/l2-transfer-tools-faq.mdx +++ /dev/null @@ -1,411 +0,0 @@ ---- -title: L2 Transfer Tools FAQ ---- - -## General - -### What are L2 Transfer Tools? - -The Graph has made it 26x cheaper for contributors to participate in the network by deploying the protocol to Arbitrum One. The L2 Transfer Tools were created by core devs to make it easy to move to L2. - -For each network participant, a set of L2 Transfer Tools are available to make the experience seamless when moving to L2, avoiding thawing periods or having to manually withdraw and bridge GRT. - -These tools will require you to follow a specific set of steps depending on what your role is within The Graph and what you are transferring to L2. - -### Can I use the same wallet I use on Ethereum mainnet? - -If you are using an [EOA](https://ethereum.org/en/developers/docs/accounts/#types-of-account) wallet you can use the same address. If your Ethereum mainnet wallet is a contract (e.g. a multisig) then you must specify an [Arbitrum wallet address](/arbitrum/arbitrum-faq/#what-do-i-need-to-do-to-use-the-graph-on-l2) where your transfer will be sent. Please check the address carefully as any transfers to an incorrect address can result in permanent loss. If you'd like to use a multisig on L2, make sure you deploy a multisig contract on Arbitrum One. - -Wallets on EVM blockchains like Ethereum and Arbitrum are a pair of keys (public and private), that you create without any need to interact with the blockchain. So any wallet that was created for Ethereum will also work on Arbitrum without having to do anything else. - -The exception is with smart contract wallets like multisigs: these are smart contracts that are deployed separately on each chain, and get their address when they are deployed. If a multisig was deployed to Ethereum, it won't exist with the same address on Arbitrum. A new multisig must be created first on Arbitrum, and may get a different address. - -### Me zai faru idan ban gama canja wuri na ba a cikin kwanaki bakwai? - -I- Kayan aikin Canja wurin L2 suna amfani da yan qasar inji na Arbitrum don aika saƙo daga L1 zuwa a alama, duk da gada na Arbitrum a GRT. Kuna iya karanta ƙara game da tikitin sake gwadawa a cikin \[Arbitrum docs (https://docs.arbitrum.io/arbos/11-to-12-messaging). - -Lokacin da kuka canja wurin dukiyan ku (subgraph, stake, delegation or curation) zuwa L2, Ana aika sako ta gadar Arbitrum GRT wanda ke halitta da tikitin sake gwadawa a L2. Kayan aikin canja wuri ya haɗa da wasu darajar ETH a cikin ma'amala, wanda ake amfani dashi 1) biya don halitta tikitin da 2) biya gas don aiwatar da tikitin a L2. Duk da Haka, saboda farashin gas na iya bambanta a cikin lokacin har sai tikitin ya shirya don aiwatar wa a L2, mai yiyuwa ne wannan yunƙurin aiwatar da kai ya gaza.- Lokacin da wannan ya faru, gada na Arbitrum zai ci gaba da tikitin sake gwadawa da za'a iya dawowa har zuwa kwanaki bakwai, kuma kowa zai iya dawo da "fansa" tikitin (wanda ke buƙatar walat tare da wasu gada na ETH zuwa Arbitrum). - -Wannan shine abin da muke kira matakin "Tabbatar" a cikin duk kayan aikin canja wuri - zai gudu ta atomatik a mafi yawan lokuta, kamar yadda aiwatar ta atomatik ya fi yawan nasara, amma yana da mahimmanci ku sake dubawa don tabbatar da ta wuce.Idan ba ta yi nasara ba kuma ba a sami nasara sake gwadawa cikin kwanaki bakwai ba, gada Arbitrum za ta watsar da tikitin, kuma kadarorin ku (Subgraph, gungumen azaba, Delegation or curation) za su ɓace kuma ba za a iya dawo dasu baThe Graph cibiya devs suna da tsarin sa ido don gano waɗannan yanayi kuma suyi ƙoƙarin fansar tikitin kafin lokaci ya kure, amma yana da alhakin ku don tabbatar da an cikakken canja wurin ku cikin lokaci.Idan kuna fuskantar matsala don tabbatar da cinikin ku, da fatan za a tuntuɓi ta amfani da \[this form (https://noteforms.com/forms/notionform-12-transfer-tooling-issues-0ogqfu?notionforms=1&utm_source=notionforms) kuma core devs za su kasance a can suna taimaka muku. - -### Na fara kawo delegation/gargadi/curation da na samu lambar sabon hutu, kuma ban sani me yake nema da shi zuwa L2, me ya sa na iya tabbatar da cewa an gano da shi ne aiki ne? - -Idan ba ka ga talauci akan damuwan da kake bukatar tabbata ga niyyar tabbatar da shi, to a yayin da ya yi tattalin hutu damuwan ya samu wutar L2 da ba a bukatar tabbata aikin ba. Idan kuma ku duba, za ku iya duba idan tattalin delegation, gargadi, curation na dauka a Arbitrum One ta nuni. - -Idan akwai lamba na damuwan L1 (wanda za ku iya samu ta bayyana damuwa a lambar damuwa na kwanan damuwa a kofar damuwa na wallet), za ku iya tabbatar da cewa "retryable ticket" da ya dauki bayanin zuwa L2 ya samu sabon hutu a nan: https://retryable-dashboard.arbitrum.io/ - idan auto-redeem ba ya daina, za ku iya kawo lambar damuwa a nan da kuma dauko wallet na ku da aka yi redeem. Kuna da damuwa cewa matakin abubuwan da suka sauko, mai raba suna ganin su gudu, kuma za su iya dauki su kafin su gudu. - -## Canja wurin Subgraph - -### Ta yaya zan canja wurin subgraph? - - - -Don canja wurin subgraph ku, kuna buƙatar cikakken matakai masu zuwa: - -1. Fara canja wuri akan Ethereum mainnet - -2. Wait 20 minutes for confirmation - -3. Tabbatar da canja wurin subgraph akan Arbitrum - -4. Gama da bugu subgraph akan Arbitrum - -5. Sabunta URL ɗin tambaya (an shawarta) - -\*Lura cewa dole ne ka tabbatar da canja wurin a cikin kwanaki bakwai in ba haka ba za a iya rasa subgraph ku.A mafi yawan lokuta, wannan matakin zai gudu ta atomatik, amma ana iya buƙatar tabbatarwa ta hannu idan an sami hauhawar farashin gas akan Arbitrum.Idan akwai wasu batutuwa yayin wannan aikin, za a sami albarkatu don taimakawa: tuntuɓar tallafi a support@thegraph.com or on [Discord](https://discord.gg/vtvv7FP). - -### Daga ina zan fara canja wuri na? - -Kuna iya fara canja wurin ku daga wurin [Subgraph Studio](https://thegraph.com/studio/), [Explorer,](https://thegraph.com/explorer) ko kowane subgraph cikakken bayani. Danna maballin "Transfer Subgraph" a cikin cikakken bayanin subgraph don fara canja wuri. - -### Har yaushe zan jira har sai an canjawa wurin subgraph dina - -Lokacin canja wuri yana ɗaukar kusan minti ashirin. Gadar Arbitrum tana aiki a bango don cikakken canja wurin gadan ta atomatik. A wasu lokuta, farashin gas na iya ƙaruwa kuma kuna buƙatar sake tabbatar da ciniki. - -### Shin har yanzu za'a iya gano subgraph na bayan na canja wurin shi zuwa L2? - -Subgraph ɗinku za a iya gano shi kawai akan hanyar cibiyar sadarwar da aka buga zuwa. Alal misali, idan ka subgraph ne a kan Arbitrum Daya, to za ka iya kawai samun shi a Explorer a kan Arbitrum One kuma ba za su iya samun shi a kan Ethereum. Don Allah a fatan za a tabbatar cewa kana da Arbitrum Daya da aka zaɓa a cikin cibiyar sadarwa a saman shafin don tabbatar da cewa kana kan hanyar cibiyar sadarwa daidai. Bayan canja wuri, subgraph L1 zai bayyana kamar yadda aka yanke. - -### Shin yana buƙatar buga subgraph na don canja wurin shi? - -Don cin amfani kayan aikin canja wuri, subgraph naku dole ne a riga an buga shi zuwa Ethereum mainnet kuma dole ne ya sami sigina curation mallakin walat ɗin da ya mallaki subgraph. Idan ba a buga subgraph ku ba, ana ba da shawarar ku kawai ku buga kai tsaye akan Arbitrum Daya- kudaden gas masu alaƙa za su yi ƙasa sosai. Idan kuna son canja wurin subgraph aka buga amma asusun mai shi bai curated wata sigina akansa ba, zaku iya sigina ƙaramin adadin (e.g.1 GRT) daga wannan asusun; tabbatar da zaba sigina "auto-migrating". - -### Me zai faru da sigar na Ethereum mainnet akan subgraph bayan na canja wurin zuwa Arbitrum? - -Bayan canja wurin subgraph zuwa Arbitrum, sigar mainnet Ethereum za ta ƙare. Muna ba da shawarar ku sabunta URL ɗin tambayar ku a cikin awanni arba'in da takwas. Duk da Haka, akwai lokacin alheri a wurin da ke kiyaye mainnet URL ɗin ku don a iya sabunta kowane tallafin dapp na ɓangare na uku. - -### Bayan na canja wurin, shin ina kuma buƙatar sake bugawa akan Arbitrum? - -Bayan taga canja wurin minti ashirin, kuna buƙatar tabbatar da canja wuri tare da ma'amala a cikin UI don gama canja wurin, amma kayan aikin canja wuri zai shiryar ku ta wannan. Za a ci gaba da samun goyan bayan ƙarshen L1 ɗinku yayin taga canja wuri da lokacin alheri bayan. Ana ƙarfafa ka sabunta ƙarshen ƙarshen lokacin da ya dace da kai. - -### Shin za a sami ƙarancin lokaci zuwa ƙarshen ƙarshena yayin sake bugawa? - -It is unlikely, but possible to experience a brief downtime depending on which Indexers are supporting the subgraph on L1 and whether they keep indexing it until the subgraph is fully supported on L2. - -### Shin bugu da sigar iri ɗaya ne akan L2 Ethereum mainnet? - -Tabbatar da zaɓin Arbitrum Days azaman hanyar cibiyar sadarwar ku da aka buga lokacin bugawa a Studio Subgraph. A cikin Studio, sabon wurin ƙarshe zai kasance wanda ke nuna sabon sigar subgraph. - -### Shin subgraph na curation zai motsa da subgraph nawa? - -Idan kun zaba sigina ƙaura ta atomatik, 100% na curation ku zai matsa tare da subgraph zuwa Arbitrum Daya. Duk sigina curation na subgraph za a canja shi zuwa GRT a lokacin canja wuri, kuma GRT ɗin da ke daidai da sigina curation ɗin ku za a yi amfani da shi don mint sigina akan subgraph L2. - -Sauran Curators na iya zaɓar ko za su janye sulusi da murabba'i na GRT, ko kuma su tura shi zuwa L2 zuwa sigina mint akan wannan subgraph. - -### Zan iya matsar da subgraph na zuwa Ethereum mainnet bayan na canja wurin? - -Da zarar an canjawa wuri, za a soke sigar subgraph ku na Ethereum mainnet. Idan kuna son komawa zuwa mainnet, kuna buƙatar sake aiki da buga baya zuwa mainnet. Duk da Haka, komawa zuwa Ethereum mainnet yana da ƙarfi sosai saboda za a rarraba ladan indexing gaba ɗaya akan Arbitrum Daya. - -### Me yasa nake buƙatar gada ETH don cikakken canja wuri na? - -Ana biyan kuɗin gas akan Arbitrum Daya ta hanyar amfani da gada ETH (i.e. watau ETH wanda aka gada haɗa zuwa Arbitrum One) Duk da haka, biyan kudi gas ya ragu sosai idan aka kwatanta da Ethereum mainnet. - -## Delegation - -### Ta yaya zan canja wurin delegation na? - - - -Don canja wurin delegation ku, kuna buƙatar cikakken matakai masu zuwa: - -1. Fara canja wurin delegation akan Ethereum mainnet -2. Wait 20 minutes for confirmation -3. Tabbatar da canja wurin delegation akan Arbitrum - -\*\*\*\*Dole ne ku tabbatar da ma'amala don cikakken canja wuri delegation akan Arbitrum. Dole ne a cikakken wannan matakin a cikin kwanaki bakwai ko kuma a rasa delegation.A mafi yawan lokuta, wannan matakin zai gudu ta atomatik, amma ana yin buƙatar tabbatarwa ta hannu idan akwai tashin farashin gas akan Arbitrum.Idan akwai wasu batutuwa yayin wannan tsari, za a sami albarkatu don taimakawa: tuntuɓar tallafi a tallafi@thegraph.com or on [Discord](https://discord.gg/vtvv7FP). - -### Menene zai faru da lada na idan na fara canja wuri tare da buɗe kasafi akan Ethereum mainnet? - -Idan indexer wanda kuke delegating yana ci gaba da aiki akan L1, lokacin da kuka canja wurin zuwa Arbitrum zaku rasa duk wani ladan delegation daga buɗe kasafi akan Ethereum mainnet. Wannan yana nufin cewa za ku rasa lada daga, a mafi yawan, kwanakin ashirin da takwas na ƙarshe. Idan kun sanya lokacin canja wuri daidai bayan indexer ya rufe kasafi za ku iya tabbatar da wannan shine mafi ƙarancin adadin da zai yiwu. Idan kuna da tashar sadarwa tare da indexer(s), yi la'akari da tattauna da su don nemo mafi kyau lokacin canja wurin ku. - -### Menene zai faru idan Indexer da nake delegate a halin yanzu baya kan Arbitrum One? - -Za a kunna kayan aikin canja wurin L2 ne kawai idan Indexer da kuka delegated ya canjawa wuri nasu stake zuwa Arbitrum. - -### Shin Delegators suna da zaɓi don delegate zuwa wani Indexer? - -Idan kuna son delegate zuwa wani Indexer, zaku iya canja wurin zuwa mai indexer iri ɗaya akan Arbitrum, sannan undelegate kuma ku jira lokacin narkewa. Bayan wannan, zaku iya zaɓar wani Indexer mai aiki don delegate zuwa. - -### Idan na kasa samun Indexer da nake delegating akan L2 fa? - -Kayan aikin Canja wurin L2 zai gani Indexer ta atomatik wanda kuka delegated a baya. - -### Shin zan iya haɗawa da wasa ko 'baza' delegation a kan sabo ko da yawa Indexers maimakon Indexers da ta gaba? - -Kayan aikin canja wurin L2 koyaushe zai motsa delegation ku zuwa Indexer iri ɗaya da kuka delegated a baya. Da zarar kun ƙoma zuwa L2, zaku iya undelegate, jira lokacin narkewa, sannan ku yanke shawara idan kuna son raba delegation ku. - -### Shin ina batun lokacin kwantar da hankali ko zan iya janyewa nan da nan bayan amfani da kayan aikin canja wuri delegation L2? - -Kayan aikin canja wuri yana ba ku damar matsawa zuwa L2 nan da nan. Idan kuna son undelegate za ku jira lokacin narkewa. Duk da Haka, idan Indexer ya canjawa wuri stake din su zuwa L2, zaku iya janye kan Ethereum mainnet nan da nan. - -### Shin za a iya yin barnatar tasiri ga lada na idan ban canja wurin delegation na ba? - -Ana sa ran cewa duk haɗin sa hannu cibiyar sadarwa zai matsa zuwa Arbitrum One a nan gaba. - -### Tsawon wane lokaci ake ɗauka kafin a cikakken canja wurin delegation na zuwa L2? - -Ana buƙatar tabbatarwa na minti ashirin don canja wurin delegation. Lura cewa bayan lokacin minti ashirin, dole ne ku dawo kuma ku cikakken mataki na uku na tsarin canja wuri a cikin kwanaki bakwai.Idan kun kasa yin wannan, delegation ku na iya ɓacewa. Lura cewa a mafi yawan lokuta kayan aikin canja wuri zai cikakken muku wannan matakin ta atomatik.Idan an kaza ƙoƙarin yin-kai, kuna buƙatar cikakken shi da hannu. Idan wata matsala ta taso yayin wannan aikin, kada ku damu, za mu kasance a nan don taimakawa: tuntuɓe mu a support@thegraph.com ko a kunne.[Discord] \(https://discord.gg/graphprotocol). - -### Zan iya canja wurin delegation ta idan ina amfani da kwangila na vesting GRT/walat kulle alama? - -Ee! Tsarin ya ɗan bambanta saboda kwangila na vesting ba zai iya tura ETH da ake buƙata don biyan L2 gas ba, don haka kuna buƙatar saka shi tukuna. Idan kwangila ku na vesting ba ta cika ba, za ku fara kwangila akan L2 vesting kuma kawai za ku iya canja wurin delegation zuwa wannan kwangila hannun L2. UI akan Explorer zai iya shiryar ku ta wannan tsari lokacin da kuka haɗa zuwa Explorer ta amfani da walat ɗin kulle vesting. - -### Does my Arbitrum vesting contract allow releasing GRT just like on mainnet? - -No, the vesting contract that is created on Arbitrum will not allow releasing any GRT until the end of the vesting timeline, i.e. until your contract is fully vested. This is to prevent double spending, as otherwise it would be possible to release the same amounts on both layers. - -If you'd like to release GRT from the vesting contract, you can transfer them back to the L1 vesting contract using Explorer: in your Arbitrum One profile, you will see a banner saying you can transfer GRT back to the mainnet vesting contract. This requires a transaction on Arbitrum One, waiting 7 days, and a final transaction on mainnet, as it uses the same native bridging mechanism from the GRT bridge. - -### Akwai wani harajin delegation? - -A'a. Ana ba da alamun da aka karɓa akan L2 zuwa ajali Indexer a madadin ajali Delegator ba tare da caji harajin wakilai ba. - -### Will my unrealized rewards be transferred when I transfer my delegation? - -​Yes! The only rewards that can't be transferred are the ones for open allocations, as those won't exist until the Indexer closes the allocations (usually every 28 days). If you've been delegating for a while, this is likely only a small fraction of rewards. - -At the smart contract level, unrealized rewards are already part of your delegation balance, so they will be transferred when you transfer your delegation to L2. ​ - -### Is moving delegations to L2 mandatory? Is there a deadline? - -​Moving delegation to L2 is not mandatory, but indexing rewards are increasing on L2 following the timeline described in [GIP-0052](https://forum.thegraph.com/t/gip-0052-timeline-and-requirements-to-increase-rewards-in-l2/4193). Eventually, if the Council keeps approving the increases, all rewards will be distributed in L2 and there will be no indexing rewards for Indexers and Delegators on L1. ​ - -### If I am delegating to an Indexer that has already transferred stake to L2, do I stop receiving rewards on L1? - -​Many Indexers are transferring stake gradually so Indexers on L1 will still be earning rewards and fees on L1, which are then shared with Delegators. Once an Indexer has transferred all of their stake, then they will stop operating on L1, so Delegators will not receive any more rewards unless they transfer to L2. - -Eventually, if the Council keeps approving the indexing rewards increases in L2, all rewards will be distributed on L2 and there will be no indexing rewards for Indexers and Delegators on L1. ​ - -### I don't see a button to transfer my delegation. Why is that? - -​Your Indexer has probably not used the L2 transfer tools to transfer stake yet. - -If you can contact the Indexer, you can encourage them to use the L2 Transfer Tools so that Delegators can transfer delegations to their L2 Indexer address. ​ - -### My Indexer is also on Arbitrum, but I don't see a button to transfer the delegation in my profile. Why is that? - -​It is possible that the Indexer has set up operations on L2, but hasn't used the L2 transfer tools to transfer stake. The L1 smart contracts will therefore not know about the Indexer's L2 address. If you can contact the Indexer, you can encourage them to use the transfer tool so that Delegators can transfer delegations to their L2 Indexer address. ​ - -### Can I transfer my delegation to L2 if I have started the undelegating process and haven't withdrawn it yet? - -​No. If your delegation is thawing, you have to wait the 28 days and withdraw it. - -The tokens that are being undelegated are "locked" and therefore cannot be transferred to L2. - -## Curation Signal - -### Ta yaya zan canja wurin curation na? - -Fara canja wurin sigina akan Ethereum mainnet: - -1. Fara canja wurin sigina akan Ethereum mainnet - -2. Saka adireshin L2 Curator - -3. Wait 20 minutes for confirmation - -\*Idan ya wajibi-i.e. kana amfani da adireshin kwangila. - -### Ta yaya zan san idan subgraph da na curated ya koma L2? - -Lokacin duba cikakken bayanin shafi na subgraph, banner zai sanar da kai cewa an canja wurin wannan subgraph. Kuna iya bin saƙon don canja wurin curation ku. Hakanan zaka iya samun wannan bayanin na subgraph akan cikakken subgraph na kowane da ya motsa. - -### Idan bana so in matsar da curation na zuwa L2 fa? - -Lokacin da subgraph ya ƙare kuna da zazi don janye sigina ku. Kamar wancan, idan subgraph ya koma L2, zaku iya zaɓa janye sigina ku a cikin Ethereum mainnet ko aika sigina zuwa L2. - -### Ta yaya zan san curation na cikin nasarar canjawa wuri? - -Cikakkun bayani na sigina za a sami ta hanyar Explorer kamar minti ashirin bayan an qaddamar da kayan aikin canja wurin L2. - -### Zan iya canja wurin curation na akan fiye subgraph ɗaya a lokaci guda? - -Babu zaɓin canja wuri mai yawa a wannan lokacin. - -## Indexer gungumen azaba - -### Ta yaya zan canja wuri gugumen azaba na zuwa Arbitrum? - -> Disclaimer: Idan a halin yanzu kuna kwance kowane yanki na GRT ɗinku akan Indexer ɗinku, ba za ku iya amfani da Kayan aikin Canja wurin L2 ba. - - - -Don canja wurin stake, kuna buƙatar cikakken matakai masu zuwa: - -1. Fara canja wurin stake akan Ethereum mainnet - -2. Wait 20 minutes for confirmation - -3. Tabbatar da canja wurin stake akan Arbitrum - -Lura cewa dole ne ku tabbatar da canja wurin a cikin kwanaki bakwai in ba haka ba na iya rasa stake. A mafi yawan lokuta, wannan matakin zai gudi ta atomatik, amma ana iya buƙatar tabbatarwa ta hannu idan akwai tashin farashin gas akan Arbitrum. Idan akwai wasu batutuwa yayin wannan tsari, za a sami albarkatu don taimakawa: tuntuɓar tallafi a tallafi@thegraph.com or on [Discord](https://discord.gg/vtvv7FP). - -### Duk stake na za a canja wuri? - -Kuna iya zaɓa nawa na stake don canja wurin. Idan ka zaɓa canja wurin duk stake din ku a lokaci ɗaya, kuna buƙatar rufe duk wani buɗaɗɗen kasafi da farko. - -Idan kuna shirin canja wurin sassa stake din ku akan ma'amaloli da yawa, dole ne ku saka adireshin mai amfana koyaushe. - -Dole ne ku cika minimum buƙatun stake akan L2 a karon farko da kuka yi amfani da kayan aikin canja wuri. Dole ne Indexers su aika minimum 100k GRT (lokacin kiran wannan aikin a karon farko). Idan barin wani yanki na stake akan L1, dole ne kuma ya wuce minimum 100k GRT kuma ya isa (tare da delegations ku) don rufe kasafi da kuke buɗe. - -### Yaya tsawon lokaci zan tabbatar da canja wurin stake na zuwa Arbitrum? - -\*\*\* Dole ne ku tabbatar da ma’amala ku don cikakken canja wurin stake akan Arbitrum. Dole ne a cikakken wannan matakin a cikin kwanaki bakwai ko kuma za a iya stake. - -### Idan ina da buɗaɗɗen kasafi? - -Idan ba ku aika duk stake ba, kayan aikin canja wuri na L2 zai tabbatar da cewa kadan minimum 100k GRT ya rage a cikin Ethereum mainnet kuma ragowar stake din ku da delegation sun isa su rufe duk wani buɗaɗɗen kasafi. Kuna iya buƙatar rufe kasafi buɗewa idan ma'auni na GRT ɗinku bai rufe minimums kasafi buɗewa ba. - -### Yin amfani da kayan aikin canja wuri, shin ya zama dole a jira kwanaki ashirin da takwas don unstake akan Ethereum mainnet kafin canja wurin? - -A'a, zaku iya canja wurin stake zuwa L2 nan da nan, babu buƙatar unstake kuma jira kafin amfani da kayan aikin canja wuri. Jiran kwana ashirin da takwas ya shafi kawai idan kuna son janye stake zuwa walat ɗin ku, akan Ethereum mainnet ko L2. - -### Yaya tsawon lokacin da za a ɗauka don canja wurin stake na? - -Zai ɗauki kusan minti ashirin don kayan aikin canja wuri na L2 don cikakken canja wurin stake ku. - -### Shin dole ne in yi index akan Arbitrum kafin in canja wuri stake na? - -Kuna iya fara canja wurin stake na ku yadda ya kamata kafin kafa indexing, amma ba za ku iya neman kowane lada akan L2 ba har sai kun ware subgraghs akan L2, index su, da ba POIs. - -### Delegators za su iya motsa delegation sun kafin in motsa indexing stake na? - -A'a, domin Delegators su canja wurin GRT da aka delegated zuwa Arbitrum, Indexer da suke delegating dole ne yayi aiki akan L2. - -### Zan iya canja wurin stake na idan ina amfani da kwangila na vesting na GRT/walat ɗin kulle alama? - -Ee! Tsarin yana ɗa bambanta, saboda kwangila na vesting bai iya tura ETH gaba ɗin da ake buƙata don biyan kuɗin gas na L2 ba, don haka kuna buƙatar saka shi tukuna. Idan kwangila na vesting ba ta cika ba, za ku kuma fara kwangila na vesting sa hannun takwaran vesting akan L2 kuma kawai za ku iya canja wurin stake zuwa wannan kwangila sanya hannun L2 vesting. UI akan Explorer na iya shiryar ku ta wannan tsari lokacin da kuka haɗa zuwa Explorer ta amfani da walat ɗin kulle vesting. - -### I already have stake on L2. Do I still need to send 100k GRT when I use the transfer tools the first time? - -​Yes. The L1 smart contracts will not be aware of your L2 stake, so they will require you to transfer at least 100k GRT when you transfer for the first time. ​ - -### Can I transfer my stake to L2 if I am in the process of unstaking GRT? - -​No. If any fraction of your stake is thawing, you have to wait the 28 days and withdraw it before you can transfer stake. The tokens that are being staked are "locked" and will prevent any transfers or stake to L2. - -## Canja wurin Kwangila Vesting - -### Ta yaya zan canza wurin kwangila na vesting na? - -Don canja wurin vesting ku, kuna buƙatar kammala matakai masu zuwa: - -1. Fara da vesting na canja wuri Ethereum mainnet - -2. Wait 20 minutes for confirmation - -3. Tabbatar da vesting na canja wuri a kan Arbitrum - -### Ta yaya zan canza wurin kwangila na vesting na idan an ba ni wani bangare kawai? - - - -1. Sanya wasu ETH a cikin kwangila kayan aikin canja wuri (UI zai iya taimaka wajen adadin kuɗi) - -2. Aika wasu GRT da aka kulle ta hanyar kwangila kayan aikin canja wuri, zuwa L2 don fara kulle L2 a vesting. Wannan kuma zai saita adireshin masu cin amfani L2. - -3. Aika stake / delegation zuwa L2 ta hanyar "kulle" ayyuka kayan aikin canja wuri a cikin kwangila Staking na L1. - -4. Jare duk saura ETH daga kwangila kayan aikin canja wuri - -### Ta yaya zan canja wurin kwangila na vesting idan na cika? - - - -Domin waɗan ke cikakken vested, tsarin yana kama da haka: - -1. Sanya wasu ETH a cikin kwangila kayan aikin canja wuri (UI zai iya taimaka wajen adadin kuɗi) - -2. Saita adireshin L2 ɗinku tare da kira zuwa kwangila kayan aikin canja wuri - -3. Aika stake / delegation ku zuwa L2 ta hanyar "kulle" ayyuka kayan aikin canja wuri a cikin kwangila Staking na L1. - -4. Jare duk saura ETH daga kwangila kayan aikin canja wuri - -### Zan iya canza wurin kwangila na vesting nawa zuwa Arbitrum? - -Kuna iya canja wurin ma'auni na GRT kwangila na vesting ku zuwa kwangilar a cikin L2. Wannan abin da ake bukata ne don canja wurin stake ko delegation daga kwangila na vesting zuwa L2. Dole ne kwangila na vesting ta riƙe adadin GRT mara sifili (zaku iya canja wurin ƙaramin adadin kamar GRT daya zuwa gare shi idan an buƙata). - -Lokacin da ka canja wurin GRT daga kwangila na vesting na L1 zuwa L2, za ka iya zaɓar adadin da za ka aika kuma za ka iya yin haka sau da yawa yadda kake so. Za a fara vesting da kwangilar na L2 a farkon lokacin da kuka canja wurin GRT. - -Ana yin canja wurin ta amfani da Kayan aikin Canja wurin da za a iya gani akan Explorer profile lokacin da kuka haɗa tare da asusun kwangila na vesting. - -Don Allah za a lura cewa ba za ku iya sakin / janye GRT daga kwangila na vesting na L2 ba har zuwa ƙarshen lokacin vesting ku da kwangila ta cika. Idan kuna buƙatar sakin GRT kafin wannan lokacin, zaku iya canja wurin GRT zuwa kwangila na vesting ta L1 ta amfani da wani kayan aikin canja wuri wanda yake akwai don wannan dalili. - -Idan baku canza ma'aunin kwangila na vesting ba zuwa L2, kuma kwangila ku na vesting da cikakkiyar vested, bai kamata ku canza wurin kwangila na vesting ku zuwa L2 ba. Madadin haka, zaku iya amfani da kayan aikin canja wuri don saita adireshin L2 walat, da kuma canja wurin stake ko delegation zuwa wannan walat na yau da kullun akan L2. - -### Ina amfani da kwangila na vesting akan mainnet don stake. Zan iya canja wuri stake na zuwa Arbitrum? - -Ee, amma idan har yanzu kwangila ku tana ci gaba, zaku iya canja wurin stake domin ya zama mallakin kwangila na vesting ku na L2. Dole ne ku fara wannan kwangila L2 ta hanyar canja wurin wasu ma'auni na GRT ta amfani da kayan aikin canja wurin kwangila na vesting a kan Explorer. Idan kwangila ku ta cika vested, za ku iya canja wurin stake din ku zuwa kowane adireshi a cikin L2, amma dole ne ku saita shi a gaba kuma ku saka wasu ETH don kayan aikin canja wuri na L2 don biyan gas na L2. - -### I'm using my vesting contract to delegate on mainnet. Can I transfer my delegations to Arbitrum? - -Yes, but if your contract is still vesting, you can only transfer the delegation so that it is owned by your L2 vesting contract. You must first initialize this L2 contract by transferring some GRT balance using the vesting contract transfer tool on Explorer. If your contract is fully vested, you can transfer your delegation to any address in L2, but you must set it beforehand and deposit some ETH for the L2 transfer tool to pay for L2 gas. - -### Can I specify a different beneficiary for my vesting contract on L2? - -Yes, the first time you transfer a balance and set up your L2 vesting contract, you can specify an L2 beneficiary. Make sure this beneficiary is a wallet that can perform transactions on Arbitrum One, i.e. it must be an EOA or a multisig deployed to Arbitrum One. - -If your contract is fully vested, you will not set up a vesting contract on L2; instead, you will set an L2 wallet address and this will be the receiving wallet for your stake or delegation on Arbitrum. - -### My contract is fully vested. Can I transfer my stake or delegation to another address that is not an L2 vesting contract? - -Yes. If you haven't transferred any vesting contract balance to L2, and your vesting contract is fully vested, you should not transfer your vesting contract to L2. Instead, you can use the transfer tools to set an L2 wallet address, and directly transfer your stake or delegation to this regular wallet on L2. - -This allows you to transfer your stake or delegation to any L2 address. - -### My vesting contract is still vesting. How do I transfer my vesting contract balance to L2? - -These steps only apply if your contract is still vesting, or if you've used this process before when your contract was still vesting. - -To transfer your vesting contract to L2, you will send any GRT balance to L2 using the transfer tools, which will initialize your L2 vesting contract: - -1. Deposit some ETH into the transfer tool contract (this will be used to pay for L2 gas) - -2. Revoke protocol access to the vesting contract (needed for the next step) - -3. Give protocol access to the vesting contract (will allow your contract to interact with the transfer tool) - -4. Specify an L2 beneficiary address\* and initiate the balance transfer on Ethereum mainnet - -5. Wait 20 minutes for confirmation - -6. Confirm the balance transfer on L2 - -\*Idan ya wajibi-i.e. kana amfani da adireshin kwangila. - -\*\*\*\*You must confirm your transaction to complete the balance transfer on Arbitrum. This step must be completed within 7 days or the balance could be lost. In most cases, this step will run automatically, but a manual confirmation may be needed if there is a gas price spike on Arbitrum. If there are any issues during this process, there will be resources to help: contact support at support@thegraph.com or on [Discord](https://discord.gg/graphprotocol). - -### My vesting contract shows 0 GRT so I cannot transfer it, why is this and how do I fix it? - -​To initialize your L2 vesting contract, you need to transfer a nonzero amount of GRT to L2. This is required by the Arbitrum GRT bridge that is used by the L2 Transfer Tools. The GRT must come from the vesting contract's balance, so it does not include staked or delegated GRT. - -If you've staked or delegated all your GRT from the vesting contract, you can manually send a small amount like 1 GRT to the vesting contract address from anywhere else (e.g. from another wallet, or an exchange). ​ - -### I am using a vesting contract to stake or delegate, but I don't see a button to transfer my stake or delegation to L2, what do I do? - -​If your vesting contract hasn't finished vesting, you need to first create an L2 vesting contract that will receive your stake or delegation on L2. This vesting contract will not allow releasing tokens in L2 until the end of the vesting timeline, but will allow you to transfer GRT back to the L1 vesting contract to be released there. - -When connected with the vesting contract on Explorer, you should see a button to initialize your L2 vesting contract. Follow that process first, and you will then see the buttons to transfer your stake or delegation in your profile. ​ - -### If I initialize my L2 vesting contract, will this also transfer my delegation to L2 automatically? - -​No, initializing your L2 vesting contract is a prerequisite for transferring stake or delegation from the vesting contract, but you still need to transfer these separately. - -You will see a banner on your profile prompting you to transfer your stake or delegation after you have initialized your L2 vesting contract. - -### Can I move my vesting contract back to L1? - -There is no need to do so because your vesting contract is still in L1. When you use the transfer tools, you just create a new contract in L2 that is connected with your L1 vesting contract, and you can send GRT back and forth between the two. - -### Why do I need to move my vesting contract to begin with? - -You need to set up an L2 vesting contract so that this account can own your stake or delegation on L2. Otherwise, there'd be no way for you to transfer the stake/delegation to L2 without "escaping" the vesting contract. - -### What happens if I try to cash out my contract when it is only partially vested? Is this possible? - -This is not a possibility. You can move funds back to L1 and withdraw them there. - -### What if I don't want to move my vesting contract to L2? - -You can keep staking/delegating on L1. Over time, you may want to consider moving to L2 to enable rewards there as the protocol scales on Arbitrum. Note that these transfer tools are for vesting contracts that are allowed to stake and delegate in the protocol. If your contract does not allow staking or delegating, or is revocable, then there is no transfer tool available. You will still be able to withdraw your GRT from L1 when available. diff --git a/website/pages/ha/arbitrum/l2-transfer-tools-guide.mdx b/website/pages/ha/arbitrum/l2-transfer-tools-guide.mdx deleted file mode 100644 index ebaca7d1a7e6..000000000000 --- a/website/pages/ha/arbitrum/l2-transfer-tools-guide.mdx +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: L2 Transfer Tools Guide ---- - -The Graph has made it easy to move to L2 on Arbitrum One. For each protocol participant, there are a set of L2 Transfer Tools to make transferring to L2 seamless for all network participants. These tools will require you to follow a specific set of steps depending on what you are transferring. - -Some frequent questions about these tools are answered in the [L2 Transfer Tools FAQ](/arbitrum/l2-transfer-tools-faq). The FAQs contain in-depth explanations of how to use the tools, how they work, and things to keep in mind when using them. - -## How to transfer your subgraph to Arbitrum (L2) - - - -## Benefits of transferring your subgraphs - -The Graph's community and core devs have [been preparing](https://forum.thegraph.com/t/gip-0031-arbitrum-grt-bridge/3305) to move to Arbitrum over the past year. Arbitrum, a layer 2 or "L2" blockchain, inherits the security from Ethereum but provides drastically lower gas fees. - -When you publish or upgrade your subgraph to The Graph Network, you're interacting with smart contracts on the protocol and this requires paying for gas using ETH. By moving your subgraphs to Arbitrum, any future updates to your subgraph will require much lower gas fees. The lower fees, and the fact that curation bonding curves on L2 are flat, also make it easier for other Curators to curate on your subgraph, increasing the rewards for Indexers on your subgraph. This lower-cost environment also makes it cheaper for Indexers to index and serve your subgraph. Indexing rewards will be increasing on Arbitrum and decreasing on Ethereum mainnet over the coming months, so more and more Indexers will be transferring their stake and setting up their operations on L2. - -## Understanding what happens with signal, your L1 subgraph and query URLs - -Transferring a subgraph to Arbitrum uses the Arbitrum GRT bridge, which in turn uses the native Arbitrum bridge, to send the subgraph to L2. The "transfer" will deprecate the subgraph on mainnet and send the information to re-create the subgraph on L2 using the bridge. It will also include the subgraph owner's signaled GRT, which must be more than zero for the bridge to accept the transfer. - -When you choose to transfer the subgraph, this will convert all of the subgraph's curation signal to GRT. This is equivalent to "deprecating" the subgraph on mainnet. The GRT corresponding to your curation will be sent to L2 together with the subgraph, where they will be used to mint signal on your behalf. - -Other Curators can choose whether to withdraw their fraction of GRT, or also transfer it to L2 to mint signal on the same subgraph. If a subgraph owner does not transfer their subgraph to L2 and manually deprecates it via a contract call, then Curators will be notified and will be able to withdraw their curation. - -As soon as the subgraph is transferred, since all curation is converted to GRT, Indexers will no longer receive rewards for indexing the subgraph. However, there will be Indexers that will 1) keep serving transferred subgraphs for 24 hours, and 2) immediately start indexing the subgraph on L2. Since these Indexers already have the subgraph indexed, there should be no need to wait for the subgraph to sync, and it will be possible to query the L2 subgraph almost immediately. - -Queries to the L2 subgraph will need to be done to a different URL (on `arbitrum-gateway.thegraph.com`), but the L1 URL will continue working for at least 48 hours. After that, the L1 gateway will forward queries to the L2 gateway (for some time), but this will add latency so it is recommended to switch all your queries to the new URL as soon as possible. - -## Choosing your L2 wallet - -When you published your subgraph on mainnet, you used a connected wallet to create the subgraph, and this wallet owns the NFT that represents this subgraph and allows you to publish updates. - -When transferring the subgraph to Arbitrum, you can choose a different wallet that will own this subgraph NFT on L2. - -If you're using a "regular" wallet like MetaMask (an Externally Owned Account or EOA, i.e. a wallet that is not a smart contract), then this is optional and it is recommended to keep the same owner address as in L1. - -If you're using a smart contract wallet, like a multisig (e.g. a Safe), then choosing a different L2 wallet address is mandatory, as it is most likely that this account only exists on mainnet and you will not be able to make transactions on Arbitrum using this wallet. If you want to keep using a smart contract wallet or multisig, create a new wallet on Arbitrum and use its address as the L2 owner of your subgraph. - -**It is very important to use a wallet address that you control, and that can make transactions on Arbitrum. Otherwise, the subgraph will be lost and cannot be recovered.** - -## Preparing for the transfer: bridging some ETH - -Transferring the subgraph involves sending a transaction through the bridge, and then executing another transaction on Arbitrum. The first transaction uses ETH on mainnet, and includes some ETH to pay for gas when the message is received on L2. However, if this gas is insufficient, you will have to retry the transaction and pay for the gas directly on L2 (this is "Step 3: Confirming the transfer" below). This step **must be executed within 7 days of starting the transfer**. Moreover, the second transaction ("Step 4: Finishing the transfer on L2") will be done directly on Arbitrum. For these reasons, you will need some ETH on an Arbitrum wallet. If you're using a multisig or smart contract account, the ETH will need to be in the regular (EOA) wallet that you are using to execute the transactions, not on the multisig wallet itself. - -You can buy ETH on some exchanges and withdraw it directly to Arbitrum, or you can use the Arbitrum bridge to send ETH from a mainnet wallet to L2: [bridge.arbitrum.io](http://bridge.arbitrum.io). Since gas fees on Arbitrum are lower, you should only need a small amount. It is recommended that you start at a low threshold (0.e.g. 01 ETH) for your transaction to be approved. - -## Finding the subgraph Transfer Tool - -You can find the L2 Transfer Tool when you're looking at your subgraph's page on Subgraph Studio: - -![transfer tool](/img/L2-transfer-tool1.png) - -It is also available on Explorer if you're connected with the wallet that owns a subgraph and on that subgraph's page on Explorer: - -![Transferring to L2](/img/transferToL2.png) - -Clicking on the Transfer to L2 button will open the transfer tool where you can start the transfer process. - -## Step 1: Starting the transfer - -Before starting the transfer, you must decide which address will own the subgraph on L2 (see "Choosing your L2 wallet" above), and it is strongly recommend having some ETH for gas already bridged on Arbitrum (see "Preparing for the transfer: bridging some ETH" above). - -Also please note transferring the subgraph requires having a nonzero amount of signal on the subgraph with the same account that owns the subgraph; if you haven't signaled on the subgraph you will have to add a bit of curation (adding a small amount like 1 GRT would suffice). - -After opening the Transfer Tool, you will be able to input the L2 wallet address into the "Receiving wallet address" field - **make sure you've entered the correct address here**. Clicking on Transfer Subgraph will prompt you to execute the transaction on your wallet (note some ETH value is included to pay for L2 gas); this will initiate the transfer and deprecate your L1 subgraph (see "Understanding what happens with signal, your L1 subgraph and query URLs" above for more details on what goes on behind the scenes). - -If you execute this step, **make sure you proceed until completing step 3 in less than 7 days, or the subgraph and your signal GRT will be lost.** This is due to how L1-L2 messaging works on Arbitrum: messages that are sent through the bridge are "retry-able tickets" that must be executed within 7 days, and the initial execution might need a retry if there are spikes in the gas price on Arbitrum. - -![Start the trnasfer to L2](/img/startTransferL2.png) - -## Step 2: Waiting for the subgraph to get to L2 - -After you start the transfer, the message that sends your L1 subgraph to L2 must propagate through the Arbitrum bridge. This takes approximately 20 minutes (the bridge waits for the mainnet block containing the transaction to be "safe" from potential chain reorgs). - -Da zarar wannan lokacin jira ya ƙare, Arbitrum zai yi ƙoƙarin aiwatar da canja wurin kai tsaye akan kwangila L2. - -![Wait screen](/img/screenshotOfWaitScreenL2.png) - -## Step 3: Confirming the transfer - -In most cases, this step will auto-execute as the L2 gas included in step 1 should be sufficient to execute the transaction that receives the subgraph on the Arbitrum contracts. In some cases, however, it is possible that a spike in gas prices on Arbitrum causes this auto-execution to fail. In this case, the "ticket" that sends your subgraph to L2 will be pending and require a retry within 7 days. - -If this is the case, you will need to connect using an L2 wallet that has some ETH on Arbitrum, switch your wallet network to Arbitrum, and click on "Confirm Transfer" to retry the transaction. - -![Confirm the transfer to L2](/img/confirmTransferToL2.png) - -## Step 4: Finishing the transfer on L2 - -At this point, your subgraph and GRT have been received on Arbitrum, but the subgraph is not published yet. You will need to connect using the L2 wallet that you chose as the receiving wallet, switch your wallet network to Arbitrum, and click "Publish Subgraph." - -![Publish the subgraph](/img/publishSubgraphL2TransferTools.png) - -![Wait for the subgraph to be published](/img/waitForSubgraphToPublishL2TransferTools.png) - -This will publish the subgraph so that Indexers that are operating on Arbitrum can start serving it. It will also mint curation signal using the GRT that were transferred from L1. - -## Step 5: Updating the query URL - -Your subgraph has been successfully transferred to Arbitrum! To query the subgraph, the new URL will be : - -`https://arbitrum-gateway.thegraph.com/api/[api-key]/subgraphs/id/[l2-subgraph-id]` - -Note that the subgraph ID on Arbitrum will be a different than the one you had on mainnet, but you can always find it on Explorer or Studio. As mentioned above (see "Understanding what happens with signal, your L1 subgraph and query URLs") the old L1 URL will be supported for a short while, but you should switch your queries to the new address as soon as the subgraph has been synced on L2. - -## How to transfer your curation to Arbitrum (L2) - -## Understanding what happens to curation on subgraph transfers to L2 - -When the owner of a subgraph transfers a subgraph to Arbitrum, all of the subgraph's signal is converted to GRT at the same time. This applies to "auto-migrated" signal, i.e. signal that is not specific to a subgraph version or deployment but that follows the latest version of a subgraph. - -This conversion from signal to GRT is the same as what would happen if the subgraph owner deprecated the subgraph in L1. When the subgraph is deprecated or transferred, all curation signal is "burned" simultaneously (using the curation bonding curve) and the resulting GRT is held by the GNS smart contract (that is the contract that handles subgraph upgrades and auto-migrated signal). Each Curator on that subgraph therefore has a claim to that GRT proportional to the amount of shares they had for the subgraph. - -A fraction of these GRT corresponding to the subgraph owner is sent to L2 together with the subgraph. - -At this point, the curated GRT will not accrue any more query fees, so Curators can choose to withdraw their GRT or transfer it to the same subgraph on L2, where it can be used to mint new curation signal. There is no rush to do this as the GRT can be help indefinitely and everybody gets an amount proportional to their shares, irrespective of when they do it. - -## Choosing your L2 wallet - -If you decide to transfer your curated GRT to L2, you can choose a different wallet that will own the curation signal on L2. - -If you're using a "regular" wallet like Metamask (an Externally Owned Account or EOA, i.e. a wallet that is not a smart contract), then this is optional and it is recommended to keep the same Curator address as in L1. - -If you're using a smart contract wallet, like a multisig (e.g. a Safe), then choosing a different L2 wallet address is mandatory, as it is most likely that this account only exists on mainnet and you will not be able to make transactions on Arbitrum using this wallet. If you want to keep using a smart contract wallet or multisig, create a new wallet on Arbitrum and use its address as the L2 receiving wallet address. - -**It is very important to use a wallet address that you control, and that can make transactions on Arbitrum, as otherwise the curation will be lost and cannot be recovered.** - -## Sending curation to L2: Step 1 - -Before starting the transfer, you must decide which address will own the curation on L2 (see "Choosing your L2 wallet" above), and it is recommended having some ETH for gas already bridged on Arbitrum in case you need to retry the execution of the message on L2. You can buy ETH on some exchanges and withdraw it directly to Arbitrum, or you can use the Arbitrum bridge to send ETH from a mainnet wallet to L2: [bridge.arbitrum.io](http://bridge.arbitrum.io) - since gas fees on Arbitrum are so low, you should only need a small amount, e.g. 0.01 ETH will probably be more than enough. - -If a subgraph that you curate to has been transferred to L2, you will see a message on Explorer telling you that you're curating to a transferred subgraph. - -When looking at the subgraph page, you can choose to withdraw or transfer the curation. Clicking on "Transfer Signal to Arbitrum" will open the transfer tool. - -![Transfer signal](/img/transferSignalL2TransferTools.png) - -After opening the Transfer Tool, you may be prompted to add some ETH to your wallet if you don't have any. Then you will be able to input the L2 wallet address into the "Receiving wallet address" field - **make sure you've entered the correct address here**. Clicking on Transfer Signal will prompt you to execute the transaction on your wallet (note some ETH value is included to pay for L2 gas); this will initiate the transfer. - -If you execute this step, **make sure you proceed until completing step 3 in less than 7 days, or your signal GRT will be lost.** This is due to how L1-L2 messaging works on Arbitrum: messages that are sent through the bridge are "retryable tickets" that must be executed within 7 days, and the initial execution might need a retry if there are spikes in the gas price on Arbitrum. - -## Sending curation to L2: step 2 - -Starting the transfer: - -![Send signal to L2](/img/sendingCurationToL2Step2First.png) - -After you start the transfer, the message that sends your L1 curation to L2 must propagate through the Arbitrum bridge. This takes approximately 20 minutes (the bridge waits for the mainnet block containing the transaction to be "safe" from potential chain reorgs). - -Da zarar wannan lokacin jira ya ƙare, Arbitrum zai yi ƙoƙarin aiwatar da canja wurin kai tsaye akan kwangila L2. - -![Sending curation signal to L2](/img/sendingCurationToL2Step2Second.png) - -## Sending curation to L2: step 3 - -In most cases, this step will auto-execute as the L2 gas included in step 1 should be sufficient to execute the transaction that receives the curation on the Arbitrum contracts. In some cases, however, it is possible that a spike in gas prices on Arbitrum causes this auto-execution to fail. In this case, the "ticket" that sends your curation to L2 will be pending and require a retry within 7 days. - -If this is the case, you will need to connect using an L2 wallet that has some ETH on Arbitrum, switch your wallet network to Arbitrum, and click on "Confirm Transfer" to retry the transaction. - -![Send signal to L2](/img/L2TransferToolsFinalCurationImage.png) - -## Withdrawing your curation on L1 - -If you prefer not to send your GRT to L2, or you'd rather bridge the GRT manually, you can withdraw your curated GRT on L1. On the banner on the subgraph page, choose "Withdraw Signal" and confirm the transaction; the GRT will be sent to your Curator address. diff --git a/website/pages/ha/billing.mdx b/website/pages/ha/billing.mdx deleted file mode 100644 index 34a1ed7a8ce0..000000000000 --- a/website/pages/ha/billing.mdx +++ /dev/null @@ -1,208 +0,0 @@ ---- -title: Billing ---- - -> Invoices are generated on a weekly basis. - -There are two options for paying for your query fees: - -- [Paying with fiat currency with Banxa](#billing-with-banxa) -- [Paying with crypto wallet](#billing-on-arbitrum) - -## Billing with Banxa - -Banxa enables you to bypass the need for an exchange and pay for your query fees using the fiat currency of your choice. The fiat currency will be converted to GRT, added to your account balance on the billing contract, and used to pay for queries associated with your API keys. - -There may be KYC requirements depending on the regulations in your country. For more information about KYC, please visit [Banxa's FAQ page](https://docs.banxa.com/docs/faqs). - -You can learn more about Banxa by reading their [documentation](https://docs.banxa.com/docs). - -### Paying for query fees with Banxa - -1. Select “Pay with Card” option in [Subgraph Studio](https://thegraph.com/studio/billing/?show=Deposit). -2. Enter the amount of GRT to be added to your account balance. -3. Click the 'Continue with Banxa' button. -4. Enter necessary banking information on Banxa including payment method & fiat currency of choice. -5. Finish the transaction. - -It may take up to 10 minutes to complete the transaction. Once the transaction is confirmed, the purchased GRT will automatically be added to your account balance on Arbitrum. - -## Billing on Arbitrum - -While The Graph protocol operates on Ethereum Mainnet, [the billing contract](https://arbiscan.io/address/0x1b07d3344188908fb6deceac381f3ee63c48477a) lives on the [Arbitrum](https://arbitrum.io/) network to reduce transaction times and cost. You'll be required to pay the query fees generated from your API keys. Using the billing contract, you'll be able to: - -- Add and withdraw GRT from your account balance. -- Keep track of your balances based on how much GRT you have added to your account balance, how much you have removed, and your invoices. -- Automatically pay invoices based on query fees generated, as long as there is enough GRT in your account balance. - -### Adding GRT using a crypto wallet - - - -> This section is written assuming you already have GRT in your crypto wallet, and you're on Ethereum mainnet. If you don't have GRT, you can learn how to get GRT [here](#getting-grt). - -For a video walkthrough of adding GRT to your billing balance using a crypto wallet, watch this [video](https://youtu.be/4Bw2sh0FxCg). - -1. Go to the [Subgraph Studio Billing page](https://thegraph.com/studio/billing/). - -2. Click on the "Connect Wallet" button on the top right corner of the page. You'll be redirected to the wallet selection page. Select your wallet and click on "Connect". - -3. Click the 'Add GRT' button at the center of the page. A side panel will appear. - -4. Enter the amount of GRT you want to add to your account balance. You can also select the maximum amount of GRT you want to add to your account balance by clicking on the "Max" button. - -5. Click 'Allow GRT Access' to allow the Subgraph Studio to access your GRT. Sign the associated transaction in your wallet. This will not cost any gas. - -6. Click 'Add GRT to account balance' to add the GRT to your account balance. Sign the associated transaction in your wallet. This will cost gas. - -7. Once the transaction is confirmed, you'll see the GRT added to your account balance within an hour. - -### Withdrawing GRT using a crypto wallet - -> This section is written assuming you have deposited GRT into your account balance on [Subgraph Studio](https://thegraph.com/studio/billing/) and that you're on the Arbitrum network. - -1. Go to the [Subgraph Studio Billing page](https://thegraph.com/studio/billing/). - -2. Click on the "Connect Wallet" button on the top right corner of the page. Select your wallet and click on "Connect". - -3. Click the dropdown next to the 'Add GRT' button at the center of the page. Select withdraw GRT. A side panel will appear. - -4. Enter the amount of GRT you would like to withdraw. - -5. Click 'Withdraw GRT' to withdraw the GRT from your account balance. Sign the associated transaction in your wallet. This will cost gas. The GRT will be sent to your Arbitrum wallet. - -6. Once the transaction is confirmed, you'll see the GRT withdrawn from your account balance in your Arbitrum wallet. - -### Adding GRT using a multisig wallet - - - -1. Go to the [Subgraph Studio Billing page](https://thegraph.com/studio/billing/). - -2. Click on the "Connect Wallet" button on the top right corner of the page. Select your wallet and click on "Connect". If you're using [Gnosis-Safe](https://gnosis-safe.io/), you'll be able to connect your multisig as well as your signing wallet. Then, sign the associated message. This will not cost any gas. - -3. Click the 'Add GRT' button at the center of the page. A side panel will appear. - -4. Once the transaction is confirmed, you'll see the GRT added to your account balance within an hour. - -### Withdrawing GRT using a multisig wallet - -> This section is written assuming you have deposited GRT into your account balance on [Subgraph Studio](https://thegraph.com/studio/billing/) and that you're on Ethereum mainnet. - -1. Go to the [Subgraph Studio Billing page](https://thegraph.com/studio/billing/). - -2. Click on the "Connect Wallet" button on the top right corner of the page. Select your wallet and click on "Connect". - -3. Click the dropdown next to the 'Add GRT' button at the center of the page. Select withdraw GRT. A side panel will appear. - -4. Enter the amount of GRT you would like to withdraw. Specify the receiving wallet which will receive the GRT from this transaction. The GRT will be sent to the receiving wallet on Arbitrum. - -5. Click 'Withdraw GRT' to withdraw the GRT from your account balance. Sign the associated transaction in your wallet. This will cost gas. - -6. Once the transaction is confirmed, you'll see the GRT added to your Arbitrum wallet within an hour. - -## Getting GRT - -This section will show you how to get GRT to pay for query fees. - -### Coinbase - -This will be a step by step guide for purchasing GRT on Coinbase. - -1. Go to [Coinbase](https://www.coinbase.com/) and create an account. -2. Once you have created an account, you will need to verify your identity through a process known as KYC (or Know Your Customer). This is a standard procedure for all centralized or custodial crypto exchanges. -3. Once you have verified your identity, you can purchase GRT. You can do this by clicking on the "Buy/Sell" button on the top right of the page. -4. Select the currency you want to purchase. Select GRT. -5. Select the payment method. Select your preferred payment method. -6. Select the amount of GRT you want to purchase. -7. Review your purchase. Review your purchase and click "Buy GRT". -8. Confirm your purchase. Confirm your purchase and you will have successfully purchased GRT. -9. You can transfer the GRT from your account to your crypto wallet such as [MetaMask](https://metamask.io/). - - To transfer the GRT to your crypto wallet, click on the "Accounts" button on the top right of the page. - - Click on the "Send" button next to the GRT account. - - Enter the amount of GRT you want to send and the wallet address you want to send it to. - - Click "Continue" and confirm your transaction. -Please note that for larger purchase amounts, Coinbase may require you to wait 7-10 days before transferring the full amount to a crypto wallet. - -You can learn more about getting GRT on Coinbase [here](https://help.coinbase.com/en/coinbase/trading-and-funding/buying-selling-or-converting-crypto/how-do-i-buy-digital-currency). - -### Binance - -This will be a step by step guide for purchasing GRT on Binance. - -1. Go to [Binance](https://www.binance.com/en) and create an account. -2. Once you have created an account, you will need to verify your identity through a process known as KYC (or Know Your Customer). This is a standard procedure for all centralized or custodial crypto exchanges. -3. Once you have verified your identity, you can purchase GRT. You can do this by clicking on the "Buy Now" button on the homepage banner. -4. You will be taken to a page where you can select the currency you want to purchase. Select GRT. -5. Select your preferred payment method. You'll be able to pay with different fiat currencies such as Euros, US Dollars, and more. -6. Select the amount of GRT you want to purchase. -7. Review your purchase and click "Buy GRT". -8. Confirm your purchase and you will be able to see your GRT in your Binance Spot Wallet. -9. You can withdraw the GRT from your account to your crypto wallet such as [MetaMask](https://metamask.io/). - - [To withdraw](https://www.binance.com/en/blog/ecosystem/how-to-transfer-crypto-from-binance-to-trust-wallet-8305050796630181570) the GRT to your crypto wallet, add your crypto wallet's address to the withdrawel whitelist. - - Click on the "wallet" button, click withdraw, and select GRT. - - Enter the amount of GRT you want to send and the whitelisted wallet address you want to send it to. - - Click "Continue" and confirm your transaction. - -You can learn more about getting GRT on Binance [here](https://www.binance.com/en/support/faq/how-to-buy-cryptocurrency-on-binance-homepage-400c38f5e0cd4b46a1d0805c296b5582). - -### Uniswap - -This is how you can purchase GRT on Uniswap. - -1. Go to [Uniswap](https://app.uniswap.org/#/swap) and connect your wallet. -2. Select the token you want to swap from. Select ETH. -3. Select the token you want to swap to. Select GRT. - - Make sure you're swapping for the correct token. The GRT smart contract address is: `0xc944E90C64B2c07662A292be6244BDf05Cda44a7` -4. Enter the amount of ETH you want to swap. -5. Click "Swap". -6. Confirm the transaction in your wallet and you wait for the transaction to process. - -You can learn more about getting GRT on Uniswap [here](https://support.uniswap.org/hc/en-us/articles/8370549680909-How-to-Swap-Tokens-). - -## Getting Ethereum - -This section will show you how to get Ethereum (ETH) to pay for transaction fees or gas costs. ETH is necessary to execute operations on the Ethereum network such as transferring tokens or interacting with contracts. - -### Coinbase - -This will be a step by step guide for purchasing ETH on Coinbase. - -1. Go to [Coinbase](https://www.coinbase.com/) and create an account. -2. Once you have created an account, verify your identity through a process known as KYC (or Know Your Customer). This is a standard procedure for all centralized or custodial crypto exchanges. -3. Once you have verified your identity, purchase ETH by clicking on the "Buy/Sell" button on the top right of the page. -4. Select the currency you want to purchase. Select ETH. -5. Select your preferred payment method. -6. Enter the amount of ETH you want to purchase. -7. Review your purchase and click "Buy ETH". -8. Confirm your purchase and you will have successfully purchased ETH. -9. You can transfer the ETH from your Coinbase account to your crypto wallet such as [MetaMask](https://metamask.io/). - - To transfer the ETH to your crypto wallet, click on the "Accounts" button on the top right of the page. - - Click on the "Send" button next to the ETH account. - - Enter the amount of ETH you want to send and the wallet address you want to send it to. - - Click "Continue" and confirm your transaction. - -You can learn more about getting ETH on Coinbase [here](https://help.coinbase.com/en/coinbase/trading-and-funding/buying-selling-or-converting-crypto/how-do-i-buy-digital-currency). - -### Binance - -This will be a step by step guide for purchasing ETH on Binance. - -1. Go to [Binance](https://www.binance.com/en) and create an account. -2. Once you have created an account, verify your identity through a process known as KYC (or Know Your Customer). This is a standard procedure for all centralized or custodial crypto exchanges. -3. Once you have verified your identity, purchase ETH by clicking on the "Buy Now" button on the homepage banner. -4. Select the currency you want to purchase. Select ETH. -5. Select your preferred payment method. -6. Enter the amount of ETH you want to purchase. -7. Review your purchase and click "Buy ETH". -8. Confirm your purchase and you will see your ETH in your Binance Spot Wallet. -9. You can withdraw the ETH from your account to your crypto wallet such as [MetaMask](https://metamask.io/). - - To withdraw the ETH to your crypto wallet, add your crypto wallet's address to the withdrawal whitelist. - - Click on the "wallet" button, click withdraw, and select ETH. - - Enter the amount of ETH you want to send and the whitelisted wallet address you want to send it to. - - Click "Continue" and confirm your transaction. - -You can learn more about getting ETH on Binance [here](https://www.binance.com/en/support/faq/how-to-buy-cryptocurrency-on-binance-homepage-400c38f5e0cd4b46a1d0805c296b5582). - -## Arbitrum Bridge - -The billing contract is only designed to bridge GRT from Ethereum mainnet to the Arbitrum network. If you'd like to transfer your GRT from Arbitrum back to Ethereum mainnet, you'll need to use the [Arbitrum Bridge](https://bridge.arbitrum.io/?l2ChainId=42161). diff --git a/website/pages/ha/chain-integration-overview.mdx b/website/pages/ha/chain-integration-overview.mdx deleted file mode 100644 index 2fe6c2580909..000000000000 --- a/website/pages/ha/chain-integration-overview.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Chain Integration Process Overview ---- - -A transparent and governance-based integration process was designed for blockchain teams seeking [integration with The Graph protocol](https://forum.thegraph.com/t/gip-0057-chain-integration-process/4468). It is a 3-phase process, as summarised below. - -## Stage 1. Technical Integration - -- Teams work on a Graph Node integration and Firehose for non-EVM based chains. [Here's how](/new-chain-integration/). -- Teams initiate the protocol integration process by creating a Forum thread [here](https://forum.thegraph.com/c/governance-gips/new-chain-support/71) (New Data Sources sub-category under Governance & GIPs). Using the default Forum template is mandatory. - -## Stage 2. Integration Validation - -- Teams collaborate with core developers, Graph Foundation and operators of GUIs and network gateways, such as [Subgraph Studio](https://thegraph.com/studio/), to ensure a smooth integration process. This involves providing the necessary backend infrastructure, such as the integrating chain's JSON RPC or Firehose endpoints. Teams wanting to avoid self-hosting such infrastructure can leverage The Graph's community of node operators (Indexers) to do so, which the Foundation can help with. -- Graph Indexers test the integration on The Graph's testnet. -- Core developers and Indexers monitor stability, performance, and data determinism. - -## Stage 3. Mainnet Integration - -- Teams propose mainnet integration by submitting a Graph Improvement Proposal (GIP) and initiating a pull request (PR) on the [feature support matrix](https://github.com/graphprotocol/indexer/blob/main/docs/feature-support-matrix.md) (more details on the link). -- The Graph Council reviews the request and approves mainnet support, providing a successful Stage 2 and positive community feedback. - ---- - -If the process looks daunting, don't worry! The Graph Foundation is committed to supporting integrators by fostering collaboration, offering essential information, and guiding them through various stages, including navigating governance processes such as Graph Improvement Proposals (GIPs) and pull requests. If you have questions, please reach out to [info@thegraph.foundation](mailto:info@thegraph.foundation) or through Discord (either Pedro, The Graph Foundation member, IndexerDAO, or other core developers). - -Ready to shape the future of The Graph Network? [Start your proposal](https://github.com/graphprotocol/graph-improvement-proposals/blob/main/gips/0057-chain-integration-process.md) now and be a part of the web3 revolution! - ---- - -## Frequently Asked Questions - -### 1. How does this relate to the [World of Data Services GIP](https://forum.thegraph.com/t/gip-0042-a-world-of-data-services/3761)? - -This process is related to the Subgraph Data Service, applicable only to new Subgraph `Data Sources`. - -### 2. What happens if Firehose & Substreams support comes after the network is supported on mainnet? - -This would only impact protocol support for indexing rewards on Substreams-powered subgraphs. The new Firehose implementation would need testing on testnet, following the methodology outlined for Stage 2 in this GIP. Similarly, assuming the implementation is performant and reliable, a PR on the [Feature Support Matrix](https://github.com/graphprotocol/indexer/blob/main/docs/feature-support-matrix.md) would be required (`Substreams data sources` Subgraph Feature), as well as a new GIP for protocol support for indexing rewards. Anyone can create the PR and GIP; the Foundation would help with Council approval. - -### 3. How much time will this process take? - -The time to mainnet is expected to be several weeks, varying based on the time of integration development, whether additional research is required, testing and bug fixes, and, as always, the timing of the governance process that requires community feedback. - -Protocol support for indexing rewards depends on the stakeholders' bandwidth to proceed with testing, feedback gathering, and handling contributions to the core codebase, if applicable. This is directly tied to the integration's maturity and how responsive the integration team is (who may or may not be the team behind the RPC/Firehose implementation). The Foundation is here to help support throughout the whole process. - -### 4. How will priorities be handled? - -Similar to #3, it will depend on overall readiness and involved stakeholders' bandwidth. For example, a new chain with a brand new Firehose implementation may take longer than integrations that have already been battle-tested or are farther along in the governance process. This is especially true for chains previously supported on the [hosted service](https://thegraph.com/hosted-service) or those relying on already tested stacks. diff --git a/website/pages/ha/cookbook/_meta.js b/website/pages/ha/cookbook/_meta.js deleted file mode 100644 index 7fc5602ab4d2..000000000000 --- a/website/pages/ha/cookbook/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/cookbook/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/cookbook/arweave.mdx b/website/pages/ha/cookbook/arweave.mdx deleted file mode 100644 index 4bb5bec045e7..000000000000 --- a/website/pages/ha/cookbook/arweave.mdx +++ /dev/null @@ -1,239 +0,0 @@ ---- -title: Building Subgraphs on Arweave ---- - -> Arweave support in Graph Node and on the hosted service is in beta: please reach us on [Discord](https://discord.gg/graphprotocol) with any questions about building Arweave subgraphs! - -In this guide, you will learn how to build and deploy Subgraphs to index the Arweave blockchain. - -## What is Arweave? - -The Arweave protocol allows developers to store data permanently and that is the main difference between Arweave and IPFS, where IPFS lacks the feature; permanence, and files stored on Arweave can't be changed or deleted. - -Arweave already has built numerous libraries for integrating the protocol in a number of different programming languages. For more information you can check: - -- [Arwiki](https://arwiki.wiki/#/en/main) -- [Arweave Resources](https://www.arweave.org/build) - -## What are Arweave Subgraphs? - -The Graph allows you to build custom open APIs called "Subgraphs". Subgraphs are used to tell indexers (server operators) which data to index on a blockchain and save on their servers in order for you to be able to query it at any time using [GraphQL](https://graphql.org/). - -[Graph Node](https://github.com/graphprotocol/graph-node) is now able to index data on Arweave protocol. The current integration is only indexing Arweave as a blockchain (blocks and transactions), it is not indexing the stored files yet. - -## Building an Arweave Subgraph - -To be able to build and deploy Arweave Subgraphs, you need two packages: - -1. `@graphprotocol/graph-cli` above version 0.30.2 - This is a command-line tool for building and deploying subgraphs. [Click here](https://www.npmjs.com/package/@graphprotocol/graph-cli) to download using `npm`. -2. `@graphprotocol/graph-ts` above version 0.27.0 - This is library of subgraph-specific types. [Click here](https://www.npmjs.com/package/@graphprotocol/graph-ts) to download using `npm`. - -## Subgraph's components - -There are three components of a subgraph: - -### 1. Manifest - `subgraph.yaml` - -Defines the data sources of interest, and how they should be processed. Arweave is a new kind of data source. - -### 2. Schema - `schema.graphql` - -Here you define which data you want to be able to query after indexing your Subgraph using GraphQL. This is actually similar to a model for an API, where the model defines the structure of a request body. - -The requirements for Arweave subgraphs are covered by the [existing documentation](/developing/creating-a-subgraph/#the-graphql-schema). - -### 3. AssemblyScript Mappings - `mapping.ts` - -This is the logic that determines how data should be retrieved and stored when someone interacts with the data sources you are listening to. The data gets translated and is stored based off the schema you have listed. - -During subgraph development there are two key commands: - -``` -$ graph codegen # generates types from the schema file identified in the manifest -$ graph build # generates Web Assembly from the AssemblyScript files, and prepares all the subgraph files in a /build folder -``` - -## Subgraph Manifest Definition - -The subgraph manifest `subgraph.yaml` identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest for an Arweave subgraph: - -```yaml -specVersion: 0.0.5 -description: Arweave Blocks Indexing -schema: - file: ./schema.graphql # link to the schema file -dataSources: - - kind: arweave - name: arweave-blocks - network: arweave-mainnet # The Graph only supports Arweave Mainnet - source: - owner: 'ID-OF-AN-OWNER' # The public key of an Arweave wallet - startBlock: 0 # set this to 0 to start indexing from chain genesis - mapping: - apiVersion: 0.0.5 - language: wasm/assemblyscript - file: ./src/blocks.ts # link to the file with the Assemblyscript mappings - entities: - - Block - - Transaction - blockHandlers: - - handler: handleBlock # the function name in the mapping file - transactionHandlers: - - handler: handleTx # the function name in the mapping file -``` - -- Arweave subgraphs introduce a new kind of data source (`arweave`) -- The network should correspond to a network on the hosting Graph Node. On the hosted service, Arweave's mainnet is `arweave-mainnet` -- Arweave data sources introduce an optional source.owner field, which is the public key of an Arweave wallet - -Arweave data sources support two types of handlers: - -- `blockHandlers` - Run on every new Arweave block. No source.owner is required. -- `transactionHandlers` - Run on every transaction where the data source's `source.owner` is the owner. Currently an owner is required for `transactionHandlers`, if users want to process all transactions they should provide "" as the `source.owner` - -> The source.owner can be the owner's address, or their Public Key. - -> Transactions are the building blocks of the Arweave permaweb and they are objects created by end-users. - -> Note: [Bundlr](https://bundlr.network/) transactions are not supported yet. - -## Schema Definition - -Schema definition describes the structure of the resulting subgraph database and the relationships between entities. This is agnostic of the original data source. There are more details on the subgraph schema definition [here](/developing/creating-a-subgraph/#the-graphql-schema). - -## AssemblyScript Mappings - -The handlers for processing events are written in [AssemblyScript](https://www.assemblyscript.org/). - -Arweave indexing introduces Arweave-specific data types to the [AssemblyScript API](/developing/graph-ts/api/). - -```tsx -class Block { - timestamp: u64 - lastRetarget: u64 - height: u64 - indepHash: Bytes - nonce: Bytes - previousBlock: Bytes - diff: Bytes - hash: Bytes - txRoot: Bytes - txs: Bytes[] - walletList: Bytes - rewardAddr: Bytes - tags: Tag[] - rewardPool: Bytes - weaveSize: Bytes - blockSize: Bytes - cumulativeDiff: Bytes - hashListMerkle: Bytes - poa: ProofOfAccess -} - -class Transaction { - format: u32 - id: Bytes - lastTx: Bytes - owner: Bytes - tags: Tag[] - target: Bytes - quantity: Bytes - data: Bytes - dataSize: Bytes - dataRoot: Bytes - signature: Bytes - reward: Bytes -} -``` - -Block handlers receive a `Block`, while transactions receive a `Transaction`. - -Writing the mappings of an Arweave Subgraph is very similar to writing the mappings of an Ethereum Subgraph. For more information, click [here](/developing/creating-a-subgraph/#writing-mappings). - -## Deploying an Arweave Subgraph on the hosted service - -Once your subgraph has been created on the hosted service dashboard, you can deploy by using the `graph deploy` CLI command. - -```bash -graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ --access-token -``` - -## Querying an Arweave Subgraph - -The GraphQL endpoint for Arweave subgraphs is determined by the schema definition, with the existing API interface. Please visit the [GraphQL API documentation](/querying/graphql-api/) for more information. - -## Example Subgraphs - -Here is an example subgraph for reference: - -- [Example subgraph for Arweave](https://github.com/graphprotocol/graph-tooling/tree/main/examples/arweave-blocks-transactions) - -## FAQ - -### Can a subgraph index Arweave and other chains? - -No, a subgraph can only support data sources from one chain/network. - -### Can I index the stored files on Arweave? - -Currently, The Graph is only indexing Arweave as a blockchain (its blocks and transactions). - -### Can I identify Bundlr bundles in my subgraph? - -This is not currently supported. - -### How can I filter transactions to a specific account? - -The source.owner can be the user's public key or account address. - -### What is the current encryption format? - -Data is generally passed into the mappings as Bytes, which if stored directly is returned in the subgraph in a `hex` format (ex. block and transaction hashes). You may want to convert to a `base64` or `base64 URL`-safe format in your mappings, in order to match what is displayed in block explorers like [Arweave Explorer](https://viewblock.io/arweave/). - -The following `bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string` helper function can be used, and will be added to `graph-ts`: - -``` -const base64Alphabet = [ - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" -]; - -const base64UrlAlphabet = [ - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", - "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "_" -]; - -function bytesToBase64(bytes: Uint8Array, urlSafe: boolean): string { - let alphabet = urlSafe? base64UrlAlphabet : base64Alphabet; - - let result = '', i: i32, l = bytes.length; - for (i = 2; i < l; i += 3) { - result += alphabet[bytes[i - 2] >> 2]; - result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)]; - result += alphabet[((bytes[i - 1] & 0x0F) << 2) | (bytes[i] >> 6)]; - result += alphabet[bytes[i] & 0x3F]; - } - if (i === l + 1) { // 1 octet yet to write - result += alphabet[bytes[i - 2] >> 2]; - result += alphabet[(bytes[i - 2] & 0x03) << 4]; - if (!urlSafe) { - result += "=="; - } - } - if (!urlSafe && i === l) { // 2 octets yet to write - result += alphabet[bytes[i - 2] >> 2]; - result += alphabet[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)]; - result += alphabet[(bytes[i - 1] & 0x0F) << 2]; - if (!urlSafe) { - result += "="; - } - } - return result; -} -``` diff --git a/website/pages/ha/cookbook/avoid-eth-calls.mdx b/website/pages/ha/cookbook/avoid-eth-calls.mdx deleted file mode 100644 index 25fcb8b0db9d..000000000000 --- a/website/pages/ha/cookbook/avoid-eth-calls.mdx +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Subgraph Best Practice 4 - Improve Indexing Speed by Avoiding eth_calls ---- - -## TLDR - -`eth_calls` are calls that can be made from a subgraph to an Ethereum node. These calls take a significant amount of time to return data, slowing down indexing. If possible, design smart contracts to emit all the data you need so you don’t need to use `eth_calls`. - -## Why Avoiding `eth_calls` Is a Best Practice - -Subgraphs are optimized to index event data emitted from smart contracts. A subgraph can also index the data coming from an `eth_call`, however, this can significantly slow down subgraph indexing as `eth_calls` require making external calls to smart contracts. The responsiveness of these calls relies not on the subgraph but on the connectivity and responsiveness of the Ethereum node being queried. By minimizing or eliminating eth_calls in our subgraphs, we can significantly improve our indexing speed. - -### What Does an eth_call Look Like? - -`eth_calls` are often necessary when the data required for a subgraph is not available through emitted events. For example, consider a scenario where a subgraph needs to identify whether ERC20 tokens are part of a specific pool, but the contract only emits a basic `Transfer` event and does not emit an event that contains the data that we need: - -```yaml -event Transfer(address indexed from, address indexed to, uint256 value); -``` - -Suppose the tokens' pool membership is determined by a state variable named `getPoolInfo`. In this case, we would need to use an `eth_call` to query this data: - -```typescript -import { Address } from '@graphprotocol/graph-ts' -import { ERC20, Transfer } from '../generated/ERC20/ERC20' -import { TokenTransaction } from '../generated/schema' - -export function handleTransfer(event: Transfer): void { - let transaction = new TokenTransaction(event.transaction.hash.toHex()) - - // Bind the ERC20 contract instance to the given address: - let instance = ERC20.bind(event.address) - - // Retrieve pool information via eth_call - let poolInfo = instance.getPoolInfo(event.params.to) - - transaction.pool = poolInfo.toHexString() - transaction.from = event.params.from.toHexString() - transaction.to = event.params.to.toHexString() - transaction.value = event.params.value - - transaction.save() -} -``` - -This is functional, however is not ideal as it slows down our subgraph’s indexing. - -## How to Eliminate `eth_calls` - -Ideally, the smart contract should be updated to emit all necessary data within events. For instance, modifying the smart contract to include pool information in the event could eliminate the need for `eth_calls`: - -``` -event TransferWithPool(address indexed from, address indexed to, uint256 value, bytes32 indexed poolInfo); -``` - -With this update, the subgraph can directly index the required data without external calls: - -```typescript -import { Address } from '@graphprotocol/graph-ts' -import { ERC20, TransferWithPool } from '../generated/ERC20/ERC20' -import { TokenTransaction } from '../generated/schema' - -export function handleTransferWithPool(event: TransferWithPool): void { - let transaction = new TokenTransaction(event.transaction.hash.toHex()) - - transaction.pool = event.params.poolInfo.toHexString() - transaction.from = event.params.from.toHexString() - transaction.to = event.params.to.toHexString() - transaction.value = event.params.value - - transaction.save() -} -``` - -This is much more performant as it has eliminated the need for `eth_calls`. - -## How to Optimize `eth_calls` - -If modifying the smart contract is not possible and `eth_calls` are required, read “[Improve Subgraph Indexing Performance Easily: Reduce eth_calls](https://thegraph.com/blog/improve-subgraph-performance-reduce-eth-calls/)” by Simon Emanuel Schmid to learn various strategies on how to optimize `eth_calls`. - -## Reducing the Runtime Overhead of `eth_calls` - -For the `eth_calls` that can not be eliminated, the runtime overhead they introduce can be minimized by declaring them in the manifest. When `graph-node` processes a block it performs all declared `eth_calls` in parallel before handlers are run. Calls that are not declared are executed sequentially when handlers run. The runtime improvement comes from performing calls in parallel rather than sequentially - that helps reduce the total time spent in calls but does not eliminate it completely. - -Currently, `eth_calls` can only be declared for event handlers. In the manifest, write - -```yaml -event: TransferWithPool(address indexed, address indexed, uint256, bytes32 indexed) -handler: handleTransferWithPool -calls: - ERC20.poolInfo: ERC20[event.address].getPoolInfo(event.params.to) -``` - -The portion highlighted in yellow is the call declaration. The part before the colon is simply a text label that is only used for error messages. The part after the colon has the form `Contract[address].function(params)`. Permissible values for address and params are `event.address` and `event.params.`. - -The handler itself accesses the result of this `eth_call` exactly as in the previous section by binding to the contract and making the call. graph-node caches the results of declared `eth_calls` in memory and the call from the handler will retrieve the result from this in memory cache instead of making an actual RPC call. - -Note: Declared eth_calls can only be made in subgraphs with specVersion >= 1.2.0. - -## Conclusion - -You can significantly improve indexing performance by minimizing or eliminating `eth_calls` in your subgraphs. - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/cosmos.mdx b/website/pages/ha/cookbook/cosmos.mdx deleted file mode 100644 index 4a5d0f0edd80..000000000000 --- a/website/pages/ha/cookbook/cosmos.mdx +++ /dev/null @@ -1,259 +0,0 @@ ---- -title: Building Subgraphs on Cosmos ---- - -This guide is an introduction on building subgraphs indexing [Cosmos](https://docs.cosmos.network/) based blockchains. - -## What are Cosmos subgraphs? - -The Graph allows developers to process blockchain events and make the resulting data easily available via an open GraphQL API, known as a subgraph. [Graph Node](https://github.com/graphprotocol/graph-node) is now able to process Cosmos events, which means Cosmos developers can now build subgraphs to easily index on-chain events. - -There are four types of handlers supported in Cosmos subgraphs: - -- **Block handlers** run whenever a new block is appended to the chain. -- **Event handlers** run when a specific event is emitted. -- **Transaction handlers** run when a transaction occurs. -- **Message handlers** run when a specific message occurs. - -Based on the [official Cosmos documentation](https://docs.cosmos.network/): - -> [Events](https://docs.cosmos.network/main/core/events) are objects that contain information about the execution of the application. They are mainly used by service providers like block explorers and wallets to track the execution of various messages and index transactions. - -> [Transactions](https://docs.cosmos.network/main/core/transactions) are objects created by end-users to trigger state changes in the application. - -> [Messages](https://docs.cosmos.network/main/core/transactions#messages) are module-specific objects that trigger state transitions within the scope of the module they belong to. - -Even though all data can be accessed with a block handler, other handlers enable subgraph developers to process data in a much more granular way. - -## Building a Cosmos subgraph - -### Subgraph Dependencies - -[graph-cli](https://github.com/graphprotocol/graph-cli) is a CLI tool to build and deploy subgraphs, version `>=0.30.0` is required in order to work with Cosmos subgraphs. - -[graph-ts](https://github.com/graphprotocol/graph-ts) is a library of subgraph-specific types, version `>=0.27.0` is required in order to work with Cosmos subgraphs. - -### Subgraph Main Components - -There are three key parts when it comes to defining a subgraph: - -**subgraph.yaml**: a YAML file containing the subgraph manifest, which identifies which events to track and how to process them. - -**schema.graphql**: a GraphQL schema that defines what data is stored for your subgraph, and how to query it via GraphQL. - -**AssemblyScript Mappings**: [AssemblyScript](https://github.com/AssemblyScript/assemblyscript) code that translates from blockchain data to the entities defined in your schema. - -### Subgraph Manifest Definition - -The subgraph manifest (`subgraph.yaml`) identifies the data sources for the subgraph, the triggers of interest, and the functions (`handlers`) that should be run in response to those triggers. See below for an example subgraph manifest for a Cosmos subgraph: - -```yaml -specVersion: 0.0.5 -description: Cosmos Subgraph Example -schema: - file: ./schema.graphql # link to the schema file -dataSources: - - kind: cosmos - name: CosmosHub - network: cosmoshub-4 # This will change for each cosmos-based blockchain. In this case, the example uses the Cosmos Hub mainnet. - source: - startBlock: 0 # Required for Cosmos, set this to 0 to start indexing from chain genesis - mapping: - apiVersion: 0.0.7 - language: wasm/assemblyscript - blockHandlers: - - handler: handleNewBlock # the function name in the mapping file - eventHandlers: - - event: rewards # the type of the event that will be handled - handler: handleReward # the function name in the mapping file - transactionHandlers: - - handler: handleTransaction # the function name in the mapping file - messageHandlers: - - message: /cosmos.staking.v1beta1.MsgDelegate # the type of a message - handler: handleMsgDelegate # the function name in the mapping file - file: ./src/mapping.ts # link to the file with the Assemblyscript mappings -``` - -- Cosmos subgraphs introduce a new `kind` of data source (`cosmos`). -- The `network` should correspond to a chain in the Cosmos ecosystem. In the example, the Cosmos Hub mainnet is used. - -### Schema Definition - -Schema definition describes the structure of the resulting subgraph database and the relationships between entities. This is agnostic of the original data source. There are more details on subgraph schema definition [here](/developing/creating-a-subgraph/#the-graph-ql-schema). - -### AssemblyScript Mappings - -The handlers for processing events are written in [AssemblyScript](https://www.assemblyscript.org/). - -Cosmos indexing introduces Cosmos-specific data types to the [AssemblyScript API](/developing/graph-ts/api/). - -```tsx -class Block { - header: Header - evidence: EvidenceList - resultBeginBlock: ResponseBeginBlock - resultEndBlock: ResponseEndBlock - transactions: Array - validatorUpdates: Array -} - -class EventData { - event: Event - block: HeaderOnlyBlock - tx: TransactionContext -} - -class TransactionData { - tx: TxResult - block: HeaderOnlyBlock -} - -class MessageData { - message: Any - block: HeaderOnlyBlock - tx: TransactionContext -} - -class TransactionContext { - hash: Bytes - index: u32 - code: u32 - gasWanted: i64 - gasUsed: i64 -} - -class HeaderOnlyBlock { - header: Header -} - -class Header { - version: Consensus - chainId: string - height: u64 - time: Timestamp - lastBlockId: BlockID - lastCommitHash: Bytes - dataHash: Bytes - validatorsHash: Bytes - nextValidatorsHash: Bytes - consensusHash: Bytes - appHash: Bytes - lastResultsHash: Bytes - evidenceHash: Bytes - proposerAddress: Bytes - hash: Bytes -} - -class TxResult { - height: u64 - index: u32 - tx: Tx - result: ResponseDeliverTx - hash: Bytes -} - -class Event { - eventType: string - attributes: Array -} - -class Any { - typeUrl: string - value: Bytes -} -``` - -Each handler type comes with its own data structure that is passed as an argument to a mapping function. - -- Block handlers receive the `Block` type. -- Event handlers receive the `EventData` type. -- Transaction handlers receive the `TransactionData` type. -- Message handlers receive the `MessageData` type. - -As a part of `MessageData` the message handler receives a transaction context, which contains the most important information about a transaction that encompasses a message. The transaction context is also available in the `EventData` type, but only when the corresponding event is associated with a transaction. Additionally, all handlers receive a reference to a block (`HeaderOnlyBlock`). - -You can find the full list of types for the Cosmos integration [here](https://github.com/graphprotocol/graph-ts/blob/4c064a8118dff43b110de22c7756e5d47fcbc8df/chain/cosmos.ts). - -### Message decoding - -It's important to note that Cosmos messages are chain-specific and they are passed to a subgraph in the form of a serialized [Protocol Buffers](https://developers.google.com/protocol-buffers/) payload. As a result, the message data needs to be decoded in a mapping function before it can be processed. - -An example of how to decode message data in a subgraph can be found [here](https://github.com/graphprotocol/graph-tooling/blob/main/examples/cosmos-validator-delegations/src/decoding.ts). - -## Creating and building a Cosmos subgraph - -The first step before starting to write the subgraph mappings is to generate the type bindings based on the entities that have been defined in the subgraph schema file (`schema.graphql`). This will allow the mapping functions to create new objects of those types and save them to the store. This is done by using the `codegen` CLI command: - -```bash -$ graph codegen -``` - -Once the mappings are ready, the subgraph needs to be built. This step will highlight any errors the manifest or the mappings might have. A subgraph needs to build successfully in order to be deployed to the Graph Node. It can be done using the `build` CLI command: - -```bash -$ graph build -``` - -## Deploying a Cosmos subgraph - -Once your subgraph has been created, you can deploy your subgraph by using the `graph deploy` CLI command after running the `graph create` CLI command: - -**Hosted Service** - -```bash -graph create account/subgraph-name --product hosted-service -``` - -```bash -graph deploy account/subgraph-name --product hosted-service -``` - -**Local Graph Node (based on default configuration):** - -```bash -graph create subgraph-name --node http://localhost:8020 -``` - -```bash -graph deploy subgraph-name --node http://localhost:8020/ --ipfs http://localhost:5001 -``` - -## Querying a Cosmos subgraph - -The GraphQL endpoint for Cosmos subgraphs is determined by the schema definition, with the existing API interface. Please visit the [GraphQL API documentation](/querying/graphql-api/) for more information. - -## Supported Cosmos Blockchains - -### Cosmos Hub - -#### What is Cosmos Hub? - -The [Cosmos Hub blockchain](https://hub.cosmos.network/) is the first blockchain in the [Cosmos](https://cosmos.network/) ecosystem. You can visit the [official documentation](https://docs.cosmos.network/) for more information. - -#### Networks - -Cosmos Hub mainnet is `cosmoshub-4`. Cosmos Hub current testnet is `theta-testnet-001`.
Other Cosmos Hub networks, i.e. `cosmoshub-3`, are halted, therefore no data is provided for them. - -### Osmosis - -> Osmosis support in Graph Node and on the Hosted Service is in beta: please contact the graph team with any questions about building Osmosis subgraphs! - -#### What is Osmosis? - -[Osmosis](https://osmosis.zone/) is a decentralized, cross-chain automated market maker (AMM) protocol built on top of the Cosmos SDK. It allows users to create custom liquidity pools and trade IBC-enabled tokens. You can visit the [official documentation](https://docs.osmosis.zone/) for more information. - -#### Networks - -Osmosis mainnet is `osmosis-1`. Osmosis current testnet is `osmo-test-4`. - -## Example Subgraphs - -Here are some example subgraphs for reference: - -[Block Filtering Example](https://github.com/graphprotocol/graph-tooling/tree/main/examples/cosmos-block-filtering) - -[Validator Rewards Example](https://github.com/graphprotocol/graph-tooling/tree/main/examples/cosmos-validator-rewards) - -[Validator Delegations Example](https://github.com/graphprotocol/graph-tooling/tree/main/examples/cosmos-validator-delegations) - -[Osmosis Token Swaps Example](https://github.com/graphprotocol/graph-tooling/tree/main/examples/cosmos-osmosis-token-swaps) diff --git a/website/pages/ha/cookbook/derivedfrom.mdx b/website/pages/ha/cookbook/derivedfrom.mdx deleted file mode 100644 index 75827a185a6b..000000000000 --- a/website/pages/ha/cookbook/derivedfrom.mdx +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Subgraph Best Practice 2 - Improve Indexing and Query Responsiveness By Using @derivedFrom ---- - -## TLDR - -Arrays in your schema can really slow down a subgraph's performance as they grow beyond thousands of entries. If possible, the `@derivedFrom` directive should be used when using arrays as it prevents large arrays from forming, simplifies handlers, and reduces the size of individual entities, improving indexing speed and query performance significantly. - -## How to Use the `@derivedFrom` Directive - -You just need to add a `@derivedFrom` directive after your array in your schema. Like this: - -```graphql -comments: [Comment!]! @derivedFrom(field: "post") -``` - -`@derivedFrom` creates efficient one-to-many relationships, enabling an entity to dynamically associate with multiple related entities based on a field in the related entity. This approach removes the need for both sides of the relationship to store duplicate data, making the subgraph more efficient. - -### Example Use Case for `@derivedFrom` - -An example of a dynamically growing array is a blogging platform where a “Post” can have many “Comments”. - -Let’s start with our two entities, `Post` and `Comment` - -Without optimization, you could implement it like this with an array: - -```graphql -type Post @entity { - id: Bytes! - title: String! - content: String! - comments: [Comment!]! -} - -type Comment @entity { - id: Bytes! - content: String! -} -``` - -Arrays like these will effectively store extra Comments data on the Post side of the relationship. - -Here’s what an optimized version looks like using `@derivedFrom`: - -```graphql -type Post @entity { - id: Bytes! - title: String! - content: String! - comments: [Comment!]! @derivedFrom(field: "post") -} - -type Comment @entity { - id: Bytes! - content: String! - post: Post! -} -``` - -Just by adding the `@derivedFrom` directive, this schema will only store the “Comments” on the “Comments” side of the relationship and not on the “Post” side of the relationship. Arrays are stored across individual rows, which allows them to expand significantly. This can lead to particularly large sizes if their growth is unbounded. - -This will not only make our subgraph more efficient, but it will also unlock three features: - -1. We can query the `Post` and see all of its comments. -2. We can do a reverse lookup and query any `Comment` and see which post it comes from. - -3. We can use [Derived Field Loaders](/developing/graph-ts/api/#looking-up-derived-entities) to unlock the ability to directly access and manipulate data from virtual relationships in our subgraph mappings. - -## Conclusion - -Use the `@derivedFrom` directive in subgraphs to effectively manage dynamically growing arrays, enhancing indexing efficiency and data retrieval. - -For a more detailed explanation of strategies to avoid large arrays, check out Kevin Jones' blog: [Best Practices in Subgraph Development: Avoiding Large Arrays](https://thegraph.com/blog/improve-subgraph-performance-avoiding-large-arrays/). - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/enums.mdx b/website/pages/ha/cookbook/enums.mdx deleted file mode 100644 index a10970c1539f..000000000000 --- a/website/pages/ha/cookbook/enums.mdx +++ /dev/null @@ -1,274 +0,0 @@ ---- -title: Categorize NFT Marketplaces Using Enums ---- - -Use Enums to make your code cleaner and less error-prone. Here's a full example of using Enums on NFT marketplaces. - -## What are Enums? - -Enums, or enumeration types, are a specific data type that allows you to define a set of specific, allowed values. - -### Example of Enums in Your Schema - -If you're building a subgraph to track the ownership history of tokens on a marketplace, each token might go through different ownerships, such as `OriginalOwner`, `SecondOwner`, and `ThirdOwner`. By using enums, you can define these specific ownerships, ensuring only predefined values are assigned. - -You can define enums in your schema, and once defined, you can use the string representation of the enum values to set an enum field on an entity. - -Here's what an enum definition might look like in your schema, based on the example above: - -```graphql -enum TokenStatus { - OriginalOwner - SecondOwner - ThirdOwner -} -``` - -This means that when you use the `TokenStatus` type in your schema, you expect it to be exactly one of predefined values: `OriginalOwner`, `SecondOwner`, or `ThirdOwner`, ensuring consistency and validity. - -To learn more about enums, check out [Creating a Subgraph](/developing/creating-a-subgraph/#enums) and [GraphQL documentation](https://graphql.org/learn/schema/#enumeration-types). - -## Benefits of Using Enums - -- **Clarity:** Enums provide meaningful names for values, making data easier to understand. -- **Validation:** Enums enforce strict value definitions, preventing invalid data entries. -- **Maintainability:** When you need to change or add new categories, enums allow you to do this in a focused manner. - -### Without Enums - -If you choose to define the type as a string instead of using an Enum, your code might look like this: - -```graphql -type Token @entity { - id: ID! - tokenId: BigInt! - owner: Bytes! # Owner of the token - tokenStatus: String! # String field to track token status - timestamp: BigInt! -} -``` - -In this schema, `TokenStatus` is a simple string with no specific, allowed values. - -#### Why is this a problem? - -- There's no restriction of `TokenStatus` values, so any string can be accidentally assigned. This makes it hard to ensure that only valid statuses like `OriginalOwner`, `SecondOwner`, or `ThirdOwner` are set. -- It's easy to make typos such as `Orgnalowner` instead of `OriginalOwner`, making the data and potential queries unreliable. - -### With Enums - -Instead of assigning free-form strings, you can define an enum for `TokenStatus` with specific values: `OriginalOwner`, `SecondOwner`, or `ThirdOwner`. Using an enum ensures only allowed values are used. - -Enums provide type safety, minimize typo risks, and ensure consistent and reliable results. - -## Defining Enums for NFT Marketplaces - -> Note: The following guide uses the CryptoCoven NFT smart contract. - -To define enums for the various marketplaces where NFTs are traded, use the following in your subgraph schema: - -```gql -# Enum for Marketplaces that the CryptoCoven contract interacted with(likely a Trade/Mint) -enum Marketplace { - OpenSeaV1 # Represents when a CryptoCoven NFT is traded on the marketplace - OpenSeaV2 # Represents when a CryptoCoven NFT is traded on the OpenSeaV2 marketplace - SeaPort # Represents when a CryptoCoven NFT is traded on the SeaPort marketplace - LooksRare # Represents when a CryptoCoven NFT is traded on the LookRare marketplace - # ...and other marketplaces -} -``` - -## Using Enums for NFT Marketplaces - -Once defined, enums can be used throughout your subgraph to categorize transactions or events. - -For example, when logging NFT sales, you can specify the marketplace involved in the trade using the enum. - -### Implementing a Function for NFT Marketplaces - -Here's how you can implement a function to retrieve the marketplace name from the enum as a string: - -```ts -export function getMarketplaceName(marketplace: Marketplace): string { - // Using if-else statements to map the enum value to a string - if (marketplace === Marketplace.OpenSeaV1) { - return 'OpenSeaV1' // If the marketplace is OpenSea, return its string representation - } else if (marketplace === Marketplace.OpenSeaV2) { - return 'OpenSeaV2' - } else if (marketplace === Marketplace.SeaPort) { - return 'SeaPort' // If the marketplace is SeaPort, return its string representation - } else if (marketplace === Marketplace.LooksRare) { - return 'LooksRare' // If the marketplace is LooksRare, return its string representation - // ... and other market places - } -} -``` - -## Best Practices for Using Enums - -- **Consistent Naming:** Use clear, descriptive names for enum values to improve readability. -- **Centralized Management:** Keep enums in a single file for consistency. This makes enums easier to update and ensures they are the single source of truth. -- **Documentation:** Add comments to enum to clarify their purpose and usage. - -## Using Enums in Queries - -Enums in queries help you improve data quality and make your results easier to interpret. They function as filters and response elements, ensuring consistency and reducing errors in marketplace values. - -**Specifics** - -- **Filtering with Enums:** Enums provide clear filters, allowing you to confidently include or exclude specific marketplaces. -- **Enums in Responses:** Enums guarantee that only recognized marketplace names are returned, making the results standardized and accurate. - -### Sample Queries - -#### Query 1: Account With The Highest NFT Marketplace Interactions - -This query does the following: - -- It finds the account with the highest unique NFT marketplace interactions, which is great for analyzing cross-marketplace activity. -- The marketplaces field uses the marketplace enum, ensuring consistent and validated marketplace values in the response. - -```gql -{ - accounts(first: 1, orderBy: uniqueMarketplacesCount, orderDirection: desc) { - id - sendCount - receiveCount - totalSpent - uniqueMarketplacesCount - marketplaces { - marketplace # This field returns the enum value representing the marketplace - } - } -} -``` - -#### Returns - -This response provides account details and a list of unique marketplace interactions with enum values for standardized clarity: - -```gql -{ - "data": { - "accounts": [ - { - "id": "0xb3abc96cb9a61576c03c955d75b703a890a14aa0", - "sendCount": "44", - "receiveCount": "44", - "totalSpent": "1197500000000000000", - "uniqueMarketplacesCount": "7", - "marketplaces": [ - { - "marketplace": "OpenSeaV1" - }, - { - "marketplace": "OpenSeaV2" - }, - { - "marketplace": "GenieSwap" - }, - { - "marketplace": "CryptoCoven" - }, - { - "marketplace": "Unknown" - }, - { - "marketplace": "LooksRare" - }, - { - "marketplace": "NFTX" - } - ] - } - ] - } -} -``` - -#### Query 2: Most Active Marketplace for CryptoCoven transactions - -This query does the following: - -- It identifies the marketplace with the highest volume of CryptoCoven transactions. -- It uses the marketplace enum to ensure that only valid marketplace types appear in the response, adding reliability and consistency to your data. - -```gql -{ - marketplaceInteractions(first: 1, orderBy: transactionCount, orderDirection: desc) { - marketplace - transactionCount - } -} -``` - -#### Result 2 - -The expected response includes the marketplace and the corresponding transaction count, using the enum to indicate the marketplace type: - -```gql -{ - "data": { - "marketplaceInteractions": [ - { - "marketplace": "Unknown", - "transactionCount": "222" - } - ] - } -} -``` - -#### Query 3: Marketplace Interactions with High Transaction Counts - -This query does the following: - -- It retrieves the top four marketplaces with over 100 transactions, excluding "Unknown" marketplaces. -- It uses enums as filters to ensure that only valid marketplace types are included, increasing accuracy. - -```gql -{ - marketplaceInteractions( - first: 4 - orderBy: transactionCount - orderDirection: desc - where: { transactionCount_gt: "100", marketplace_not: "Unknown" } - ) { - marketplace - transactionCount - } -} -``` - -#### Result 3 - -Expected output includes the marketplaces that meet the criteria, each represented by an enum value: - -```gql -{ - "data": { - "marketplaceInteractions": [ - { - "marketplace": "NFTX", - "transactionCount": "201" - }, - { - "marketplace": "OpenSeaV1", - "transactionCount": "148" - }, - { - "marketplace": "CryptoCoven", - "transactionCount": "117" - }, - { - "marketplace": "OpenSeaV1", - "transactionCount": "111" - } - ] - } -} -``` - -## Additional Resources - -For additional information, check out this guide's [repo](https://github.com/chidubemokeke/Subgraph-Tutorial-Enums). diff --git a/website/pages/ha/cookbook/grafting-hotfix.mdx b/website/pages/ha/cookbook/grafting-hotfix.mdx deleted file mode 100644 index 4be0a0b07790..000000000000 --- a/website/pages/ha/cookbook/grafting-hotfix.mdx +++ /dev/null @@ -1,186 +0,0 @@ ---- -Subgraph Best Practice 6 - Use Grafting for Quick Hotfix Deployment ---- - -## TLDR - -Grafting is a powerful feature in subgraph development that allows you to build and deploy new subgraphs while reusing the indexed data from existing ones. - -### Overview - -This feature enables quick deployment of hotfixes for critical issues, eliminating the need to re-index the entire subgraph from scratch. By preserving historical data, grafting minimizes downtime and ensures continuity in data services. - -## Benefits of Grafting for Hotfixes - -1. **Rapid Deployment** - - - **Minimize Downtime**: When a subgraph encounters a critical error and stops indexing, grafting enables you to deploy a fix immediately without waiting for re-indexing. - - **Immediate Recovery**: The new subgraph continues from the last indexed block, ensuring that data services remain uninterrupted. - -2. **Data Preservation** - - - **Reuse Historical Data**: Grafting copies the existing data from the base subgraph, so you don’t lose valuable historical records. - - **Consistency**: Maintains data continuity, which is crucial for applications relying on consistent historical data. - -3. **Efficiency** - - **Save Time and Resources**: Avoids the computational overhead of re-indexing large datasets. - - **Focus on Fixes**: Allows developers to concentrate on resolving issues rather than managing data recovery. - -## Best Practices When Using Grafting for Hotfixes - -1. **Initial Deployment Without Grafting** - - - **Start Clean**: Always deploy your initial subgraph without grafting to ensure that it’s stable and functions as expected. - - **Test Thoroughly**: Validate the subgraph’s performance to minimize the need for future hotfixes. - -2. **Implementing the Hotfix with Grafting** - - - **Identify the Issue**: When a critical error occurs, determine the block number of the last successfully indexed event. - - **Create a New Subgraph**: Develop a new subgraph that includes the hotfix. - - **Configure Grafting**: Use grafting to copy data up to the identified block number from the failed subgraph. - - **Deploy Quickly**: Publish the grafted subgraph to restore service as soon as possible. - -3. **Post-Hotfix Actions** - - - **Monitor Performance**: Ensure the grafted subgraph is indexing correctly and the hotfix resolves the issue. - - **Republish Without Grafting**: Once stable, deploy a new version of the subgraph without grafting for long-term maintenance. - > Note: Relying on grafting indefinitely is not recommended as it can complicate future updates and maintenance. - - **Update References**: Redirect any services or applications to use the new, non-grafted subgraph. - -4. **Important Considerations** - - **Careful Block Selection**: Choose the graft block number carefully to prevent data loss. - - **Tip**: Use the block number of the last correctly processed event. - - **Use Deployment ID**: Ensure you reference the Deployment ID of the base subgraph, not the Subgraph ID. - - **Note**: The Deployment ID is the unique identifier for a specific subgraph deployment. - - **Feature Declaration**: Remember to declare grafting in the subgraph manifest under features. - -## Example: Deploying a Hotfix with Grafting - -Suppose you have a subgraph tracking a smart contract that has stopped indexing due to a critical error. Here’s how you can use grafting to deploy a hotfix. - -1. **Failed Subgraph Manifest (subgraph.yaml)** - - ```yaml - specVersion: 1.0.0 - schema: - file: ./schema.graphql - dataSources: - - kind: ethereum/contract - name: OldSmartContract - network: sepolia - source: - address: '0xOldContractAddress' - abi: Lock - startBlock: 5000000 - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Withdrawal - abis: - - name: Lock - file: ./abis/OldLock.json - eventHandlers: - - event: Withdrawal(uint256,uint256) - handler: handleOldWithdrawal - file: ./src/old-lock.ts - ``` - -2. **New Grafted Subgraph Manifest (subgraph.yaml)** - ```yaml - specVersion: 1.0.0 - schema: - file: ./schema.graphql - dataSources: - - kind: ethereum/contract - name: NewSmartContract - network: sepolia - source: - address: '0xNewContractAddress' - abi: Lock - startBlock: 6000001 # Block after the last indexed block - mapping: - kind: ethereum/events - apiVersion: 0.0.7 - language: wasm/assemblyscript - entities: - - Withdrawal - abis: - - name: Lock - file: ./abis/Lock.json - eventHandlers: - - event: Withdrawal(uint256,uint256) - handler: handleWithdrawal - file: ./src/lock.ts - features: - - grafting - graft: - base: QmBaseDeploymentID # Deployment ID of the failed subgraph - block: 6000000 # Last successfully indexed block - ``` - -**Explanation:** - -- **Data Source Update**: The new subgraph points to 0xNewContractAddress, which may be a fixed version of the smart contract. -- **Start Block**: Set to one block after the last successfully indexed block to avoid reprocessing the error. -- **Grafting Configuration**: - - **base**: Deployment ID of the failed subgraph. - - **block**: Block number where grafting should begin. - -3. **Deployment Steps** - - - **Update the Code**: Implement the hotfix in your mapping scripts (e.g., handleWithdrawal). - - **Adjust the Manifest**: As shown above, update the `subgraph.yaml` with grafting configurations. - - **Deploy the Subgraph**: - - Authenticate with the Graph CLI. - - Deploy the new subgraph using `graph deploy`. - -4. **Post-Deployment** - - **Verify Indexing**: Check that the subgraph is indexing correctly from the graft point. - - **Monitor Data**: Ensure that new data is being captured and the hotfix is effective. - - **Plan for Republish**: Schedule the deployment of a non-grafted version for long-term stability. - -## Warnings and Cautions - -While grafting is a powerful tool for deploying hotfixes quickly, there are specific scenarios where it should be avoided to maintain data integrity and ensure optimal performance. - -- **Incompatible Schema Changes**: If your hotfix requires altering the type of existing fields or removing fields from your schema, grafting is not suitable. Grafting expects the new subgraph’s schema to be compatible with the base subgraph’s schema. Incompatible changes can lead to data inconsistencies and errors because the existing data won’t align with the new schema. -- **Significant Mapping Logic Overhauls**: When the hotfix involves substantial modifications to your mapping logic—such as changing how events are processed or altering handler functions—grafting may not function correctly. The new logic might not be compatible with the data processed under the old logic, leading to incorrect data or failed indexing. -- **Deployments to The Graph Network**: Grafting is not recommended for subgraphs intended for The Graph’s decentralized network (mainnet). It can complicate indexing and may not be fully supported by all Indexers, potentially causing unexpected behavior or increased costs. For mainnet deployments, it’s safer to re-index the subgraph from scratch to ensure full compatibility and reliability. - -### Risk Management - -- **Data Integrity**: Incorrect block numbers can lead to data loss or duplication. -- **Testing**: Always test grafting in a development environment before deploying to production. - -## Conclusion - -Grafting is an effective strategy for deploying hotfixes in subgraph development, enabling you to: - -- **Quickly Recover** from critical errors without re-indexing. -- **Preserve Historical Data**, maintaining continuity for applications and users. -- **Ensure Service Availability** by minimizing downtime during critical fixes. - -However, it’s important to use grafting judiciously and follow best practices to mitigate risks. After stabilizing your subgraph with the hotfix, plan to deploy a non-grafted version to ensure long-term maintainability. - -## Additional Resources - -- **[Grafting Documentation](/cookbook/grafting/)**: Replace a Contract and Keep its History With Grafting -- **[Understanding Deployment IDs](/querying/querying-by-subgraph-id-vs-deployment-id/)**: Learn the difference between Deployment ID and Subgraph ID. - -By incorporating grafting into your subgraph development workflow, you can enhance your ability to respond to issues swiftly, ensuring that your data services remain robust and reliable. - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/grafting.mdx b/website/pages/ha/cookbook/grafting.mdx deleted file mode 100644 index 266b92432ced..000000000000 --- a/website/pages/ha/cookbook/grafting.mdx +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Replace a Contract and Keep its History With Grafting ---- - -In this guide, you will learn how to build and deploy new subgraphs by grafting existing subgraphs. - -## What is Grafting? - -Grafting reuses the data from an existing subgraph and starts indexing it at a later block. This is useful during development to get past simple errors in the mappings quickly or to temporarily get an existing subgraph working again after it has failed. Also, it can be used when adding a feature to a subgraph that takes long to index from scratch. - -The grafted subgraph can use a GraphQL schema that is not identical to the one of the base subgraph, but merely compatible with it. It has to be a valid subgraph schema in its own right, but may deviate from the base subgraph's schema in the following ways: - -- It adds or removes entity types -- It removes attributes from entity types -- It adds nullable attributes to entity types -- It turns non-nullable attributes into nullable attributes -- It adds values to enums -- It adds or removes interfaces -- It changes for which entity types an interface is implemented - -For more information, you can check: - -- [Grafting](https://thegraph.com/docs/en/developing/creating-a-subgraph#grafting-onto-existing-subgraphs) - -In this tutorial, we will be covering a basic usecase. We will replace an existing contract with an identical contract (with a new address, but the same code). Then, graft the existing subgraph onto the "base" subgraph that tracks the new contract. - -## Important Note on Grafting When Upgrading to the Network - -> **Caution**: if you are upgrading your subgraph from Subgraph Studio or the hosted service to the decentralized network, it is strongly recommended to avoid using grafting during the upgrade process. - -### Why Is This Important? - -Grafting is a powerful feature that allows you to "graft" one subgraph onto another, effectively transferring historical data from the existing subgraph to a new version. While this is an effective way to preserve data and save time on indexing, grafting may introduce complexities and potential issues when migrating from a hosted environment to the decentralized network. It is not possible to graft a subgraph from The Graph Network back to the hosted service or Subgraph Studio. - -### Best Practices - -**Initial Migration**: when you first deploy your subgraph to the decentralized network, do so without grafting. Ensure that the subgraph is stable and functioning as expected. - -**Subsequent Updates**: once your subgraph is live and stable on the decentralized network, you may use grafting for future versions to make the transition smoother and to preserve historical data. - -By adhering to these guidelines, you minimize risks and ensure a smoother migration process. - -## Building an Existing Subgraph - -Building subgraphs is an essential part of The Graph, described more in depth [here](http://localhost:3000/en/cookbook/quick-start/). To be able to build and deploy the existing subgraph used in this tutorial, the following repo is provided: - -- [Subgraph example repo](https://github.com/Shiyasmohd/grafting-tutorial) - -> Note: The contract used in the subgraph was taken from the following [Hackathon Starterkit](https://github.com/schmidsi/hackathon-starterkit). - -## Subgraph Manifest Definition - -The subgraph manifest `subgraph.yaml` identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest that you will use: - -```yaml -specVersion: 0.0.4 -schema: - file: ./schema.graphql -dataSources: - - kind: ethereum - name: Lock - network: sepolia - source: - address: '0xb3aabe721794b85fe4e72134795c2f93b4eb7e63' - abi: Lock - startBlock: 5955690 - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Withdrawal - abis: - - name: Lock - file: ./abis/Lock.json - eventHandlers: - - event: Withdrawal(uint256,uint256) - handler: handleWithdrawal - file: ./src/lock.ts -``` - -- The `Lock` data source is the abi and contract address we will get when we compile and deploy the contract -- The network should correspond to a indexed network being queried. Since we're running on Sepolia testnet, the network is `sepolia` -- The `mapping` section defines the triggers of interest and the functions that should be run in response to those triggers. In this case, we are listening for the `Withdrawal` event and calling the `handleWithdrawal` function when it is emitted. - -## Grafting Manifest Definition - -Grafting requires adding two new items to the original subgraph manifest: - -```yaml ---- -features: - - grafting # feature name -graft: - base: Qm... # subgraph ID of base subgraph - block: 1502122 # block number -``` - -- `features:` is a list of all used [feature names](developing/creating-a-subgraph/#experimental-features). -- `graft:` is a map of the `base` subgraph and the block to graft on to. The `block` is the block number to start indexing from. The Graph will copy the data of the base subgraph up to and including the given block and then continue indexing the new subgraph from that block on. - -The `base` and `block` values can be found by deploying two subgraphs: one for the base indexing and one with grafting - -## Deploying the Base Subgraph - -1. Go to [The Graph Studio UI](https://thegraph.com/studio/) and create a subgraph on Sepolia testnet called `graft-example` -2. Follow the directions in the `AUTH & DEPLOY` section on your subgraph page in the `graft-example` folder from the repo -3. Once finished, verify the subgraph is indexing properly. If you run the following command in The Graph Playground - -```graphql -{ - withdrawals(first: 5) { - id - amount - when - } -} -``` - -It returns something like this: - -``` -{ - "data": { - "withdrawals": [ - { - "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000", - "amount": "0", - "when": "1716394824" - }, - { - "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000", - "amount": "0", - "when": "1716394848" - } - ] - } -} -``` - -Once you have verified the subgraph is indexing properly, you can quickly update the subgraph with grafting. - -## Deploying the Grafting Subgraph - -The graft replacement subgraph.yaml will have a new contract address. This could happen when you update your dapp, redeploy a contract, etc. - -1. Go to [The Graph Studio UI](https://thegraph.com/studio/) and create a subgraph on Sepolia testnet called `graft-replacement` -2. Create a new manifest. The `subgraph.yaml` for `graph-replacement` contains a different contract address and new information about how it should graft. These are the `block` of the [last event emitted](https://sepolia.etherscan.io/tx/0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc452) you care about by the old contract and the `base` of the old subgraph. The `base` subgraph ID is the `Deployment ID` of your original `graph-example` subgraph. You can find this in The Graph Studio UI. -3. Follow the directions in the `AUTH & DEPLOY` section on your subgraph page in the `graft-replacement` folder from the repo -4. Once finished, verify the subgraph is indexing properly. If you run the following command in The Graph Playground - -```graphql -{ - withdrawals(first: 5) { - id - amount - when - } -} -``` - -It should return the following: - -``` -{ - "data": { - "withdrawals": [ - { - "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000", - "amount": "0", - "when": "1716394824" - }, - { - "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000", - "amount": "0", - "when": "1716394848" - }, - { - "id": "0x2410475f76a44754bae66d293d14eac34f98ec03a3689cbbb56a716d20b209af06000000", - "amount": "0", - "when": "1716429732" - } - ] - } -} -``` - -You can see that the `graft-replacement` subgraph is indexing from older `graph-example` data and newer data from the new contract address. The original contract emitted two `Withdrawal` events, [Event 1](https://sepolia.etherscan.io/tx/0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d) and [Event 2](https://sepolia.etherscan.io/tx/0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc452). The new contract emitted one `Withdrawal` after, [Event 3](https://sepolia.etherscan.io/tx/0x2410475f76a44754bae66d293d14eac34f98ec03a3689cbbb56a716d20b209af). The two previously indexed transactions (Event 1 and 2) and the new transaction (Event 3) were combined together in the `graft-replacement` subgraph. - -Congrats! You have succesfully grafted a subgraph onto another subgraph. - -## Additional Resources - -If you want more experience with grafting, here's a few examples for popular contracts: - -- [Curve](https://github.com/messari/subgraphs/blob/master/subgraphs/curve-finance/protocols/curve-finance/templates/curve.template.yaml) -- [ERC-721](https://github.com/messari/subgraphs/blob/master/subgraphs/erc721-metadata/subgraph.yaml) -- [Uniswap](https://github.com/messari/subgraphs/blob/master/subgraphs/uniswap-v3/protocols/uniswap-v3/config/templates/uniswap.v3.template.yaml), - -To become even more of a Graph expert, consider learning about other ways to handle changes in underlying datasources. Alternatives like [Data Source Templates](developing/creating-a-subgraph/#data-source-templates) can achieve similar results - -> Note: A lot of material from this article was taken from the previously published [Arweave article](/cookbook/arweave/) diff --git a/website/pages/ha/cookbook/how-to-secure-api-keys-using-nextjs-server-components.mdx b/website/pages/ha/cookbook/how-to-secure-api-keys-using-nextjs-server-components.mdx deleted file mode 100644 index e37d83acbe78..000000000000 --- a/website/pages/ha/cookbook/how-to-secure-api-keys-using-nextjs-server-components.mdx +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: How to Secure API Keys Using Next.js Server Components ---- - -## Overview - -We can use [Next.js server components](https://nextjs.org/docs/app/building-your-application/rendering/server-components) to properly secure our API key from exposure in the frontend of our dapp. To further increase our API key security, we can also [restrict our API key to certain subgraphs or domains in Subgraph Studio](/cookbook/upgrading-a-subgraph/#securing-your-api-key). - -In this cookbook, we will go over how to create a Next.js server component that queries a subgraph while also hiding the API key from the frontend. - -### Caveats - -- Next.js server components do not protect API keys from being drained using denial of service attacks. -- The Graph Network gateways have denial of service detection and mitigation strategies in place, however using server components may weaken these protections. -- Next.js server components introduce centralization risks as the server can go down. - -### Why It's Needed - -In a standard React application, API keys included in the frontend code can be exposed to the client-side, posing a security risk. While `.env` files are commonly used, they don't fully protect the keys since React's code is executed on the client side, exposing the API key in the headers. Next.js Server Components address this issue by handling sensitive operations server-side. - -### Using client-side rendering to query a subgraph - -![Client-side rendering](/img/api-key-client-side-rendering.png) - -### Prerequisites - -- An API key from [Subgraph Studio](https://thegraph.com/studio) -- Basic knowledge of Next.js and React. -- An existing Next.js project that uses the [App Router](https://nextjs.org/docs/app). - -## Step-by-Step Cookbook - -### Step 1: Set Up Environment Variables - -1. In our Next.js project root, create a `.env.local` file. -2. Add our API key: `API_KEY=`. - -### Step 2: Create a Server Component - -1. In our `components` directory, create a new file, `ServerComponent.js`. -2. Use the provided example code to set up the server component. - -### Step 3: Implement Server-Side API Request - -In `ServerComponent.js`, add the following code: - -```javascript -const API_KEY = process.env.API_KEY - -export default async function ServerComponent() { - const response = await fetch( - `https://gateway-arbitrum.network.thegraph.com/api/${API_KEY}/subgraphs/id/HUZDsRpEVP2AvzDCyzDHtdc64dyDxx8FQjzsmqSg4H3B`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - query: /* GraphQL */ ` - { - factories(first: 5) { - id - poolCount - txCount - totalVolumeUSD - } - } - `, - }), - }, - ) - - const responseData = await response.json() - const data = responseData.data - - return ( -
-

Server Component

- {data ? ( -
    - {data.factories.map((factory) => ( -
  • -

    ID: {factory.id}

    -

    Pool Count: {factory.poolCount}

    -

    Transaction Count: {factory.txCount}

    -

    Total Volume USD: {factory.totalVolumeUSD}

    -
  • - ))} -
- ) : ( -

Loading data...

- )} -
- ) -} -``` - -### Step 4: Use the Server Component - -1. In our page file (e.g., `pages/index.js`), import `ServerComponent`. -2. Render the component: - -```javascript -import ServerComponent from './components/ServerComponent' - -export default function Home() { - return ( -
- -
- ) -} -``` - -### Step 5: Run and Test Our Dapp - -Start our Next.js application using `npm run dev`. Verify that the server component is fetching data without exposing the API key. - -![Server-side rendering](/img/api-key-server-side-rendering.png) - -### Conclusion - -By utilizing Next.js Server Components, we've effectively hidden the API key from the client-side, enhancing the security of our application. This method ensures that sensitive operations are handled server-side, away from potential client-side vulnerabilities. Finally, be sure to explore [other API key security measures](/cookbook/upgrading-a-subgraph/#securing-your-api-key) to increase your API key security even further. diff --git a/website/pages/ha/cookbook/immutable-entities-bytes-as-ids.mdx b/website/pages/ha/cookbook/immutable-entities-bytes-as-ids.mdx deleted file mode 100644 index 725e53d1cf53..000000000000 --- a/website/pages/ha/cookbook/immutable-entities-bytes-as-ids.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Subgraph Best Practice 3 - Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs ---- - -## TLDR - -Using Immutable Entities and Bytes for IDs in our `schema.graphql` file [significantly improves ](https://thegraph.com/blog/two-simple-subgraph-performance-improvements/) indexing speed and query performance. - -## Immutable Entities - -To make an entity immutable, we simply add `(immutable: true)` to an entity. - -```graphql -type Transfer @entity(immutable: true) { - id: Bytes! - from: Bytes! - to: Bytes! - value: BigInt! -} -``` - -By making the `Transfer` entity immutable, graph-node is able to process the entity more efficiently, improving indexing speeds and query responsiveness. - -Immutable Entities structures will not change in the future. An ideal entity to become an Immutable Entity would be an entity that is directly logging on-chain event data, such as a `Transfer` event being logged as a `Transfer` entity. - -### Under the hood - -Mutable entities have a 'block range' indicating their validity. Updating these entities requires the graph node to adjust the block range of previous versions, increasing database workload. Queries also need filtering to find only live entities. Immutable entities are faster because they are all live and since they won't change, no checks or updates are required while writing, and no filtering is required during queries. - -### When not to use Immutable Entities - -If you have a field like `status` that needs to be modified over time, then you should not make the entity immutable. Otherwise, you should use immutable entities whenever possible. - -## Bytes as IDs - -Every entity requires an ID. In the previous example, we can see that the ID is already of the Bytes type. - -```graphql -type Transfer @entity(immutable: true) { - id: Bytes! - from: Bytes! - to: Bytes! - value: BigInt! -} -``` - -While other types for IDs are possible, such as String and Int8, it is recommended to use the Bytes type for all IDs due to character strings taking twice as much space as Byte strings to store binary data, and comparisons of UTF-8 character strings must take the locale into account which is much more expensive than the bytewise comparison used to compare Byte strings. - -### Reasons to Not Use Bytes as IDs - -1. If entity IDs must be human-readable such as auto-incremented numerical IDs or readable strings, Bytes for IDs should not be used. -2. If integrating a subgraph’s data with another data model that does not use Bytes as IDs, Bytes as IDs should not be used. -3. Indexing and querying performance improvements are not desired. - -### Concatenating With Bytes as IDs - -It is a common practice in many subgraphs to use string concatenation to combine two properties of an event into a single ID, such as using `event.transaction.hash.toHex() + "-" + event.logIndex.toString()`. However, as this returns a string, this significantly impedes subgraph indexing and querying performance. - -Instead, we should use the `concatI32()` method to concatenate event properties. This strategy results in a `Bytes` ID that is much more performant. - -```typescript -export function handleTransfer(event: TransferEvent): void { - let entity = new Transfer(event.transaction.hash.concatI32(event.logIndex.toI32())) - entity.from = event.params.from - entity.to = event.params.to - entity.value = event.params.value - - entity.blockNumber = event.block.number - entity.blockTimestamp = event.block.timestamp - entity.transactionHash = event.transaction.hash - - entity.save() -} -``` - -### Sorting With Bytes as IDs - -Sorting using Bytes as IDs is not optimal as seen in this example query and response. - -Query: - -```graphql -{ - transfers(first: 3, orderBy: id) { - id - from - to - value - } -} -``` - -Query response: - -```json -{ - "data": { - "transfers": [ - { - "id": "0x00010000", - "from": "0xabcd...", - "to": "0x1234...", - "value": "256" - }, - { - "id": "0x00020000", - "from": "0xefgh...", - "to": "0x5678...", - "value": "512" - }, - { - "id": "0x01000000", - "from": "0xijkl...", - "to": "0x9abc...", - "value": "1" - } - ] - } -} -``` - -The IDs are returned as hex. - -To improve sorting, we should create another field on the entity that is a BigInt. - -```graphql -type Transfer @entity { - id: Bytes! - from: Bytes! # address - to: Bytes! # address - value: BigInt! # unit256 - tokenId: BigInt! # uint256 -} -``` - -This will allow for sorting to be optimized sequentially. - -Query: - -```graphql -{ - transfers(first: 3, orderBy: tokenId) { - id - tokenId - } -} -``` - -Query Response: - -```json -{ - "data": { - "transfers": [ - { - "id": "0x…", - "tokenId": "1" - }, - { - "id": "0x…", - "tokenId": "2" - }, - { - "id": "0x…", - "tokenId": "3" - } - ] - } -} -``` - -## Conclusion - -Using both Immutable Entities and Bytes as IDs has been shown to markedly improve subgraph efficiency. Specifically, tests have highlighted up to a 28% increase in query performance and up to a 48% acceleration in indexing speeds. - -Read more about using Immutable Entities and Bytes as IDs in this blog post by David Lutterkort, a Software Engineer at Edge & Node: [Two Simple Subgraph Performance Improvements](https://thegraph.com/blog/two-simple-subgraph-performance-improvements/). - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/near.mdx b/website/pages/ha/cookbook/near.mdx deleted file mode 100644 index 47f1406bc033..000000000000 --- a/website/pages/ha/cookbook/near.mdx +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: Building Subgraphs on NEAR ---- - -> NEAR support in Graph Node and on the Hosted Service is in beta: please contact near@thegraph.com with any questions about building NEAR subgraphs! - -This guide is an introduction to building subgraphs indexing smart contracts on the [NEAR blockchain](https://docs.near.org/). - -## What is NEAR? - -[NEAR](https://near.org/) is a smart contract platform for building decentralized applications. Visit the [official documentation](https://docs.near.org/docs/concepts/new-to-near) for more information. - -## What are NEAR subgraphs? - -The Graph gives developers tools to process blockchain events and make the resulting data easily available via a GraphQL API, known individually as a subgraph. [Graph Node](https://github.com/graphprotocol/graph-node) is now able to process NEAR events, which means that NEAR developers can now build subgraphs to index their smart contracts. - -Subgraphs are event-based, which means that they listen for and then process on-chain events. There are currently two types of handlers supported for NEAR subgraphs: - -- Block handlers: these are run on every new block -- Receipt handlers: run every time a message is executed at a specified account - -[From the NEAR documentation](https://docs.near.org/docs/concepts/transaction#receipt): - -> A Receipt is the only actionable object in the system. When we talk about "processing a transaction" on the NEAR platform, this eventually means "applying receipts" at some point. - -## Building a NEAR Subgraph - -`@graphprotocol/graph-cli` is a command-line tool for building and deploying subgraphs. - -`@graphprotocol/graph-ts` is a library of subgraph-specific types. - -NEAR subgraph development requires `graph-cli` above version `0.23.0`, and `graph-ts` above version `0.23.0`. - -> Building a NEAR subgraph is very similar to building a subgraph that indexes Ethereum. - -There are three aspects of subgraph definition: - -**subgraph.yaml:** the subgraph manifest, defining the data sources of interest, and how they should be processed. NEAR is a new `kind` of data source. - -**schema.graphql:** a schema file that defines what data is stored for your subgraph, and how to query it via GraphQL. The requirements for NEAR subgraphs are covered by [the existing documentation](/developing/creating-a-subgraph#the-graphql-schema). - -**AssemblyScript Mappings:** [AssemblyScript code](/developing/graph-ts/api) that translates from the event data to the entities defined in your schema. NEAR support introduces NEAR-specific data types and new JSON parsing functionality. - -During subgraph development there are two key commands: - -```bash -$ graph codegen # generates types from the schema file identified in the manifest -$ graph build # generates Web Assembly from the AssemblyScript files, and prepares all the subgraph files in a /build folder -``` - -### Subgraph Manifest Definition - -The subgraph manifest (`subgraph.yaml`) identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest for a NEAR subgraph: - -```yaml -specVersion: 0.0.2 -schema: - file: ./src/schema.graphql # link to the schema file -dataSources: - - kind: near - network: near-mainnet - source: - account: app.good-morning.near # This data source will monitor this account - startBlock: 10662188 # Required for NEAR - mapping: - apiVersion: 0.0.5 - language: wasm/assemblyscript - blockHandlers: - - handler: handleNewBlock # the function name in the mapping file - receiptHandlers: - - handler: handleReceipt # the function name in the mapping file - file: ./src/mapping.ts # link to the file with the Assemblyscript mappings -``` - -- NEAR subgraphs introduce a new `kind` of data source (`near`) -- The `network` should correspond to a network on the hosting Graph Node. On the Hosted Service, NEAR's mainnet is `near-mainnet`, and NEAR's testnet is `near-testnet` -- NEAR data sources introduce an optional `source.account` field, which is a human-readable ID corresponding to a [NEAR account](https://docs.near.org/docs/concepts/account). This can be an account or a sub-account. -- NEAR data sources introduce an alternative optional `source.accounts` field, which contains optional suffixes and prefixes. At least prefix or suffix must be specified, they will match the any account starting or ending with the list of values respectively. The example below would match: `[app|good].*[morning.near|morning.testnet]`. If only a list of prefixes or suffixes is necessary the other field can be omitted. - -```yaml -accounts: - prefixes: - - app - - good - suffixes: - - morning.near - - morning.testnet -``` - -NEAR data sources support two types of handlers: - -- `blockHandlers`: run on every new NEAR block. No `source.account` is required. -- `receiptHandlers`: run on every receipt where the data source's `source.account` is the recipient. Note that only exact matches are processed ([subaccounts](https://docs.near.org/docs/concepts/account#subaccounts) must be added as independent data sources). - -### Schema Definition - -Schema definition describes the structure of the resulting subgraph database and the relationships between entities. This is agnostic of the original data source. There are more details on subgraph schema definition [here](/developing/creating-a-subgraph#the-graphql-schema). - -### AssemblyScript Mappings - -The handlers for processing events are written in [AssemblyScript](https://www.assemblyscript.org/). - -NEAR indexing introduces NEAR-specific data types to the [AssemblyScript API](/developing/graph-ts/api). - -```typescript - -class ExecutionOutcome { - gasBurnt: u64, - blockHash: Bytes, - id: Bytes, - logs: Array, - receiptIds: Array, - tokensBurnt: BigInt, - executorId: string, - } - -class ActionReceipt { - predecessorId: string, - receiverId: string, - id: CryptoHash, - signerId: string, - gasPrice: BigInt, - outputDataReceivers: Array, - inputDataIds: Array, - actions: Array, - } - -class BlockHeader { - height: u64, - prevHeight: u64,// Always zero when version < V3 - epochId: Bytes, - nextEpochId: Bytes, - chunksIncluded: u64, - hash: Bytes, - prevHash: Bytes, - timestampNanosec: u64, - randomValue: Bytes, - gasPrice: BigInt, - totalSupply: BigInt, - latestProtocolVersion: u32, - } - -class ChunkHeader { - gasUsed: u64, - gasLimit: u64, - shardId: u64, - chunkHash: Bytes, - prevBlockHash: Bytes, - balanceBurnt: BigInt, - } - -class Block { - author: string, - header: BlockHeader, - chunks: Array, - } - -class ReceiptWithOutcome { - outcome: ExecutionOutcome, - receipt: ActionReceipt, - block: Block, - } -``` - -These types are passed to block & receipt handlers: - -- Block handlers will receive a `Block` -- Receipt handlers will receive a `ReceiptWithOutcome` - -Otherwise, the rest of the [AssemblyScript API](/developing/graph-ts/api) is available to NEAR subgraph developers during mapping execution. - -This includes a new JSON parsing function - logs on NEAR are frequently emitted as stringified JSONs. A new `json.fromString(...)` function is available as part of the [JSON API](/developing/graph-ts/api#json-api) to allow developers to easily process these logs. - -## Deploying a NEAR Subgraph - -Once you have a built subgraph, it is time to deploy it to Graph Node for indexing. NEAR subgraphs can be deployed to any Graph Node `>=v0.26.x` (this version has not yet been tagged & released). - -The Graph's Hosted Service currently supports indexing NEAR mainnet and testnet in beta, with the following network names: - -- `near-mainnet` -- `near-testnet` - -More information on creating and deploying subgraphs on the Hosted Service can be found [here](/deploying/deploying-a-subgraph-to-hosted). - -As a quick primer - the first step is to "create" your subgraph - this only needs to be done once. On the Hosted Service, this can be done from [your Dashboard](https://thegraph.com/hosted-service/dashboard): "Add Subgraph". - -Once your subgraph has been created, you can deploy your subgraph by using the `graph deploy` CLI command: - -```sh -$ graph create --node subgraph/name # creates a subgraph on a local Graph Node (on the Hosted Service, this is done via the UI) -$ graph deploy --node --ipfs https://api.thegraph.com/ipfs/ # uploads the build files to a specified IPFS endpoint, and then deploys the subgraph to a specified Graph Node based on the manifest IPFS hash -``` - -The node configuration will depend on where the subgraph is being deployed. - -### Hosted Service - -```sh -graph deploy --node https://api.thegraph.com/deploy/ --ipfs https://api.thegraph.com/ipfs/ --access-token -``` - -### Local Graph Node (based on default configuration) - -```sh -graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 -``` - -Once your subgraph has been deployed, it will be indexed by Graph Node. You can check its progress by querying the subgraph itself: - -```graphql -{ - _meta { - block { - number - } - } -} -``` - -### Indexing NEAR with a Local Graph Node - -Running a Graph Node that indexes NEAR has the following operational requirements: - -- NEAR Indexer Framework with Firehose instrumentation -- NEAR Firehose Component(s) -- Graph Node with Firehose endpoint configured - -We will provide more information on running the above components soon. - -## Querying a NEAR Subgraph - -The GraphQL endpoint for NEAR subgraphs is determined by the schema definition, with the existing API interface. Please visit the [GraphQL API documentation](/querying/graphql-api) for more information. - -## Example Subgraphs - -Here are some example subgraphs for reference: - -[NEAR Blocks](https://github.com/graphprotocol/graph-tooling/tree/main/examples/near-blocks) - -[NEAR Receipts](https://github.com/graphprotocol/graph-tooling/tree/main/examples/near-receipts) - -## FAQ - -### How does the beta work? - -NEAR support is in beta, which means that there may be changes to the API as we continue to work on improving the integration. Please email near@thegraph.com so that we can support you in building NEAR subgraphs, and keep you up to date on the latest developments! - -### Can a subgraph index both NEAR and EVM chains? - -No, a subgraph can only support data sources from one chain/network. - -### Can subgraphs react to more specific triggers? - -Currently, only Block and Receipt triggers are supported. We are investigating triggers for function calls to a specified account. We are also interested in supporting event triggers, once NEAR has native event support. - -### Will receipt handlers trigger for accounts and their sub-accounts? - -If an `account` is specified, that will only match the exact account name. It is possible to match sub-accounts by specifying an `accounts` field, with `suffixes` and `prefixes` specified to match accounts and sub-accounts, for example the following would match all `mintbase1.near` sub-accounts: - -```yaml -accounts: - suffixes: - - mintbase1.near -``` - -### Can NEAR subgraphs make view calls to NEAR accounts during mappings? - -This is not supported. We are evaluating whether this functionality is required for indexing. - -### Can I use data source templates in my NEAR subgraph? - -This is not currently supported. We are evaluating whether this functionality is required for indexing. - -### Ethereum subgraphs support "pending" and "current" versions, how can I deploy a "pending" version of a NEAR subgraph? - -Pending functionality is not yet supported for NEAR subgraphs. In the interim, you can deploy a new version to a different "named" subgraph, and then when that is synced with the chain head, you can redeploy to your primary "named" subgraph, which will use the same underlying deployment ID, so the main subgraph will be instantly synced. - -### My question hasn't been answered, where can I get more help building NEAR subgraphs? - -If it is a general question about subgraph development, there is a lot more information in the rest of the [Developer documentation](/quick-start). Otherwise please join [The Graph Protocol Discord](https://discord.gg/graphprotocol) and ask in the #near channel or email near@thegraph.com. - -## References - -- [NEAR developer documentation](https://docs.near.org/docs/develop/basics/getting-started) diff --git a/website/pages/ha/cookbook/pruning.mdx b/website/pages/ha/cookbook/pruning.mdx deleted file mode 100644 index d79d5b8911f9..000000000000 --- a/website/pages/ha/cookbook/pruning.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Subgraph Best Practice 1 - Improve Query Speed with Subgraph Pruning ---- - -## TLDR - -[Pruning](/developing/creating-a-subgraph/#prune) removes archival entities from the subgraph’s database up to a given block, and removing unused entities from a subgraph’s database will improve a subgraph’s query performance, often dramatically. Using `indexerHints` is an easy way to prune a subgraph. - -## How to Prune a Subgraph With `indexerHints` - -Add a section called `indexerHints` in the manifest. - -`indexerHints` has three `prune` options: - -- `prune: auto`: Retains the minimum necessary history as set by the Indexer, optimizing query performance. This is the generally recommended setting and is the default for all subgraphs created by `graph-cli` >= 0.66.0. -- `prune: `: Sets a custom limit on the number of historical blocks to retain. -- `prune: never`: No pruning of historical data; retains the entire history and is the default if there is no `indexerHints` section. `prune: never` should be selected if [Time Travel Queries](/querying/graphql-api/#time-travel-queries) are desired. - -We can add `indexerHints` to our subgraphs by updating our `subgraph.yaml`: - -```yaml -specVersion: 1.0.0 -schema: - file: ./schema.graphql -indexerHints: - prune: auto -dataSources: - - kind: ethereum/contract - name: Contract - network: mainnet -``` - -## Important Considerations - -- If [Time Travel Queries](/querying/graphql-api/#time-travel-queries) are desired as well as pruning, pruning must be performed accurately to retain Time Travel Query functionality. Due to this, it is generally not recommended to use `indexerHints: prune: auto` with Time Travel Queries. Instead, prune using `indexerHints: prune: ` to accurately prune to a block height that preserves the historical data required by Time Travel Queries, or use `prune: never` to maintain all data. - -- It is not possible to [graft](/cookbook/grafting/) at a block height that has been pruned. If grafting is routinely performed and pruning is desired, it is recommended to use `indexerHints: prune: ` that will accurately retain a set number of blocks (e.g., enough for six months). - -## Conclusion - -Pruning using `indexerHints` is a best practice for subgraph development, offering significant query performance improvements. - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/subgraph-debug-forking.mdx b/website/pages/ha/cookbook/subgraph-debug-forking.mdx deleted file mode 100644 index 7ac3bf96ca10..000000000000 --- a/website/pages/ha/cookbook/subgraph-debug-forking.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Quick and Easy Subgraph Debugging Using Forks ---- - -As with many systems processing large amounts of data, The Graph's Indexers (Graph nodes) may take quite some time to sync-up your subgraph with the target blockchain. The discrepancy between quick changes with the purpose of debugging and long wait times needed for indexing is extremely counterproductive and we are well aware of that. This is why we are introducing **subgraph forking**, developed by [LimeChain](https://limechain.tech/), and in this article I will show you how this feature can be used to substantially speed-up subgraph debugging! - -## Ok, what is it? - -**Subgraph forking** is the process of lazily fetching entities from _another_ subgraph's store (usually a remote one). - -In the context of debugging, **subgraph forking** allows you to debug your failed subgraph at block _X_ without needing to wait to sync-up to block _X_. - -## What?! How? - -When you deploy a subgraph to a remote Graph node for indexing and it fails at block _X_, the good news is that the Graph node will still serve GraphQL queries using its store, which is synced-up to block _X_. That's great! This means we can take advantage of this "up-to-date" store to fix the bugs arising when indexing block _X_. - -In a nutshell, we are going to _fork the failing subgraph_ from a remote Graph node that is guaranteed to have the subgraph indexed up to block _X_ in order to provide the locally deployed subgraph being debugged at block _X_ an up-to-date view of the indexing state. - -## Please, show me some code! - -To stay focused on subgraph debugging, let's keep things simple and run along with the [example-subgraph](https://github.com/graphprotocol/graph-tooling/tree/main/examples/ethereum-gravatar) indexing the Ethereum Gravity smart contract. - -Here are the handlers defined for indexing `Gravatar`s, with no bugs whatsoever: - -```tsx -export function handleNewGravatar(event: NewGravatar): void { - let gravatar = new Gravatar(event.params.id.toHex().toString()) - gravatar.owner = event.params.owner - gravatar.displayName = event.params.displayName - gravatar.imageUrl = event.params.imageUrl - gravatar.save() -} - -export function handleUpdatedGravatar(event: UpdatedGravatar): void { - let gravatar = Gravatar.load(event.params.id.toI32().toString()) - if (gravatar == null) { - log.critical('Gravatar not found!', []) - return - } - gravatar.owner = event.params.owner - gravatar.displayName = event.params.displayName - gravatar.imageUrl = event.params.imageUrl - gravatar.save() -} -``` - -Oops, how unfortunate, when I deploy my perfect looking subgraph to the [Hosted Service](https://thegraph.com/hosted-service/) it fails with the _"Gravatar not found!"_ error. - -The usual way to attempt a fix is: - -1. Make a change in the mappings source, which you believe will solve the issue (while I know it won't). -2. Re-deploy the subgraph to the [Hosted Service](https://thegraph.com/hosted-service/) (or another remote Graph node). -3. Wait for it to sync-up. -4. If it breaks again go back to 1, otherwise: Hooray! - -It is indeed pretty familiar to an ordinary debug process, but there is one step that horribly slows down the process: _3. Wait for it to sync-up._ - -Using **subgraph forking** we can essentially eliminate this step. Here is how it looks: - -0. Spin-up a local Graph node with the **_appropriate fork-base_** set. -1. Make a change in the mappings source, which you believe will solve the issue. -2. Deploy to the local Graph node, **_forking the failing subgraph_** and **_starting from the problematic block_**. -3. If it breaks again, go back to 1, otherwise: Hooray! - -Now, you may have 2 questions: - -1. fork-base what??? -2. Forking who?! - -And I answer: - -1. `fork-base` is the "base" URL, such that when the _subgraph id_ is appended the resulting URL (`/`) is a valid GraphQL endpoint for the subgraph's store. -2. Forking is easy, no need to sweat: - -```bash -$ graph deploy --debug-fork --ipfs http://localhost:5001 --node http://localhost:8020 -``` - -Also, don't forget to set the `dataSources.source.startBlock` field in the subgraph manifest to the number of the problematic block, so you can skip indexing unnecessary blocks and take advantage of the fork! - -So, here is what I do: - -0. I spin-up a local graph node ([here is how to do it](https://github.com/graphprotocol/graph-node#running-a-local-graph-node)) with the `fork-base` option set to: `https://api.thegraph.com/subgraphs/id/`, since I will fork a subgraph, the buggy one I deployed earlier, from the [HostedService](https://thegraph.com/hosted-service/). - -``` -$ cargo run -p graph-node --release -- \ - --postgres-url postgresql://USERNAME[:PASSWORD]@localhost:5432/graph-node \ - --ethereum-rpc NETWORK_NAME:[CAPABILITIES]:URL \ - --ipfs 127.0.0.1:5001 - --fork-base https://api.thegraph.com/subgraphs/id/ -``` - -1. After careful inspection I notice that there is a mismatch in the `id` representations used when indexing `Gravatar`s in my two handlers. While `handleNewGravatar` converts it to a hex (`event.params.id.toHex()`), `handleUpdatedGravatar` uses an int32 (`event.params.id.toI32()`) which causes the `handleUpdatedGravatar` to panic with "Gravatar not found!". I make them both convert the `id` to a hex. -2. After I made the changes I deploy my subgraph to the local Graph node, **_forking the failing subgraph_** and setting `dataSources.source.startBlock` to `6190343` in `subgraph.yaml`: - -```bash -$ graph deploy gravity --debug-fork QmNp169tKvomnH3cPXTfGg4ZEhAHA6kEq5oy1XDqAxqHmW --ipfs http://localhost:5001 --node http://localhost:8020 -``` - -3. I inspect the logs produced by the local Graph node and, Hooray!, everything seems to be working. -4. I deploy my now bug-free subgraph to a remote Graph node and live happily ever after! (no potatoes tho) -5. The end... diff --git a/website/pages/ha/cookbook/subgraph-uncrashable.mdx b/website/pages/ha/cookbook/subgraph-uncrashable.mdx deleted file mode 100644 index 989310a3f9a0..000000000000 --- a/website/pages/ha/cookbook/subgraph-uncrashable.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Safe Subgraph Code Generator ---- - -[Subgraph Uncrashable](https://float-capital.github.io/float-subgraph-uncrashable/) is a code generation tool that generates a set of helper functions from the graphql schema of a project. It ensures that all interactions with entities in your subgraph are completely safe and consistent. - -## Why integrate with Subgraph Uncrashable? - -- **Continuous Uptime**. Mishandled entities may cause subgraphs to crash, which can be disruptive for projects that are dependent on The Graph. Set up helper functions to make your subgraphs “uncrashable” and ensure business continuity. - -- **Completely Safe**. Common problems seen in subgraph development are issues of loading undefined entities, not setting or initializing all values of entities, and race conditions on loading and saving entities. Ensure all interactions with entities are completely atomic. - -- **User Configurable** Set default values and configure the level of security checks that suits your individual project's needs. Warning logs are recorded indicating where there is a breach of subgraph logic to help patch the issue to ensure data accuracy. - -**Key Features** - -- The code generation tool accommodates **all** subgraph types and is configurable for users to set sane defaults on values. The code generation will use this config to generate helper functions that are to the users specification. - -- The framework also includes a way (via the config file) to create custom, but safe, setter functions for groups of entity variables. This way it is impossible for the user to load/use a stale graph entity and it is also impossible to forget to save or set a variable that is required by the function. - -- Warning logs are recorded as logs indicating where there is a breach of subgraph logic to help patch the issue to ensure data accuracy. These logs can be viewed in the The Graph's hosted service under the 'Logs' section. - -Subgraph Uncrashable can be run as an optional flag using the Graph CLI codegen command. - -```sh -graph codegen -u [options] [] -``` - -Visit the [subgraph uncrashable documentation](https://float-capital.github.io/float-subgraph-uncrashable/docs/) or watch this [video tutorial](https://float-capital.github.io/float-subgraph-uncrashable/docs/tutorial) to learn more and to get started with developing safer subgraphs. diff --git a/website/pages/ha/cookbook/substreams-powered-subgraphs.mdx b/website/pages/ha/cookbook/substreams-powered-subgraphs.mdx deleted file mode 100644 index 6b84c84358c8..000000000000 --- a/website/pages/ha/cookbook/substreams-powered-subgraphs.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: Substreams-powered subgraphs ---- - -[Substreams](/substreams) is a new framework for processing blockchain data, developed by StreamingFast for The Graph Network. A substreams modules can output entity changes, which are compatible with Subgraph entities. A subgraph can use such a Substreams module as a data source, bringing the indexing speed and additional data of Substreams to subgraph developers. - -## Requirements - -This cookbook requires [yarn](https://yarnpkg.com/), [the dependencies necessary for local Substreams development](https://substreams.streamingfast.io/developers-guide/installation-requirements), and the latest version of Graph CLI (>=0.52.0): - -``` -npm install -g @graphprotocol/graph-cli -``` - -## Get the cookbook - -> This cookbook uses this [Substreams-powered subgraph as a reference](https://github.com/graphprotocol/graph-tooling/tree/main/examples/substreams-powered-subgraph). - -``` -graph init --from-example substreams-powered-subgraph -``` - -## Defining a Substreams package - -A Substreams package is composed of types (defined as [Protocol Buffers](https://protobuf.dev/)), modules (written in Rust), and a `substreams.yaml` file which references the types, and specifies how modules are triggered. [Visit the Substreams documentation to learn more about Substreams development](/substreams), and check out [awesome-substreams](https://github.com/pinax-network/awesome-substreams) and the [Substreams cookbook](https://github.com/pinax-network/substreams-cookbook) for more examples. - -The Substreams package in question detects contract deployments on Mainnet Ethereum, tracking the creation block and timestamp for all newly deployed contracts. To do this, there is a dedicated `Contract` type in `/proto/example.proto` ([learn more about defining Protocol Buffers](https://protobuf.dev/programming-guides/proto3/#simple)): - -```proto -syntax = "proto3"; - -package example; - -message Contracts { - repeated Contract contracts = 1; -} - -message Contract { - string address = 1; - uint64 blockNumber = 2; - string timestamp = 3; - uint64 ordinal = 4; -} -``` - -The core logic of the Substreams package is a `map_contract` module in `lib.rs`, which processes every block, filtering for Create calls which did not revert, returning `Contracts`: - -``` -#[substreams::handlers::map] -fn map_contract(block: eth::v2::Block) -> Result { - let contracts = block - .transactions() - .flat_map(|tx| { - tx.calls - .iter() - .filter(|call| !call.state_reverted) - .filter(|call| call.call_type == eth::v2::CallType::Create as i32) - .map(|call| Contract { - address: format!("0x{}", Hex(&call.address)), - block_number: block.number, - timestamp: block.timestamp_seconds().to_string(), - ordinal: tx.begin_ordinal, - }) - }) - .collect(); - Ok(Contracts { contracts }) -} -``` - -A Substreams package can be used by a subgraph as long as it has a module which outputs compatible entity changes. The example Substreams package has an additional `graph_out` module in `lib.rs` which returns a `substreams_entity_change::pb::entity::EntityChanges` output, which can be processed by Graph Node. - -> The `substreams_entity_change` crate also has a dedicated `Tables` function for simply generating entity changes ([documentation](https://docs.rs/substreams-entity-change/1.2.2/substreams_entity_change/tables/index.html)). The Entity Changes generated must be compatible with the `schema.graphql` entities defined in the `subgraph.graphql` of the corresponding subgraph. - -``` -#[substreams::handlers::map] -pub fn graph_out(contracts: Contracts) -> Result { - // hash map of name to a table - let mut tables = Tables::new(); - - for contract in contracts.contracts.into_iter() { - tables - .create_row("Contract", contract.address) - .set("timestamp", contract.timestamp) - .set("blockNumber", contract.block_number); - } - - Ok(tables.to_entity_changes()) -} -``` - -These types and modules are pulled together in `substreams.yaml`: - -``` -specVersion: v0.1.0 -package: - name: 'substreams_test' # the name to be used in the .spkg - version: v1.0.1 # the version to use when creating the .spkg - -imports: # dependencies - entity: https://github.com/streamingfast/substreams-entity-change/releases/download/v0.2.1/substreams-entity-change-v0.2.1.spkg - -protobuf: # specifies custom types for use by Substreams modules - files: - - example.proto - importPaths: - - ./proto - -binaries: - default: - type: wasm/rust-v1 - file: ./target/wasm32-unknown-unknown/release/substreams.wasm - -modules: # specify modules with their inputs and outputs. - - name: map_contract - kind: map - inputs: - - source: sf.ethereum.type.v2.Block - output: - type: proto:test.Contracts - - - name: graph_out - kind: map - inputs: - - map: map_contract - output: - type: proto:substreams.entity.v1.EntityChanges # this type can be consumed by Graph Node - -``` - -You can check the overall "flow" from a Block, to `map_contract` to `graph_out` by running `substreams graph`: - -```mermaid -graph TD; - map_contract[map: map_contract]; - sf.ethereum.type.v2.Block[source: sf.ethereum.type.v2.Block] --> map_contract; - graph_out[map: graph_out]; - map_contract --> graph_out; -``` - -To prepare this Substreams package for consumption by a subgraph, you must run the following commands: - -```bash -yarn substreams:protogen # generates types in /src/pb -yarn substreams:build # builds the substreams -yarn substreams:package # packages the substreams in a .spkg file - -# alternatively, yarn substreams:prepare calls all of the above commands -``` - -> These scripts are defined in the `package.json` file if you want to understand the underlying substreams commands - -This generates a `spkg` file based on the package name and version from `substreams.yaml`. The `spkg` file has all the information which Graph Node needs to ingest this Substreams package. - -> If you update the Substreams package, depending on the changes you make, you may need to run some or all of the above commands so that the `spkg` is up to date. - -## Defining a Substreams-powered subgraph - -Substreams-powered subgraphs introduce a new `kind` of data source, "substreams". Such subgraphs can only have one data source. - -This data source must specify the indexed network, the Substreams package (`spkg`) as a relative file location, and the module within that Substreams package which produces subgraph-compatible entity changes (in this case `map_entity_changes`, from the Substreams package above). The mapping is specified, but simply identifies the mapping kind ("substreams/graph-entities") and the apiVersion. - -> Currently the Subgraph Studio and The Graph Network support Substreams-powered subgraphs which index `mainnet` (Mainnet Ethereum). - -```yaml -specVersion: 0.0.4 -description: Ethereum Contract Tracking Subgraph (powered by Substreams) -repository: https://github.com/graphprotocol/graph-tooling -schema: - file: schema.graphql -dataSources: - - kind: substreams - name: substream_test - network: mainnet - source: - package: - moduleName: graph_out - file: substreams-test-v1.0.1.spkg - mapping: - kind: substreams/graph-entities - apiVersion: 0.0.5 -``` - -The `subgraph.yaml` also references a schema file. The requirements for this file are unchanged, but the entities specified must be compatible with the entity changes produced by the Substreams module referenced in the `subgraph.yaml`. - -```graphql -type Contract @entity { - id: ID! - - "The timestamp when the contract was deployed" - timestamp: String! - - "The block number of the contract deployment" - blockNumber: BigInt! -} -``` - -Given the above, subgraph developers can use Graph CLI to deploy this Substreams-powered subgraph. - -> Substreams-powered subgraphs indexing mainnet Ethereum can be deployed to the [Subgraph Studio](https://thegraph.com/studio/). - -```bash -yarn install # install graph-cli -yarn subgraph:build # build the subgraph -yarn subgraph:deploy # deploy the subgraph -``` - -That's it! You have built and deployed a Substreams-powered subgraph. - -## Serving Substreams-powered subgraphs - -In order to serve Substreams-powered subgraphs, Graph Node must be configured with a Substreams provider for the relevant network, as well as a Firehose or RPC to track the chain head. These providers can be configured via a `config.toml` file: - -```toml -[chains.mainnet] -shard = "main" -protocol = "ethereum" -provider = [ - { label = "substreams-provider-mainnet", - details = { type = "substreams", - url = "https://mainnet-substreams-url.grpc.substreams.io/", - token = "exampletokenhere" }}, - { label = "firehose-provider-mainnet", - details = { type = "firehose", - url = "https://mainnet-firehose-url.grpc.firehose.io/", - token = "exampletokenhere" }}, -] -``` diff --git a/website/pages/ha/cookbook/timeseries.mdx b/website/pages/ha/cookbook/timeseries.mdx deleted file mode 100644 index 88ee70005a6e..000000000000 --- a/website/pages/ha/cookbook/timeseries.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Subgraph Best Practice 5 - Simplify and Optimize with Timeseries and Aggregations ---- - -## TLDR - -Leveraging the new time-series and aggregations feature in subgraphs can significantly enhance both indexing speed and query performance. - -## Overview - -Timeseries and aggregations reduce data processing overhead and accelerate queries by offloading aggregation computations to the database and simplifying mapping code. This approach is particularly effective when handling large volumes of time-based data. - -## Benefits of Timeseries and Aggregations - -1. Improved Indexing Time - -- Less Data to Load: Mappings handle less data since raw data points are stored as immutable timeseries entities. -- Database-Managed Aggregations: Aggregations are automatically computed by the database, reducing the workload on the mappings. - -2. Simplified Mapping Code - -- No Manual Calculations: Developers no longer need to write complex aggregation logic in mappings. -- Reduced Complexity: Simplifies code maintenance and minimizes the potential for errors. - -3. Dramatically Faster Queries - -- Immutable Data: All timeseries data is immutable, enabling efficient storage and retrieval. -- Efficient Data Separation: Aggregates are stored separately from raw timeseries data, allowing queries to process significantly less data—often several orders of magnitude less. - -### Important Considerations - -- Immutable Data: Timeseries data cannot be altered once written, ensuring data integrity and simplifying indexing. -- Automatic ID and Timestamp Management: id and timestamp fields are automatically managed by graph-node, reducing potential errors. -- Efficient Data Storage: By separating raw data from aggregates, storage is optimized, and queries run faster. - -## How to Implement Timeseries and Aggregations - -### Defining Timeseries Entities - -A timeseries entity represents raw data points collected over time. It is defined with the `@entity(timeseries: true)` annotation. Key requirements: - -- Immutable: Timeseries entities are always immutable. -- Mandatory Fields: - - `id`: Must be of type `Int8!` and is auto-incremented. - - `timestamp`: Must be of type `Timestamp!` and is automatically set to the block timestamp. - -Example: - -```graphql -type Data @entity(timeseries: true) { - id: Int8! - timestamp: Timestamp! - price: BigDecimal! -} -``` - -### Defining Aggregation Entities - -An aggregation entity computes aggregated values from a timeseries source. It is defined with the `@aggregation` annotation. Key components: - -- Annotation Arguments: - - `intervals`: Specifies time intervals (e.g., `["hour", "day"]`). - -Example: - -```graphql -type Stats @aggregation(intervals: ["hour", "day"], source: "Data") { - id: Int8! - timestamp: Timestamp! - sum: BigDecimal! @aggregate(fn: "sum", arg: "price") -} -``` - -In this example, Stats aggregates the price field from Data over hourly and daily intervals, computing the sum. - -### Querying Aggregated Data - -Aggregations are exposed via query fields that allow filtering and retrieval based on dimensions and time intervals. - -Example: - -```graphql -{ - tokenStats( - interval: "hour" - where: { token: "0x1234567890abcdef", timestamp_gte: "1704164640000000", timestamp_lt: "1704251040000000" } - ) { - id - timestamp - token { - id - } - totalVolume - priceUSD - count - } -} -``` - -### Using Dimensions in Aggregations - -Dimensions are non-aggregated fields used to group data points. They enable aggregations based on specific criteria, such as a token in a financial application. - -Example: - -### Timeseries Entity - -```graphql -type TokenData @entity(timeseries: true) { - id: Int8! - timestamp: Timestamp! - token: Token! - amount: BigDecimal! - priceUSD: BigDecimal! -} -``` - -### Aggregation Entity with Dimension - -```graphql -type TokenStats @aggregation(intervals: ["hour", "day"], source: "TokenData") { - id: Int8! - timestamp: Timestamp! - token: Token! - totalVolume: BigDecimal! @aggregate(fn: "sum", arg: "amount") - priceUSD: BigDecimal! @aggregate(fn: "last", arg: "priceUSD") - count: Int8! @aggregate(fn: "count", cumulative: true) -} -``` - -- Dimension Field: token groups the data, so aggregates are computed per token. -- Aggregates: - - totalVolume: Sum of amount. - - priceUSD: Last recorded priceUSD. - - count: Cumulative count of records. - -### Aggregation Functions and Expressions - -Supported aggregation functions: - -- sum -- count -- min -- max -- first -- last - -### The arg in @aggregate can be - -- A field name from the timeseries entity. -- An expression using fields and constants. - -### Examples of Aggregation Expressions - -- Sum Token Value: @aggregate(fn: "sum", arg: "priceUSD \_ amount") -- Maximum Positive Amount: @aggregate(fn: "max", arg: "greatest(amount0, amount1, 0)") -- Conditional Sum: @aggregate(fn: "sum", arg: "case when amount0 > amount1 then amount0 else 0 end") - -Supported operators and functions include basic arithmetic (+, -, \_, /), comparison operators, logical operators (and, or, not), and SQL functions like greatest, least, coalesce, etc. - -### Query Parameters - -- interval: Specifies the time interval (e.g., "hour"). -- where: Filters based on dimensions and timestamp ranges. -- timestamp_gte / timestamp_lt: Filters for start and end times (microseconds since epoch). - -### Notes - -- Sorting: Results are automatically sorted by timestamp and id in descending order. -- Current Data: An optional current argument can include the current, partially filled interval. - -### Conclusion - -Implementing timeseries and aggregations in subgraphs is a best practice for projects dealing with time-based data. This approach: - -- Enhances Performance: Speeds up indexing and querying by reducing data processing overhead. -- Simplifies Development: Eliminates the need for manual aggregation logic in mappings. -- Scales Efficiently: Handles large volumes of data without compromising on speed or responsiveness. - -By adopting this pattern, developers can build more efficient and scalable subgraphs, providing faster and more reliable data access to end-users. To learn more about implementing timeseries and aggregations, refer to the [Timeseries and Aggregations Readme](https://github.com/graphprotocol/graph-node/blob/master/docs/aggregations.md) and consider experimenting with this feature in your subgraphs. - -## Subgraph Best Practices 1-6 - -1. [Improve Query Speed with Subgraph Pruning](/cookbook/pruning/) - -2. [Improve Indexing and Query Responsiveness by Using @derivedFrom](/cookbook/derivedfrom/) - -3. [Improve Indexing and Query Performance by Using Immutable Entities and Bytes as IDs](/cookbook/immutable-entities-bytes-as-ids/) - -4. [Improve Indexing Speed by Avoiding `eth_calls`](/cookbook/avoid-eth-calls/) - -5. [Simplify and Optimize with Timeseries and Aggregations](/cookbook/timeseries/) - -6. [Use Grafting for Quick Hotfix Deployment](/cookbook/grafting-hotfix/) diff --git a/website/pages/ha/cookbook/transfer-to-the-graph.mdx b/website/pages/ha/cookbook/transfer-to-the-graph.mdx deleted file mode 100644 index 287cd7d81b4b..000000000000 --- a/website/pages/ha/cookbook/transfer-to-the-graph.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Tranfer to The Graph ---- - -Quickly upgrade your subgraphs from any platform to [The Graph's decentralized network](https://thegraph.com/networks/). - -## Benefits of Switching to The Graph - -- Use the same subgraph that your apps already use with zero-downtime migration. -- Increase reliability from a global network supported by 100+ Indexers. -- Receive lightning-fast support for subgraphs 24/7, with an on-call engineering team. - -## Upgrade Your Subgraph to The Graph in 3 Easy Steps - -1. [Set Up Your Studio Environment](/cookbook/transfer-to-the-graph/#1-set-up-your-studio-environment) -2. [Deploy Your Subgraph to Studio](/cookbook/transfer-to-the-graph/#2-deploy-your-subgraph-to-studio) -3. [Publish to The Graph Network](/cookbook/transfer-to-the-graph/#publish-your-subgraph-to-the-graphs-decentralized-network) - -## 1. Set Up Your Studio Environment - -### Create a Subgraph in Subgraph Studio - -- Go to [Subgraph Studio](https://thegraph.com/studio/) and connect your wallet. -- Click "Create a Subgraph". It is recommended to name the subgraph in Title Case: "Subgraph Name Chain Name". - -> Note: After publishing, the subgraph name will be editable but requires on-chain action each time, so name it properly. - -### Install the Graph CLI⁠ - -You must have [Node.js](https://nodejs.org/) and a package manager of your choice (`npm` or `pnpm`) installed to use the Graph CLI. Check for the [most recent](https://github.com/graphprotocol/graph-tooling/releases?q=%40graphprotocol%2Fgraph-cli&expanded=true) CLI version. - -On your local machine, run the following command: - -Using [npm](https://www.npmjs.com/): - -```sh -npm install -g @graphprotocol/graph-cli@latest -``` - -Use the following command to create a subgraph in Studio using the CLI: - -```sh -graph init --product subgraph-studio -``` - -### Authenticate Your Subgraph - -In The Graph CLI, use the auth command seen in Subgraph Studio: - -```sh -graph auth --studio -``` - -## 2. Deploy Your Subgraph to Studio - -If you have your source code, you can easily deploy it to Studio. If you don't have it, here's a quick way to deploy your subgraph. - -In The Graph CLI, run the following command: - -```sh -graph deploy --studio --ipfs-hash - -``` - -> **Note:** Every subgraph has an IPFS hash (Deployment ID), which looks like this: "Qmasdfad...". To deploy simply use this **IPFS hash**. You’ll be prompted to enter a version (e.g., v0.0.1). - -## 3. Publish Your Subgraph to The Graph Network - -![publish button](/img/publish-sub-transfer.png) - -### Query Your Subgraph - -> To attract about 3 indexers to query your subgraph, it’s recommended to curate at least 3,000 GRT. To learn more about curating, check out [Curating](/network/curating/) on The Graph. - -You can start [querying](/querying/querying-the-graph/) any subgraph by sending a GraphQL query into the subgraph’s query URL endpoint, which is located at the top of its Explorer page in Subgraph Studio. - -#### Example - -[CryptoPunks Ethereum subgraph](https://thegraph.com/explorer/subgraphs/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK) by Messari: - -![Query URL](/img/cryptopunks-screenshot-transfer.png) - -The query URL for this subgraph is: - -```sh -https://gateway-arbitrum.network.thegraph.com/api/`**your-own-api-key**`/subgraphs/id/HdVdERFUe8h61vm2fDyycgxjsde5PbB832NHgJfZNqK -``` - -Now, you simply need to fill in **your own API Key** to start sending GraphQL queries to this endpoint. - -### Getting your own API Key - -You can create API Keys in Subgraph Studio under the “API Keys” menu at the top of the page: - -![API keys](/img/Api-keys-screenshot.png) - -### Monitor Subgraph Status - -Once you upgrade, you can access and manage your subgraphs in [Subgraph Studio](https://thegraph.com/studio/) and explore all subgraphs in [The Graph Explorer](https://thegraph.com/networks/). - -### Additional Resources - -- To quickly create and publish a new subgraph, check out the [Quick Start](/quick-start/). -- To explore all the ways you can optimize and customize your subgraph for a better performance, read more about [creating a subgraph here](/developing/creating-a-subgraph/). diff --git a/website/pages/ha/deploying/_meta.js b/website/pages/ha/deploying/_meta.js deleted file mode 100644 index 3d7abedc4d57..000000000000 --- a/website/pages/ha/deploying/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/deploying/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/deploying/deploy-using-subgraph-studio.mdx b/website/pages/ha/deploying/deploy-using-subgraph-studio.mdx deleted file mode 100644 index 502169b4ccfa..000000000000 --- a/website/pages/ha/deploying/deploy-using-subgraph-studio.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Deploy Using Subgraph Studio ---- - -Learn how to deploy your subgraph to Subgraph Studio. - -> Note: When you deploy a subgraph, you push it to Subgraph Studio, where you'll be able to test it. It's important to remember that deploying is not the same as publishing. When you publish a subgraph, you're publishing it on-chain. - -## Subgraph Studio Overview - -In [Subgraph Studio](https://thegraph.com/studio/), you can do the following: - -- View a list of subgraphs you've created -- Manage, view details, and visualize the status of a specific subgraph -- Create and manage your API keys for specific subgraphs -- Restrict your API keys to specific domains and allow only certain Indexers to query with them -- Create your subgraph through the Studio UI -- Deploy your subgraph using the The Graph CLI -- Test your subgraph in the playground environment -- Integrate your subgraph in staging using the development query URL -- Publish your subgraph with the Studio UI -- Manage your billing - -## Install The Graph CLI - -Before deploying, you must install The Graph CLI. - -You must have [Node.js](https://nodejs.org/) and a package manager of your choice (`npm`, `yarn` or `pnpm`) installed to use The Graph CLI. Check for the [most recent](https://github.com/graphprotocol/graph-tooling/releases?q=%40graphprotocol%2Fgraph-cli&expanded=true) CLI version. - -**Install with yarn:** - -```bash -yarn global add @graphprotocol/graph-cli -``` - -**Install with npm:** - -```bash -npm install -g @graphprotocol/graph-cli -``` - -## Create Your Subgraph - -Before deploying your subgraph you need to create an account in [Subgraph Studio](https://thegraph.com/studio/). - -1. Open [Subgraph Studio](https://thegraph.com/studio/). -2. Connect your wallet to sign in. - - You can do this via MetaMask, Coinbase Wallet, WalletConnect, or Safe. -3. After you sign in, your unique deploy key will be displayed on your subgraph details page. - - The deploy key allows you to publish your subgraphs or manage your API keys and billing. It is unique but can be regenerated if you think it has been compromised. - -> Important: You need an API key to query subgraphs - -### How to Create a Subgraph in Subgraph Studio - - - -> For additional written detail, review the [Quick-Start](/quick-start/). - -### Subgraph Compatibility with The Graph Network - -In order to be supported by Indexers on The Graph Network, subgraphs must: - -- Index a [supported network](/developing/supported-networks) -- Must not use any of the following features: - - ipfs.cat & ipfs.map - - Non-fatal errors - - Grafting - -## Initialize Your Subgraph - -Once your subgraph has been created in Subgraph Studio, you can initialize its code through the CLI using this command: - -```bash -graph init --studio -``` - -You can find the `` value on your subgraph details page in Subgraph Studio, see image below: - -![Subgraph Studio - Slug](/img/doc-subgraph-slug.png) - -After running `graph init`, you will be asked to input the contract address, network, and an ABI that you want to query. This will generate a new folder on your local machine with some basic code to start working on your subgraph. You can then finalize your subgraph to make sure it works as expected. - -## Graph Auth - -Before you can deploy your subgraph to Subgraph Studio, you need to login into your account within the CLI. To do this, you will need your deploy key, which you can find under your subgraph details page. - -Then, use the following command to authenticate from the CLI: - -```bash -graph auth --studio -``` - -## Deploying a Subgraph - -Once you are ready, you can deploy your subgraph to Subgraph Studio. - -> Deploying a subgraph with the CLI pushes it to the Studio, where you can test it and and update the metadata. This action won't publish your subgraph to the decentralized network. - -Use the following CLI command to deploy your subgraph: - -```bash -graph deploy --studio -``` - -After running this command, the CLI will ask for a version label. - -- It's strongly recommended to use [semver](https://semver.org/) for versioning like `0.0.1`. That said, you are free to choose any string as version such as `v1`, `version1`, or `asdf`. -- The labels you create will be visible in Graph Explorer and can be used by curators to decide if they want to signal on a specific version or not, so choose them wisely. - -## Testing Your Subgraph - -After deploying, you can test your subgraph (either in Subgraph Studio or in your own app, with the deployment query URL), deploy another version, update the metadata, and publish to [Graph Explorer](https://thegraph.com/explorer) when you are ready. - -Use Subgraph Studio to check the logs on the dashboard and look for any errors with your subgraph. - -## Publish Your Subgraph - -In order to publish your subgraph successfully, review [publishing a subgraph](/publishing/publishing-a-subgraph/). - -## Versioning Your Subgraph with the CLI - -If you want to update your subgraph, you can do the following: - -- You can deploy a new version to Studio using the CLI (it will only be private at this point). -- Once you're happy with it, you can publish your new deployment to [Graph Explorer](https://thegraph.com/explorer). -- This action will create a new version of your subgraph that Curators can start signaling on and Indexers can index. - -You can also update your subgraph's metadata without publishing a new version. You can update your subgraph details in Studio (under the profile picture, name, description, etc.) by checking an option called **Update Details** in Graph Explorer. If this is checked, an on-chain transaction will be generated that updates subgraph details in Explorer without having to publish a new version with a new deployment. - -> Note: There are costs associated with publishing a new version of a subgraph to the network. In addition to the transaction fees, you must also fund a part of the curation tax on the auto-migrating signal. You cannot publish a new version of your subgraph if Curators have not signaled on it. For more information, please read more [here](/network/curating/). - -## Automatic Archiving of Subgraph Versions - -Whenever you deploy a new subgraph version in Subgraph Studio, the previous version will be archived. Archived versions won't be indexed/synced and therefore cannot be queried. You can unarchive an archived version of your subgraph in Subgraph Studio. - -> Note: Previous versions of non-published subgraphs deployed to Studio will be automatically archived. - -![Subgraph Studio - Unarchive](/img/Unarchive.png) diff --git a/website/pages/ha/deploying/multiple-networks.mdx b/website/pages/ha/deploying/multiple-networks.mdx deleted file mode 100644 index dc2b8e533430..000000000000 --- a/website/pages/ha/deploying/multiple-networks.mdx +++ /dev/null @@ -1,241 +0,0 @@ ---- -title: Deploying a Subgraph to Multiple Networks ---- - -This page explains how to deploy a subgraph to multiple networks. To deploy a subgraph you need to first install the [Graph CLI](https://github.com/graphprotocol/graph-tooling/tree/main/packages/cli). If you have not created a subgraph already, see [Creating a subgraph](/developing/creating-a-subgraph). - -## Deploying the subgraph to multiple networks - -In some cases, you will want to deploy the same subgraph to multiple networks without duplicating all of its code. The main challenge that comes with this is that the contract addresses on these networks are different. - -### Using `graph-cli` - -Both `graph build` (since `v0.29.0`) and `graph deploy` (since `v0.32.0`) accept two new options: - -```sh -Options: - - ... - --network Network configuration to use from the networks config file - --network-file Networks config file path (default: "./networks.json") -``` - -You can use the `--network` option to specify a network configuration from a `json` standard file (defaults to `networks.json`) to easily update your subgraph during development. - -> Note: The `init` command will now auto-generate a `networks.json` based on the provided information. You will then be able to update existing or add additional networks. - -If you don't have a `networks.json` file, you'll need to manually create one with the following structure: - -```json -{ - "network1": { // the network name - "dataSource1": { // the dataSource name - "address": "0xabc...", // the contract address (optional) - "startBlock": 123456 // the startBlock (optional) - }, - "dataSource2": { - "address": "0x123...", - "startBlock": 123444 - } - }, - "network2": { - "dataSource1": { - "address": "0x987...", - "startBlock": 123 - }, - "dataSource2": { - "address": "0xxyz..", - "startBlock": 456 - } - }, - ... -} -``` - -> Note: You don't have to specify any of the `templates` (if you have any) in the config file, only the `dataSources`. If there are any `templates` declared in the `subgraph.yaml` file, their network will be automatically updated to the one specified with the `--network` option. - -Now, let's assume you want to be able to deploy your subgraph to the `mainnet` and `sepolia` networks, and this is your `subgraph.yaml`: - -```yaml -# ... -dataSources: - - kind: ethereum/contract - name: Gravity - network: mainnet - source: - address: '0x123...' - abi: Gravity - mapping: - kind: ethereum/events -``` - -This is what your networks config file should look like: - -```json -{ - "mainnet": { - "Gravity": { - "address": "0x123..." - } - }, - "sepolia": { - "Gravity": { - "address": "0xabc..." - } - } -} -``` - -Now we can run one of the following commands: - -```sh -# Using default networks.json file -yarn build --network sepolia - -# Using custom named file -yarn build --network sepolia --network-file path/to/config -``` - -The `build` command will update your `subgraph.yaml` with the `sepolia` configuration and then re-compile the subgraph. Your `subgraph.yaml` file now should look like this: - -```yaml -# ... -dataSources: - - kind: ethereum/contract - name: Gravity - network: sepolia - source: - address: '0xabc...' - abi: Gravity - mapping: - kind: ethereum/events -``` - -Now you are ready to `yarn deploy`. - -> Note: As mentioned earlier, since `graph-cli 0.32.0` you can directly run `yarn deploy` with the `--network` option: - -```sh -# Using default networks.json file -yarn deploy --network sepolia - -# Using custom named file -yarn deploy --network sepolia --network-file path/to/config -``` - -### Using subgraph.yaml template - -One way to parameterize aspects like contract addresses using older `graph-cli` versions is to generate parts of it with a templating system like [Mustache](https://mustache.github.io/) or [Handlebars](https://handlebarsjs.com/). - -To illustrate this approach, let's assume a subgraph should be deployed to mainnet and Sepolia using different contract addresses. You could then define two config files providing the addresses for each network: - -```json -{ - "network": "mainnet", - "address": "0x123..." -} -``` - -and - -```json -{ - "network": "sepolia", - "address": "0xabc..." -} -``` - -Along with that, you would substitute the network name and addresses in the manifest with variable placeholders `{{network}}` and `{{address}}` and rename the manifest to e.g. `subgraph.template.yaml`: - -```yaml -# ... -dataSources: - - kind: ethereum/contract - name: Gravity - network: mainnet - network: {{network}} - source: - address: '0x2E645469f354BB4F5c8a05B3b30A929361cf77eC' - address: '{{address}}' - abi: Gravity - mapping: - kind: ethereum/events -``` - -In order to generate a manifest to either network, you could add two additional commands to `package.json` along with a dependency on `mustache`: - -```json -{ - ... - "scripts": { - ... - "prepare:mainnet": "mustache config/mainnet.json subgraph.template.yaml > subgraph.yaml", - "prepare:sepolia": "mustache config/sepolia.json subgraph.template.yaml > subgraph.yaml" - }, - "devDependencies": { - ... - "mustache": "^3.1.0" - } -} -``` - -To deploy this subgraph for mainnet or Sepolia you would now simply run one of the two following commands: - -```sh -# Mainnet: -yarn prepare:mainnet && yarn deploy - -# Sepolia: -yarn prepare:sepolia && yarn deploy -``` - -A working example of this can be found [here](https://github.com/graphprotocol/example-subgraph/tree/371232cf68e6d814facf5e5413ad0fef65144759). - -**Note:** This approach can also be applied to more complex situations, where it is necessary to substitute more than contract addresses and network names or where generating mappings or ABIs from templates as well. - -This will give you the `chainHeadBlock` which you can compare with the `latestBlock` on your subgraph to check if it is running behind. `synced` informs if the subgraph has ever caught up to the chain. `health` can currently take the values of `healthy` if no errors occurred, or `failed` if there was an error which halted the progress of the subgraph. In this case, you can check the `fatalError` field for details on this error. - -## Subgraph Studio subgraph archive policy - -A subgraph version in Studio is archived if and only if it meets the following criteria: - -- The version is not published to the network (or pending publish) -- The version was created 45 or more days ago -- The subgraph hasn't been queried in 30 days - -In addition, when a new version is deployed, if the subgraph has not been published, then the N-2 version of the subgraph is archived. - -Every subgraph affected with this policy has an option to bring the version in question back. - -## Checking subgraph health - -If a subgraph syncs successfully, that is a good sign that it will continue to run well forever. However, new triggers on the network might cause your subgraph to hit an untested error condition or it may start to fall behind due to performance issues or issues with the node operators. - -Graph Node exposes a GraphQL endpoint which you can query to check the status of your subgraph. On the hosted service, it is available at `https://api.thegraph.com/index-node/graphql`. On a local node, it is available on port `8030/graphql` by default. The full schema for this endpoint can be found [here](https://github.com/graphprotocol/graph-node/blob/master/server/index-node/src/schema.graphql). Here is an example query that checks the status of the current version of a subgraph: - -```graphql -{ - indexingStatusForCurrentVersion(subgraphName: "org/subgraph") { - synced - health - fatalError { - message - block { - number - hash - } - handler - } - chains { - chainHeadBlock { - number - } - latestBlock { - number - } - } - } -} -``` - -This will give you the `chainHeadBlock` which you can compare with the `latestBlock` on your subgraph to check if it is running behind. `synced` informs if the subgraph has ever caught up to the chain. `health` can currently take the values of `healthy` if no errors occurred, or `failed` if there was an error which halted the progress of the subgraph. In this case, you can check the `fatalError` field for details on this error. diff --git a/website/pages/ha/deploying/subgraph-studio-faqs.mdx b/website/pages/ha/deploying/subgraph-studio-faqs.mdx deleted file mode 100644 index 65217d4b7741..000000000000 --- a/website/pages/ha/deploying/subgraph-studio-faqs.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Subgraph Studio FAQs ---- - -## 1. What is Subgraph Studio? - -[Subgraph Studio](https://thegraph.com/studio/) is a dapp for creating, managing, and publishing subgraphs and API keys. - -## 2. How do I create an API Key? - -To create an API, navigate to the Subgraph Studio and connect your wallet. You will be able to click the API keys tab at the top. There, you will be able to create an API key. - -## 3. Can I create multiple API Keys? - -Yes! You can create multiple API Keys to use in different projects. Check out the link [here](https://thegraph.com/studio/apikeys/). - -## 4. How do I restrict a domain for an API Key? - -After creating an API Key, in the Security section, you can define the domains that can query a specific API Key. - -## 5. Can I transfer my subgraph to another owner? - -Yes, subgraphs that have been published to Mainnet can be transferred to a new wallet or a Multisig. You can do so by clicking the three dots next to the 'Publish' button on the subgraph's details page and selecting 'Transfer ownership'. - -Note that you will no longer be able to see or edit the subgraph in Studio once it has been transferred. - -## 6. How do I find query URLs for subgraphs if I’m not the developer of the subgraph I want to use? - -You can find the query URL of each subgraph in the Subgraph Details section of The Graph Explorer. When you click on the “Query” button, you will be directed to a pane wherein you can view the query URL of the subgraph you’re interested in. You can then replace the `` placeholder with the API key you wish to leverage in the Subgraph Studio. - -Remember that you can create an API key and query any subgraph published to the network, even if you build a subgraph yourself. These queries via the new API key, are paid queries as any other on the network. diff --git a/website/pages/ha/developing/_meta.js b/website/pages/ha/developing/_meta.js deleted file mode 100644 index 48d6b89bb3fe..000000000000 --- a/website/pages/ha/developing/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/developing/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/developing/creating-a-subgraph/_meta.js b/website/pages/ha/developing/creating-a-subgraph/_meta.js deleted file mode 100644 index a904468b50a2..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../../en/developing/creating-a-subgraph/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/developing/creating-a-subgraph/advanced.mdx b/website/pages/ha/developing/creating-a-subgraph/advanced.mdx deleted file mode 100644 index 45acd610f237..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/advanced.mdx +++ /dev/null @@ -1,555 +0,0 @@ ---- -title: Advance Subgraph Features ---- - -## Overview - -Add and implement advanced subgraph features to enhanced your subgraph's built. - -Starting from `specVersion` `0.0.4`, subgraph features must be explicitly declared in the `features` section at the top level of the manifest file, using their `camelCase` name, as listed in the table below: - -| Feature | Name | -| ---------------------------------------------------- | ---------------- | -| [Non-fatal errors](#non-fatal-errors) | `nonFatalErrors` | -| [Full-text Search](#defining-fulltext-search-fields) | `fullTextSearch` | -| [Grafting](#grafting-onto-existing-subgraphs) | `grafting` | - -For instance, if a subgraph uses the **Full-Text Search** and the **Non-fatal Errors** features, the `features` field in the manifest should be: - -```yaml -specVersion: 0.0.4 -description: Gravatar for Ethereum -features: - - fullTextSearch - - nonFatalErrors -dataSources: ... -``` - -> Note that using a feature without declaring it will incur a **validation error** during subgraph deployment, but no errors will occur if a feature is declared but not used. - -## Timeseries and Aggregations - -Timeseries and aggregations enable your subgraph to track statistics like daily average price, hourly total transfers, etc. - -This feature introduces two new types of subgraph entity. Timeseries entities record data points with timestamps. Aggregation entities perform pre-declared calculations on the Timeseries data points on an hourly or daily basis, then store the results for easy access via GraphQL. - -### Example Schema - -```graphql -type Data @entity(timeseries: true) { - id: Int8! - timestamp: Timestamp! - price: BigDecimal! -} - -type Stats @aggregation(intervals: ["hour", "day"], source: "Data") { - id: Int8! - timestamp: Timestamp! - sum: BigDecimal! @aggregate(fn: "sum", arg: "price") -} -``` - -### Defining Timeseries and Aggregations - -Timeseries entities are defined with `@entity(timeseries: true)` in schema.graphql. Every timeseries entity must have a unique ID of the int8 type, a timestamp of the Timestamp type, and include data that will be used for calculation by aggregation entities. These Timeseries entities can be saved in regular trigger handlers, and act as the “raw data” for the Aggregation entities. - -Aggregation entities are defined with `@aggregation` in schema.graphql. Every aggregation entity defines the source from which it will gather data (which must be a Timeseries entity), sets the intervals (e.g., hour, day), and specifies the aggregation function it will use (e.g., sum, count, min, max, first, last). Aggregation entities are automatically calculated on the basis of the specified source at the end of the required interval. - -#### Available Aggregation Intervals - -- `hour`: sets the timeseries period every hour, on the hour. -- `day`: sets the timeseries period every day, starting and ending at 00:00. - -#### Available Aggregation Functions - -- `sum`: Total of all values. -- `count`: Number of values. -- `min`: Minimum value. -- `max`: Maximum value. -- `first`: First value in the period. -- `last`: Last value in the period. - -#### Example Aggregations Query - -```graphql -{ - stats(interval: "hour", where: { timestamp_gt: 1704085200 }) { - id - timestamp - sum - } -} -``` - -Note: - -To use Timeseries and Aggregations, a subgraph must have a spec version ≥1.1.0. Note that this feature might undergo significant changes that could affect backward compatibility. - -[Read more](https://github.com/graphprotocol/graph-node/blob/master/docs/aggregations.md) about Timeseries and Aggregations. - -## Non-fatal errors - -Indexing errors on already synced subgraphs will, by default, cause the subgraph to fail and stop syncing. Subgraphs can alternatively be configured to continue syncing in the presence of errors, by ignoring the changes made by the handler which provoked the error. This gives subgraph authors time to correct their subgraphs while queries continue to be served against the latest block, though the results might be inconsistent due to the bug that caused the error. Note that some errors are still always fatal. To be non-fatal, the error must be known to be deterministic. - -> **Note:** The Graph Network does not yet support non-fatal errors, and developers should not deploy subgraphs using that functionality to the network via the Studio. - -Enabling non-fatal errors requires setting the following feature flag on the subgraph manifest: - -```yaml -specVersion: 0.0.4 -description: Gravatar for Ethereum -features: - - nonFatalErrors - ... -``` - -The query must also opt-in to querying data with potential inconsistencies through the `subgraphError` argument. It is also recommended to query `_meta` to check if the subgraph has skipped over errors, as in the example: - -```graphql -foos(first: 100, subgraphError: allow) { - id -} - -_meta { - hasIndexingErrors -} -``` - -If the subgraph encounters an error, that query will return both the data and a graphql error with the message `"indexing_error"`, as in this example response: - -```graphql -"data": { - "foos": [ - { - "id": "0xdead" - } - ], - "_meta": { - "hasIndexingErrors": true - } -}, -"errors": [ - { - "message": "indexing_error" - } -] -``` - -## IPFS/Arweave File Data Sources - -File data sources are a new subgraph functionality for accessing off-chain data during indexing in a robust, extendable way. File data sources support fetching files from IPFS and from Arweave. - -> This also lays the groundwork for deterministic indexing of off-chain data, as well as the potential introduction of arbitrary HTTP-sourced data. - -### Overview - -Rather than fetching files "in line" during handler execution, this introduces templates which can be spawned as new data sources for a given file identifier. These new data sources fetch the files, retrying if they are unsuccessful, running a dedicated handler when the file is found. - -This is similar to the [existing data source templates](/developing/creating-a-subgraph/#data-source-templates), which are used to dynamically create new chain-based data sources. - -> This replaces the existing `ipfs.cat` API - -### Upgrade guide - -#### Update `graph-ts` and `graph-cli` - -File data sources requires graph-ts >=0.29.0 and graph-cli >=0.33.1 - -#### Add a new entity type which will be updated when files are found - -File data sources cannot access or update chain-based entities, but must update file specific entities. - -This may mean splitting out fields from existing entities into separate entities, linked together. - -Original combined entity: - -```graphql -type Token @entity { - id: ID! - tokenID: BigInt! - tokenURI: String! - externalURL: String! - ipfsURI: String! - image: String! - name: String! - description: String! - type: String! - updatedAtTimestamp: BigInt - owner: User! -} -``` - -New, split entity: - -```graphql -type Token @entity { - id: ID! - tokenID: BigInt! - tokenURI: String! - ipfsURI: TokenMetadata - updatedAtTimestamp: BigInt - owner: String! -} - -type TokenMetadata @entity { - id: ID! - image: String! - externalURL: String! - name: String! - description: String! -} -``` - -If the relationship is 1:1 between the parent entity and the resulting file data source entity, the simplest pattern is to link the parent entity to a resulting file entity by using the IPFS CID as the lookup. Get in touch on Discord if you are having difficulty modelling your new file-based entities! - -> You can use [nested filters](/querying/graphql-api/#example-for-nested-entity-filtering) to filter parent entities on the basis of these nested entities. - -#### Add a new templated data source with `kind: file/ipfs` or `kind: file/arweave` - -This is the data source which will be spawned when a file of interest is identified. - -```yaml -templates: - - name: TokenMetadata - kind: file/ipfs - mapping: - apiVersion: 0.0.7 - language: wasm/assemblyscript - file: ./src/mapping.ts - handler: handleMetadata - entities: - - TokenMetadata - abis: - - name: Token - file: ./abis/Token.json -``` - -> Currently `abis` are required, though it is not possible to call contracts from within file data sources - -The file data source must specifically mention all the entity types which it will interact with under `entities`. See [limitations](#limitations) for more details. - -#### Create a new handler to process files - -This handler should accept one `Bytes` parameter, which will be the contents of the file, when it is found, which can then be processed. This will often be a JSON file, which can be processed with `graph-ts` helpers ([documentation](/developing/graph-ts/api/#json-api)). - -The CID of the file as a readable string can be accessed via the `dataSource` as follows: - -```typescript -const cid = dataSource.stringParam() -``` - -Example handler: - -```typescript -import { json, Bytes, dataSource } from '@graphprotocol/graph-ts' -import { TokenMetadata } from '../generated/schema' - -export function handleMetadata(content: Bytes): void { - let tokenMetadata = new TokenMetadata(dataSource.stringParam()) - const value = json.fromBytes(content).toObject() - if (value) { - const image = value.get('image') - const name = value.get('name') - const description = value.get('description') - const externalURL = value.get('external_url') - - if (name && image && description && externalURL) { - tokenMetadata.name = name.toString() - tokenMetadata.image = image.toString() - tokenMetadata.externalURL = externalURL.toString() - tokenMetadata.description = description.toString() - } - - tokenMetadata.save() - } -} -``` - -#### Spawn file data sources when required - -You can now create file data sources during execution of chain-based handlers: - -- Import the template from the auto-generated `templates` -- call `TemplateName.create(cid: string)` from within a mapping, where the cid is a valid content identifier for IPFS or Arweave - -For IPFS, Graph Node supports [v0 and v1 content identifiers](https://docs.ipfs.tech/concepts/content-addressing/), and content identifers with directories (e.g. `bafyreighykzv2we26wfrbzkcdw37sbrby4upq7ae3aqobbq7i4er3tnxci/metadata.json`). - -For Arweave, as of version 0.33.0 Graph Node can fetch files stored on Arweave based on their [transaction ID](https://docs.arweave.org/developers/arweave-node-server/http-api#transactions) from an Arweave gateway ([example file](https://bdxujjl5ev5eerd5ouhhs6o4kjrs4g6hqstzlci5pf6vhxezkgaa.arweave.net/CO9EpX0lekJEfXUOeXncUmMuG8eEp5WJHXl9U9yZUYA)). Arweave supports transactions uploaded via Irys (previously Bundlr), and Graph Node can also fetch files based on [Irys manifests](https://docs.irys.xyz/overview/gateways#indexing). - -Example: - -```typescript -import { TokenMetadata as TokenMetadataTemplate } from '../generated/templates' - -const ipfshash = 'QmaXzZhcYnsisuue5WRdQDH6FDvqkLQX1NckLqBYeYYEfm' -//This example code is for a Crypto coven subgraph. The above ipfs hash is a directory with token metadata for all crypto coven NFTs. - -export function handleTransfer(event: TransferEvent): void { - let token = Token.load(event.params.tokenId.toString()) - if (!token) { - token = new Token(event.params.tokenId.toString()) - token.tokenID = event.params.tokenId - - token.tokenURI = '/' + event.params.tokenId.toString() + '.json' - const tokenIpfsHash = ipfshash + token.tokenURI - //This creates a path to the metadata for a single Crypto coven NFT. It concats the directory with "/" + filename + ".json" - - token.ipfsURI = tokenIpfsHash - - TokenMetadataTemplate.create(tokenIpfsHash) - } - - token.updatedAtTimestamp = event.block.timestamp - token.owner = event.params.to.toHexString() - token.save() -} -``` - -This will create a new file data source, which will poll Graph Node's configured IPFS or Arweave endpoint, retrying if it is not found. When the file is found, the file data source handler will be executed. - -This example is using the CID as the lookup between the parent `Token` entity and the resulting `TokenMetadata` entity. - -> Previously, this is the point at which a subgraph developer would have called `ipfs.cat(CID)` to fetch the file - -Congratulations, you are using file data sources! - -#### Deploying your subgraphs - -You can now `build` and `deploy` your subgraph to any Graph Node >=v0.30.0-rc.0. - -#### Limitations - -File data source handlers and entities are isolated from other subgraph entities, ensuring that they are deterministic when executed, and ensuring no contamination of chain-based data sources. To be specific: - -- Entities created by File Data Sources are immutable, and cannot be updated -- File Data Source handlers cannot access entities from other file data sources -- Entities associated with File Data Sources cannot be accessed by chain-based handlers - -> While this constraint should not be problematic for most use-cases, it may introduce complexity for some. Please get in touch via Discord if you are having issues modelling your file-based data in a subgraph! - -Additionally, it is not possible to create data sources from a file data source, be it an onchain data source or another file data source. This restriction may be lifted in the future. - -#### Best practices - -If you are linking NFT metadata to corresponding tokens, use the metadata's IPFS hash to reference a Metadata entity from the Token entity. Save the Metadata entity using the IPFS hash as an ID. - -You can use [DataSource context](/developing/graph-ts/api/#entity-and-datasourcecontext) when creating File Data Sources to pass extra information which will be available to the File Data Source handler. - -If you have entities which are refreshed multiple times, create unique file-based entities using the IPFS hash & the entity ID, and reference them using a derived field in the chain-based entity. - -> We are working to improve the above recommendation, so queries only return the "most recent" version - -#### Known issues - -File data sources currently require ABIs, even though ABIs are not used ([issue](https://github.com/graphprotocol/graph-cli/issues/961)). Workaround is to add any ABI. - -Handlers for File Data Sources cannot be in files which import `eth_call` contract bindings, failing with "unknown import: `ethereum::ethereum.call` has not been defined" ([issue](https://github.com/graphprotocol/graph-node/issues/4309)). Workaround is to create file data source handlers in a dedicated file. - -#### Examples - -[Crypto Coven Subgraph migration](https://github.com/azf20/cryptocoven-api/tree/file-data-sources-refactor) - -#### References - -[GIP File Data Sources](https://forum.thegraph.com/t/gip-file-data-sources/2721) - -## Indexed Argument Filters / Topic Filters - -> **Requires**: [SpecVersion](#specversion-releases) >= `1.2.0` - -Topic filters, also known as indexed argument filters, are a powerful feature in subgraphs that allow users to precisely filter blockchain events based on the values of their indexed arguments. - -- These filters help isolate specific events of interest from the vast stream of events on the blockchain, allowing subgraphs to operate more efficiently by focusing only on relevant data. - -- This is useful for creating personal subgraphs that track specific addresses and their interactions with various smart contracts on the blockchain. - -### How Topic Filters Work - -When a smart contract emits an event, any arguments that are marked as indexed can be used as filters in a subgraph's manifest. This allows the subgraph to listen selectively for events that match these indexed arguments. - -- The event's first indexed argument corresponds to `topic1`, the second to `topic2`, and so on, up to `topic3`, since the Ethereum Virtual Machine (EVM) allows up to three indexed arguments per event. - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract Token { - // Event declaration with indexed parameters for addresses - event Transfer(address indexed from, address indexed to, uint256 value); - - // Function to simulate transferring tokens - function transfer(address to, uint256 value) public { - // Emitting the Transfer event with from, to, and value - emit Transfer(msg.sender, to, value); - } -} -``` - -In this example: - -- The `Transfer` event is used to log transactions of tokens between addresses. -- The `from` and `to` parameters are indexed, allowing event listeners to filter and monitor transfers involving specific addresses. -- The `transfer` function is a simple representation of a token transfer action, emitting the Transfer event whenever it is called. - -#### Configuration in Subgraphs - -Topic filters are defined directly within the event handler configuration in the subgraph manifest. Here is how they are configured: - -```yaml -eventHandlers: - - event: SomeEvent(indexed uint256, indexed address, indexed uint256) - handler: handleSomeEvent - topic1: ['0xValue1', '0xValue2'] - topic2: ['0xAddress1', '0xAddress2'] - topic3: ['0xValue3'] -``` - -In this setup: - -- `topic1` corresponds to the first indexed argument of the event, `topic2` to the second, and `topic3` to the third. -- Each topic can have one or more values, and an event is only processed if it matches one of the values in each specified topic. - -#### Filter Logic - -- Within a Single Topic: The logic functions as an OR condition. The event will be processed if it matches any one of the listed values in a given topic. -- Between Different Topics: The logic functions as an AND condition. An event must satisfy all specified conditions across different topics to trigger the associated handler. - -#### Example 1: Tracking Direct Transfers from Address A to Address B - -```yaml -eventHandlers: - - event: Transfer(indexed address,indexed address,uint256) - handler: handleDirectedTransfer - topic1: ['0xAddressA'] # Sender Address - topic2: ['0xAddressB'] # Receiver Address -``` - -In this configuration: - -- `topic1` is configured to filter `Transfer` events where `0xAddressA` is the sender. -- `topic2` is configured to filter `Transfer` events where `0xAddressB` is the receiver. -- The subgraph will only index transactions that occur directly from `0xAddressA` to `0xAddressB`. - -#### Example 2: Tracking Transactions in Either Direction Between Two or More Addresses - -```yaml -eventHandlers: - - event: Transfer(indexed address,indexed address,uint256) - handler: handleTransferToOrFrom - topic1: ['0xAddressA', '0xAddressB', '0xAddressC'] # Sender Address - topic2: ['0xAddressB', '0xAddressC'] # Receiver Address -``` - -In this configuration: - -- `topic1` is configured to filter `Transfer` events where `0xAddressA`, `0xAddressB`, `0xAddressC` is the sender. -- `topic2` is configured to filter `Transfer` events where `0xAddressB` and `0xAddressC` is the receiver. -- The subgraph will index transactions that occur in either direction between multiple addresses allowing for comprehensive monitoring of interactions involving all addresses. - -## Declared eth_call - -> Note: This is an experimental feature that is not currently available in a stable Graph Node release yet. You can only use it in Subgraph Studio or your self-hosted node. - -Declarative `eth_calls` are a valuable subgraph feature that allows `eth_calls` to be executed ahead of time, enabling `graph-node` to execute them in parallel. - -This feature does the following: - -- Significantly improves the performance of fetching data from the Ethereum blockchain by reducing the total time for multiple calls and optimizing the subgraph's overall efficiency. -- Allows faster data fetching, resulting in quicker query responses and a better user experience. -- Reduces wait times for applications that need to aggregate data from multiple Ethereum calls, making the data retrieval process more efficient. - -### Key Concepts - -- Declarative `eth_calls`: Ethereum calls that are defined to be executed in parallel rather than sequentially. -- Parallel Execution: Instead of waiting for one call to finish before starting the next, multiple calls can be initiated simultaneously. -- Time Efficiency: The total time taken for all the calls changes from the sum of the individual call times (sequential) to the time taken by the longest call (parallel). - -#### Scenario without Declarative `eth_calls` - -Imagine you have a subgraph that needs to make three Ethereum calls to fetch data about a user's transactions, balance, and token holdings. - -Traditionally, these calls might be made sequentially: - -1. Call 1 (Transactions): Takes 3 seconds -2. Call 2 (Balance): Takes 2 seconds -3. Call 3 (Token Holdings): Takes 4 seconds - -Total time taken = 3 + 2 + 4 = 9 seconds - -#### Scenario with Declarative `eth_calls` - -With this feature, you can declare these calls to be executed in parallel: - -1. Call 1 (Transactions): Takes 3 seconds -2. Call 2 (Balance): Takes 2 seconds -3. Call 3 (Token Holdings): Takes 4 seconds - -Since these calls are executed in parallel, the total time taken is equal to the time taken by the longest call. - -Total time taken = max (3, 2, 4) = 4 seconds - -#### How it Works - -1. Declarative Definition: In the subgraph manifest, you declare the Ethereum calls in a way that indicates they can be executed in parallel. -2. Parallel Execution Engine: The Graph Node's execution engine recognizes these declarations and runs the calls simultaneously. -3. Result Aggregation: Once all calls are complete, the results are aggregated and used by the subgraph for further processing. - -#### Example Configuration in Subgraph Manifest - -Declared `eth_calls` can access the `event.address` of the underlying event as well as all the `event.params`. - -`Subgraph.yaml` using `event.address`: - -```yaml -eventHandlers: -event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24) -handler: handleSwap -calls: - global0X128: Pool[event.address].feeGrowthGlobal0X128() - global1X128: Pool[event.address].feeGrowthGlobal1X128() -``` - -Details for the example above: - -- `global0X128` is the declared `eth_call`. -- The text (`global0X128`) is the label for this `eth_call` which is used when logging errors. -- The text (`Pool[event.address].feeGrowthGlobal0X128()`) is the actual `eth_call` that will be executed, which is in the form of `Contract[address].function(arguments)` -- The `address` and `arguments` can be replaced with variables that will be available when the handler is executed. - -`Subgraph.yaml` using `event.params` - -```yaml -calls: - - ERC20DecimalsToken0: ERC20[event.params.token0].decimals() -``` - -### Grafting onto Existing Subgraphs - -> **Note:** it is not recommended to use grafting when initially upgrading to The Graph Network. Learn more [here](/cookbook/grafting/#important-note-on-grafting-when-upgrading-to-the-network). - -When a subgraph is first deployed, it starts indexing events at the genesis block of the corresponding chain (or at the `startBlock` defined with each data source) In some circumstances; it is beneficial to reuse the data from an existing subgraph and start indexing at a much later block. This mode of indexing is called _Grafting_. Grafting is, for example, useful during development to get past simple errors in the mappings quickly or to temporarily get an existing subgraph working again after it has failed. - -A subgraph is grafted onto a base subgraph when the subgraph manifest in `subgraph.yaml` contains a `graft` block at the top-level: - -```yaml -description: ... -graft: - base: Qm... # Subgraph ID of base subgraph - block: 7345624 # Block number -``` - -When a subgraph whose manifest contains a `graft` block is deployed, Graph Node will copy the data of the `base` subgraph up to and including the given `block` and then continue indexing the new subgraph from that block on. The base subgraph must exist on the target Graph Node instance and must have indexed up to at least the given block. Because of this restriction, grafting should only be used during development or during an emergency to speed up producing an equivalent non-grafted subgraph. - -Because grafting copies rather than indexes base data, it is much quicker to get the subgraph to the desired block than indexing from scratch, though the initial data copy can still take several hours for very large subgraphs. While the grafted subgraph is being initialized, the Graph Node will log information about the entity types that have already been copied. - -The grafted subgraph can use a GraphQL schema that is not identical to the one of the base subgraph, but merely compatible with it. It has to be a valid subgraph schema in its own right, but may deviate from the base subgraph's schema in the following ways: - -- It adds or removes entity types -- It removes attributes from entity types -- It adds nullable attributes to entity types -- It turns non-nullable attributes into nullable attributes -- It adds values to enums -- It adds or removes interfaces -- It changes for which entity types an interface is implemented - -> **[Feature Management](#experimental-features):** `grafting` must be declared under `features` in the subgraph manifest. diff --git a/website/pages/ha/developing/creating-a-subgraph/assemblyscript-mappings.mdx b/website/pages/ha/developing/creating-a-subgraph/assemblyscript-mappings.mdx deleted file mode 100644 index 2ac894695fe1..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/assemblyscript-mappings.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Writing AssemblyScript Mappings ---- - -## Overview - -The mappings take data from a particular source and transform it into entities that are defined within your schema. Mappings are written in a subset of [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html) called [AssemblyScript](https://github.com/AssemblyScript/assemblyscript/wiki) which can be compiled to WASM ([WebAssembly](https://webassembly.org/)). AssemblyScript is stricter than normal TypeScript, yet provides a familiar syntax. - -## Writing Mappings - -For each event handler that is defined in `subgraph.yaml` under `mapping.eventHandlers`, create an exported function of the same name. Each handler must accept a single parameter called `event` with a type corresponding to the name of the event which is being handled. - -In the example subgraph, `src/mapping.ts` contains handlers for the `NewGravatar` and `UpdatedGravatar` events: - -```javascript -import { NewGravatar, UpdatedGravatar } from '../generated/Gravity/Gravity' -import { Gravatar } from '../generated/schema' - -export function handleNewGravatar(event: NewGravatar): void { - let gravatar = new Gravatar(event.params.id) - gravatar.owner = event.params.owner - gravatar.displayName = event.params.displayName - gravatar.imageUrl = event.params.imageUrl - gravatar.save() -} - -export function handleUpdatedGravatar(event: UpdatedGravatar): void { - let id = event.params.id - let gravatar = Gravatar.load(id) - if (gravatar == null) { - gravatar = new Gravatar(id) - } - gravatar.owner = event.params.owner - gravatar.displayName = event.params.displayName - gravatar.imageUrl = event.params.imageUrl - gravatar.save() -} -``` - -The first handler takes a `NewGravatar` event and creates a new `Gravatar` entity with `new Gravatar(event.params.id.toHex())`, populating the entity fields using the corresponding event parameters. This entity instance is represented by the variable `gravatar`, with an id value of `event.params.id.toHex()`. - -The second handler tries to load the existing `Gravatar` from the Graph Node store. If it does not exist yet, it is created on-demand. The entity is then updated to match the new event parameters before it is saved back to the store using `gravatar.save()`. - -### Recommended IDs for Creating New Entities - -It is highly recommended to use `Bytes` as the type for `id` fields, and only use `String` for attributes that truly contain human-readable text, like the name of a token. Below are some recommended `id` values to consider when creating new entities. - -- `transfer.id = event.transaction.hash` - -- `let id = event.transaction.hash.concatI32(event.logIndex.toI32())` - -- For entities that store aggregated data, for e.g, daily trade volumes, the `id` usually contains the day number. Here, using a `Bytes` as the `id` is beneficial. Determining the `id` would look like - -```typescript -let dayID = event.block.timestamp.toI32() / 86400 -let id = Bytes.fromI32(dayID) -``` - -- Convert constant addresses to `Bytes`. - -`const id = Bytes.fromHexString('0xdead...beef')` - -There is a [Graph Typescript Library](https://github.com/graphprotocol/graph-tooling/tree/main/packages/ts) which contains utilities for interacting with the Graph Node store and conveniences for handling smart contract data and entities. It can be imported into `mapping.ts` from `@graphprotocol/graph-ts`. - -### Handling of entities with identical IDs - -When creating and saving a new entity, if an entity with the same ID already exists, the properties of the new entity are always preferred during the merge process. This means that the existing entity will be updated with the values from the new entity. - -If a null value is intentionally set for a field in the new entity with the same ID, the existing entity will be updated with the null value. - -If no value is set for a field in the new entity with the same ID, the field will result in null as well. - -## Code Generation - -In order to make it easy and type-safe to work with smart contracts, events and entities, the Graph CLI can generate AssemblyScript types from the subgraph's GraphQL schema and the contract ABIs included in the data sources. - -This is done with - -```sh -graph codegen [--output-dir ] [] -``` - -but in most cases, subgraphs are already preconfigured via `package.json` to allow you to simply run one of the following to achieve the same: - -```sh -# Yarn -yarn codegen - -# NPM -npm run codegen -``` - -This will generate an AssemblyScript class for every smart contract in the ABI files mentioned in `subgraph.yaml`, allowing you to bind these contracts to specific addresses in the mappings and call read-only contract methods against the block being processed. It will also generate a class for every contract event to provide easy access to event parameters, as well as the block and transaction the event originated from. All of these types are written to `//.ts`. In the example subgraph, this would be `generated/Gravity/Gravity.ts`, allowing mappings to import these types with. - -```javascript -import { - // The contract class: - Gravity, - // The events classes: - NewGravatar, - UpdatedGravatar, -} from '../generated/Gravity/Gravity' -``` - -In addition to this, one class is generated for each entity type in the subgraph's GraphQL schema. These classes provide type-safe entity loading, read and write access to entity fields as well as a `save()` method to write entities to store. All entity classes are written to `/schema.ts`, allowing mappings to import them with - -```javascript -import { Gravatar } from '../generated/schema' -``` - -> **Note:** The code generation must be performed again after every change to the GraphQL schema or the ABIs included in the manifest. It must also be performed at least once before building or deploying the subgraph. - -Code generation does not check your mapping code in `src/mapping.ts`. If you want to check that before trying to deploy your subgraph to Graph Explorer, you can run `yarn build` and fix any syntax errors that the TypeScript compiler might find. diff --git a/website/pages/ha/developing/creating-a-subgraph/install-the-cli.mdx b/website/pages/ha/developing/creating-a-subgraph/install-the-cli.mdx deleted file mode 100644 index 282c68973a8a..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/install-the-cli.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Install the Graph CLI ---- - -> In order to use your subgraph on The Graph's decentralized network, you will need to [create an API key](/deploying/subgraph-studio-faqs/#2-how-do-i-create-an-api-key) in [Subgraph Studio](https://thegraph.com/studio/apikeys/). It is recommended that you add signal to your subgraph with at least 3,000 GRT to attract 2-3 Indexers. To learn more about signaling, check out [curating](/network/curating/). - -## Overview - -The [Graph CLI](https://github.com/graphprotocol/graph-tooling/tree/main/packages/cli) is a command-line interface that facilitates developers' commands for The Graph. It processes a [subgraph manifest](/creating-a-subgraph/subgraph-manifest/) and compiles the [mappings](/creating-a-subgraph/assemblyscript-mappings/) to create the files you will need to deploy the subgraph to [Subgraph Studio](https://thegraph.com/studio/) and the network. - -## Getting Started - -### Install the Graph CLI - -The Graph CLI is written in TypeScript, and you must have `node` and either `npm` or `yarn` installed to use it. Check for the [most recent](https://github.com/graphprotocol/graph-tooling/releases?q=%40graphprotocol%2Fgraph-cli&expanded=true) CLI version. - -On your local machine, run one of the following commands: - -#### Using [npm](https://www.npmjs.com/) - -```bash -npm install -g @graphprotocol/graph-cli@latest -``` - -#### Using [yarn](https://yarnpkg.com/) - -```bash -yarn global add @graphprotocol/graph-cli -``` - -The `graph init` command can be used to set up a new subgraph project, either from an existing contract or from an example subgraph. If you already have a smart contract deployed to your preferred network, you can bootstrap a new subgraph from that contract to get started. - -## Create a Subgraph - -### From an Existing Contract - -The following command creates a subgraph that indexes all events of an existing contract: - -```sh -graph init \ - --product subgraph-studio - --from-contract \ - [--network ] \ - [--abi ] \ - [] -``` - -- The command tries to retrieve the contract ABI from Etherscan. - - - The Graph CLI relies on a public RPC endpoint. While occasional failures are expected, retries typically resolve this issue. If failures persist, consider using a local ABI. - -- If any of the optional arguments are missing, it guides you through an interactive form. - -- The `` is the ID of your subgraph in [Subgraph Studio](https://thegraph.com/studio/). It can be found on your subgraph details page. - -### From an Example Subgraph - -The following command initializes a new project from an example subgraph: - -```sh -graph init --from-example=example-subgraph -``` - -- The [example subgraph](https://github.com/graphprotocol/example-subgraph) is based on the Gravity contract by Dani Grant, which manages user avatars and emits `NewGravatar` or `UpdateGravatar` events whenever avatars are created or updated. - -- The subgraph handles these events by writing `Gravatar` entities to the Graph Node store and ensuring these are updated according to the events. - -### Add New `dataSources` to an Existing Subgraph - -`dataSources` are key components of subgraphs. They define the sources of data that the subgraph indexes and processes. A `dataSource` specifies which smart contract to listen to, which events to process, and how to handle them. - -Recent versions of the Graph CLI supports adding new `dataSources` to an existing subgraph through the `graph add` command: - -```sh -graph add
[] - -Options: - - --abi Path to the contract ABI (default: download from Etherscan) - --contract-name Name of the contract (default: Contract) - --merge-entities Whether to merge entities with the same name (default: false) - --network-file Networks config file path (default: "./networks.json") -``` - -#### Specifics - -The `graph add` command will fetch the ABI from Etherscan (unless an ABI path is specified with the `--abi` option) and creates a new `dataSource`, similar to how the `graph init` command creates a `dataSource` `--from-contract`, updating the schema and mappings accordingly. This allows you to index implementation contracts from their proxy contracts. - -- The `--merge-entities` option identifies how the developer would like to handle `entity` and `event` name conflicts: - - - If `true`: the new `dataSource` should use existing `eventHandlers` & `entities`. - - - If `false`: a new `entity` & `event` handler should be created with `${dataSourceName}{EventName}`. - -- The contract `address` will be written to the `networks.json` for the relevant network. - -> Note: When using the interactive CLI, after successfully running `graph init`, you'll be prompted to add a new `dataSource`. - -### Getting The ABIs - -The ABI file(s) must match your contract(s). There are a few ways to obtain ABI files: - -- If you are building your own project, you will likely have access to your most current ABIs. -- If you are building a subgraph for a public project, you can download that project to your computer and get the ABI by using [`npx hardhat compile`](https://hardhat.org/hardhat-runner/docs/guides/compile-contracts#compiling-your-contracts) or using `solc` to compile. -- You can also find the ABI on [Etherscan](https://etherscan.io/), but this isn't always reliable, as the ABI that is uploaded there may be out of date. Make sure you have the right ABI, otherwise running your subgraph will fail. - -## SpecVersion Releases - -| Version | Release notes | -| :-: | --- | -| 1.2.0 | Added support for [Indexed Argument Filtering](/#indexed-argument-filters--topic-filters) & declared `eth_call` | -| 1.1.0 | Supports [Timeseries & Aggregations](#timeseries-and-aggregations). Added support for type `Int8` for `id`. | -| 1.0.0 | Supports [`indexerHints`](/developing/creating-a-subgraph/#indexer-hints) feature to prune subgraphs | -| 0.0.9 | Supports `endBlock` feature | -| 0.0.8 | Added support for polling [Block Handlers](/developing/creating-a-subgraph/#polling-filter) and [Initialisation Handlers](/developing/creating-a-subgraph/#once-filter). | -| 0.0.7 | Added support for [File Data Sources](/developing/creating-a-subgraph/#file-data-sources). | -| 0.0.6 | Supports fast [Proof of Indexing](/network/indexing/#what-is-a-proof-of-indexing-poi) calculation variant. | -| 0.0.5 | Added support for event handlers having access to transaction receipts. | -| 0.0.4 | Added support for managing subgraph features. | diff --git a/website/pages/ha/developing/creating-a-subgraph/ql-schema.mdx b/website/pages/ha/developing/creating-a-subgraph/ql-schema.mdx deleted file mode 100644 index 90036d1bfab9..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/ql-schema.mdx +++ /dev/null @@ -1,312 +0,0 @@ ---- -title: The Graph QL Schema ---- - -## Overview - -The schema for your subgraph is in the file `schema.graphql`. GraphQL schemas are defined using the GraphQL interface definition language. - -> Note: If you've never written a GraphQL schema, it is recommended that you check out this primer on the GraphQL type system. Reference documentation for GraphQL schemas can be found in the [GraphQL API](/querying/graphql-api/) section. - -### Defining Entities - -Before defining entities, it is important to take a step back and think about how your data is structured and linked. - -- All queries will be made against the data model defined in the subgraph schema. As a result, the design of the subgraph schema should be informed by the queries that your application will need to perform. -- It may be useful to imagine entities as "objects containing data", rather than as events or functions. -- You define entity types in `schema.graphql`, and Graph Node will generate top-level fields for querying single instances and collections of that entity type. -- Each type that should be an entity is required to be annotated with an `@entity` directive. -- By default, entities are mutable, meaning that mappings can load existing entities, modify them and store a new version of that entity. - - Mutability comes at a price, so for entity types that will never be modified, such as those containing data extracted verbatim from the chain, it is recommended to mark them as immutable with `@entity(immutable: true)`. - - If changes happen in the same block in which the entity was created, then mappings can make changes to immutable entities. Immutable entities are much faster to write and to query so they should be used whenever possible. - -#### Good Example - -The following `Gravatar` entity is structured around a Gravatar object and is a good example of how an entity could be defined. - -```graphql -type Gravatar @entity(immutable: true) { - id: Bytes! - owner: Bytes - displayName: String - imageUrl: String - accepted: Boolean -} -``` - -#### Bad Example - -The following example `GravatarAccepted` and `GravatarDeclined` entities are based around events. It is not recommended to map events or function calls to entities 1:1. - -```graphql -type GravatarAccepted @entity { - id: Bytes! - owner: Bytes - displayName: String - imageUrl: String -} - -type GravatarDeclined @entity { - id: Bytes! - owner: Bytes - displayName: String - imageUrl: String -} -``` - -#### Optional and Required Fields - -Entity fields can be defined as required or optional. Required fields are indicated by the `!` in the schema. If the field is a scalar field, you get an error when you try to store the entity. If the field references another entity then you get this error: - -``` -Null value resolved for non-null field 'name' -``` - -Each entity must have an `id` field, which must be of type `Bytes!` or `String!`. It is generally recommended to use `Bytes!`, unless the `id` contains human-readable text, since entities with `Bytes!` id's will be faster to write and query as those with a `String!` `id`. The `id` field serves as the primary key, and needs to be unique among all entities of the same type. For historical reasons, the type `ID!` is also accepted and is a synonym for `String!`. - -For some entity types the `id` for `Bytes!` is constructed from the id's of two other entities; that is possible using `concat`, e.g., `let id = left.id.concat(right.id) ` to form the id from the id's of `left` and `right`. Similarly, to construct an id from the id of an existing entity and a counter `count`, `let id = left.id.concatI32(count)` can be used. The concatenation is guaranteed to produce unique id's as long as the length of `left` is the same for all such entities, for example, because `left.id` is an `Address`. - -### Built-In Scalar Types - -#### GraphQL Supported Scalars - -The following scalars are supported in the GraphQL API: - -| Type | Description | -| --- | --- | -| `Bytes` | Byte array, represented as a hexadecimal string. Commonly used for Ethereum hashes and addresses. | -| `String` | Scalar for `string` values. Null characters are not supported and are automatically removed. | -| `Boolean` | Scalar for `boolean` values. | -| `Int` | The GraphQL spec defines `Int` to be a signed 32-bit integer. | -| `Int8` | An 8-byte signed integer, also known as a 64-bit signed integer, can store values in the range from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. Prefer using this to represent `i64` from ethereum. | -| `BigInt` | Large integers. Used for Ethereum's `uint32`, `int64`, `uint64`, ..., `uint256` types. Note: Everything below `uint32`, such as `int32`, `uint24` or `int8` is represented as `i32`. | -| `BigDecimal` | `BigDecimal` High precision decimals represented as a significand and an exponent. The exponent range is from −6143 to +6144. Rounded to 34 significant digits. | -| `Timestamp` | It is an `i64` value in microseconds. Commonly used for `timestamp` fields for timeseries and aggregations. | - -### Enums - -You can also create enums within a schema. Enums have the following syntax: - -```graphql -enum TokenStatus { - OriginalOwner - SecondOwner - ThirdOwner -} -``` - -Once the enum is defined in the schema, you can use the string representation of the enum value to set an enum field on an entity. For example, you can set the `tokenStatus` to `SecondOwner` by first defining your entity and subsequently setting the field with `entity.tokenStatus = "SecondOwner"`. The example below demonstrates what the Token entity would look like with an enum field: - -More detail on writing enums can be found in the [GraphQL documentation](https://graphql.org/learn/schema/). - -### Entity Relationships - -An entity may have a relationship to one or more other entities in your schema. These relationships may be traversed in your queries. Relationships in The Graph are unidirectional. It is possible to simulate bidirectional relationships by defining a unidirectional relationship on either "end" of the relationship. - -Relationships are defined on entities just like any other field except that the type specified is that of another entity. - -#### One-To-One Relationships - -Define a `Transaction` entity type with an optional one-to-one relationship with a `TransactionReceipt` entity type: - -```graphql -type Transaction @entity(immutable: true) { - id: Bytes! - transactionReceipt: TransactionReceipt -} - -type TransactionReceipt @entity(immutable: true) { - id: Bytes! - transaction: Transaction -} -``` - -#### One-To-Many Relationships - -Define a `TokenBalance` entity type with a required one-to-many relationship with a Token entity type: - -```graphql -type Token @entity(immutable: true) { - id: Bytes! -} - -type TokenBalance @entity { - id: Bytes! - amount: Int! - token: Token! -} -``` - -### Reverse Lookups - -Reverse lookups can be defined on an entity through the `@derivedFrom` field. This creates a virtual field on the entity that may be queried but cannot be set manually through the mappings API. Rather, it is derived from the relationship defined on the other entity. For such relationships, it rarely makes sense to store both sides of the relationship, and both indexing and query performance will be better when only one side is stored and the other is derived. - -For one-to-many relationships, the relationship should always be stored on the 'one' side, and the 'many' side should always be derived. Storing the relationship this way, rather than storing an array of entities on the 'many' side, will result in dramatically better performance for both indexing and querying the subgraph. In general, storing arrays of entities should be avoided as much as is practical. - -#### Example - -We can make the balances for a token accessible from the token by deriving a `tokenBalances` field: - -```graphql -type Token @entity(immutable: true) { - id: Bytes! - tokenBalances: [TokenBalance!]! @derivedFrom(field: "token") -} - -type TokenBalance @entity { - id: Bytes! - amount: Int! - token: Token! -} -``` - -#### Many-To-Many Relationships - -For many-to-many relationships, such as users that each may belong to any number of organizations, the most straightforward, but generally not the most performant, way to model the relationship is as an array in each of the two entities involved. If the relationship is symmetric, only one side of the relationship needs to be stored and the other side can be derived. - -#### Example - -Define a reverse lookup from a `User` entity type to an `Organization` entity type. In the example below, this is achieved by looking up the `members` attribute from within the `Organization` entity. In queries, the `organizations` field on `User` will be resolved by finding all `Organization` entities that include the user's ID. - -```graphql -type Organization @entity { - id: Bytes! - name: String! - members: [User!]! -} - -type User @entity { - id: Bytes! - name: String! - organizations: [Organization!]! @derivedFrom(field: "members") -} -``` - -A more performant way to store this relationship is through a mapping table that has one entry for each `User` / `Organization` pair with a schema like - -```graphql -type Organization @entity { - id: Bytes! - name: String! - members: [UserOrganization!]! @derivedFrom(field: "organization") -} - -type User @entity { - id: Bytes! - name: String! - organizations: [UserOrganization!] @derivedFrom(field: "user") -} - -type UserOrganization @entity { - id: Bytes! # Set to `user.id.concat(organization.id)` - user: User! - organization: Organization! -} -``` - -This approach requires that queries descend into one additional level to retrieve, for example, the organizations for users: - -```graphql -query usersWithOrganizations { - users { - organizations { - # this is a UserOrganization entity - organization { - name - } - } - } -} -``` - -This more elaborate way of storing many-to-many relationships will result in less data stored for the subgraph, and therefore to a subgraph that is often dramatically faster to index and to query. - -### Adding comments to the schema - -As per GraphQL spec, comments can be added above schema entity attributes using the hash symbol `#`. This is illustrated in the example below: - -```graphql -type MyFirstEntity @entity { - # unique identifier and primary key of the entity - id: Bytes! - address: Bytes! -} -``` - -## Defining Fulltext Search Fields - -Fulltext search queries filter and rank entities based on a text search input. Fulltext queries are able to return matches for similar words by processing the query text input into stems before comparing them to the indexed text data. - -A fulltext query definition includes the query name, the language dictionary used to process the text fields, the ranking algorithm used to order the results, and the fields included in the search. Each fulltext query may span multiple fields, but all included fields must be from a single entity type. - -To add a fulltext query, include a `_Schema_` type with a fulltext directive in the GraphQL schema. - -```graphql -type _Schema_ - @fulltext( - name: "bandSearch" - language: en - algorithm: rank - include: [{ entity: "Band", fields: [{ name: "name" }, { name: "description" }, { name: "bio" }] }] - ) - -type Band @entity { - id: Bytes! - name: String! - description: String! - bio: String - wallet: Address - labels: [Label!]! - discography: [Album!]! - members: [Musician!]! -} -``` - -The example `bandSearch` field can be used in queries to filter `Band` entities based on the text documents in the `name`, `description`, and `bio` fields. Jump to [GraphQL API - Queries](/querying/graphql-api#queries) for a description of the fulltext search API and more example usage. - -```graphql -query { - bandSearch(text: "breaks & electro & detroit") { - id - name - description - wallet - } -} -``` - -> **[Feature Management](#experimental-features):** From `specVersion` `0.0.4` and onwards, `fullTextSearch` must be declared under the `features` section in the subgraph manifest. - -## Languages supported - -Choosing a different language will have a definitive, though sometimes subtle, effect on the fulltext search API. Fields covered by a fulltext query field are examined in the context of the chosen language, so the lexemes produced by analysis and search queries vary from language to language. For example: when using the supported Turkish dictionary "token" is stemmed to "toke" while, of course, the English dictionary will stem it to "token". - -Supported language dictionaries: - -| Code | Dictionary | -| ------ | ---------- | -| simple | General | -| da | Danish | -| nl | Dutch | -| en | English | -| fi | Finnish | -| fr | French | -| de | German | -| hu | Hungarian | -| it | Italian | -| no | Norwegian | -| pt | Portuguese | -| ro | Romanian | -| ru | Russian | -| es | Spanish | -| sv | Swedish | -| tr | Turkish | - -### Ranking Algorithms - -Supported algorithms for ordering results: - -| Algorithm | Description | -| ------------- | ----------------------------------------------------------------------- | -| rank | Use the match quality (0-1) of the fulltext query to order the results. | -| proximityRank | Similar to rank but also includes the proximity of the matches. | diff --git a/website/pages/ha/developing/creating-a-subgraph/starting-your-subgraph.mdx b/website/pages/ha/developing/creating-a-subgraph/starting-your-subgraph.mdx deleted file mode 100644 index 5127f01632aa..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/starting-your-subgraph.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Starting Your Subgraph ---- - -## Overview - -The Graph is home to thousands of subgraphs already available for query, so check [The Graph Explorer](https://thegraph.com/explorer) and find one that already matches your needs. - -When you create a [subgraph](/subgraphs/), you create a custom open API that extracts data from a blockchain, processes it, stores it, and makes it easy to query via GraphQL. - -Subgraph development ranges from simple scaffold subgraphs to advanced, specifically tailored subgraphs. - -### Start Building - -Start the process and build a subgraph that matches your needs: - -1. [Install the CLI](/developing/creating-a-subgraph/install-the-cli/) - Set up your infrastructure -2. [Subgraph Manifest](/developing/creating-a-subgraph/subgraph-manifest/) - Understand a subgraph's key component -3. [The Graph Ql Schema](/developing/creating-a-subgraph/ql-schema/) - Write your schema -4. [Writing AssemblyScript Mappings](/developing/creating-a-subgraph/assemblyscript-mappings/) - Write your mappings -5. [Advanced Features](/developing/creating-a-subgraph/advanced/) - Customize your subgraph with advanced features diff --git a/website/pages/ha/developing/creating-a-subgraph/subgraph-manifest.mdx b/website/pages/ha/developing/creating-a-subgraph/subgraph-manifest.mdx deleted file mode 100644 index 7476b7175d57..000000000000 --- a/website/pages/ha/developing/creating-a-subgraph/subgraph-manifest.mdx +++ /dev/null @@ -1,534 +0,0 @@ ---- -title: Subgraph Manifest ---- - -## Overview - -The subgraph manifest, `subgraph.yaml`, defines the smart contracts & network your subgraph will index, the events from these contracts to pay attention to, and how to map event data to entities that Graph Node stores and allows to query. - -The **subgraph definition** consists of the following files: - -- `subgraph.yaml`: Contains the subgraph manifest - -- `schema.graphql`: A GraphQL schema defining the data stored for your subgraph and how to query it via GraphQL - -- `mapping.ts`: [AssemblyScript Mappings](https://github.com/AssemblyScript/assemblyscript) code that translates event data into entities defined in your schema (e.g. `mapping.ts` in this guide) - -### Subgraph Capabilities - -A single subgraph can: - -- Index data from multiple smart contracts (but not multiple networks). - -- Index data from IPFS files using File Data Sources. - -- Add an entry for each contract that requires indexing to the `dataSources` array. - -The full specification for subgraph manifests can be found [here](https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md). - -For the example subgraph listed above, `subgraph.yaml` is: - -```yaml -specVersion: 0.0.4 -description: Gravatar for Ethereum -repository: https://github.com/graphprotocol/graph-tooling -schema: - file: ./schema.graphql -indexerHints: - prune: auto -dataSources: - - kind: ethereum/contract - name: Gravity - network: mainnet - source: - address: '0x2E645469f354BB4F5c8a05B3b30A929361cf77eC' - abi: Gravity - startBlock: 6175244 - endBlock: 7175245 - context: - foo: - type: Bool - data: true - bar: - type: String - data: 'bar' - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Gravatar - abis: - - name: Gravity - file: ./abis/Gravity.json - eventHandlers: - - event: NewGravatar(uint256,address,string,string) - handler: handleNewGravatar - - event: UpdatedGravatar(uint256,address,string,string) - handler: handleUpdatedGravatar - callHandlers: - - function: createGravatar(string,string) - handler: handleCreateGravatar - blockHandlers: - - handler: handleBlock - - handler: handleBlockWithCall - filter: - kind: call - file: ./src/mapping.ts -``` - -## Subgraph Entries - -> Important Note: Be sure you populate your subgraph manifest with all handlers and [entities](/developing/creating-a-subgraph/ql-schema/). - -The important entries to update for the manifest are: - -- `specVersion`: a semver version that identifies the supported manifest structure and functionality for the subgraph. The latest version is `1.2.0`. See [specVersion releases](#specversion-releases) section to see more details on features & releases. - -- `description`: a human-readable description of what the subgraph is. This description is displayed in Graph Explorer when the subgraph is deployed to Subgraph Studio. - -- `repository`: the URL of the repository where the subgraph manifest can be found. This is also displayed in Graph Explorer. - -- `features`: a list of all used [feature](#experimental-features) names. - -- `indexerHints.prune`: Defines the retention of historical block data for a subgraph. See [prune](#prune) in [indexerHints](#indexer-hints) section. - -- `dataSources.source`: the address of the smart contract the subgraph sources, and the ABI of the smart contract to use. The address is optional; omitting it allows to index matching events from all contracts. - -- `dataSources.source.startBlock`: the optional number of the block that the data source starts indexing from. In most cases, we suggest using the block in which the contract was created. - -- `dataSources.source.endBlock`: The optional number of the block that the data source stops indexing at, including that block. Minimum spec version required: `0.0.9`. - -- `dataSources.context`: key-value pairs that can be used within subgraph mappings. Supports various data types like `Bool`, `String`, `Int`, `Int8`, `BigDecimal`, `Bytes`, `List`, and `BigInt`. Each variable needs to specify its `type` and `data`. These context variables are then accessible in the mapping files, offering more configurable options for subgraph development. - -- `dataSources.mapping.entities`: the entities that the data source writes to the store. The schema for each entity is defined in the schema.graphql file. - -- `dataSources.mapping.abis`: one or more named ABI files for the source contract as well as any other smart contracts that you interact with from within the mappings. - -- `dataSources.mapping.eventHandlers`: lists the smart contract events this subgraph reacts to and the handlers in the mapping—./src/mapping.ts in the example—that transform these events into entities in the store. - -- `dataSources.mapping.callHandlers`: lists the smart contract functions this subgraph reacts to and handlers in the mapping that transform the inputs and outputs to function calls into entities in the store. - -- `dataSources.mapping.blockHandlers`: lists the blocks this subgraph reacts to and handlers in the mapping to run when a block is appended to the chain. Without a filter, the block handler will be run every block. An optional call-filter can be provided by adding a `filter` field with `kind: call` to the handler. This will only run the handler if the block contains at least one call to the data source contract. - -A single subgraph can index data from multiple smart contracts. Add an entry for each contract from which data needs to be indexed to the `dataSources` array. - -## Event Handlers - -Event handlers in a subgraph react to specific events emitted by smart contracts on the blockchain and trigger handlers defined in the subgraph's manifest. This enables subgraphs to process and store event data according to defined logic. - -### Defining an Event Handler - -An event handler is declared within a data source in the subgraph's YAML configuration. It specifies which events to listen for and the corresponding function to execute when those events are detected. - -```yaml -dataSources: - - kind: ethereum/contract - name: Gravity - network: dev - source: - address: '0x731a10897d267e19b34503ad902d0a29173ba4b1' - abi: Gravity - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Gravatar - - Transaction - abis: - - name: Gravity - file: ./abis/Gravity.json - eventHandlers: - - event: Approval(address,address,uint256) - handler: handleApproval - - event: Transfer(address,address,uint256) - handler: handleTransfer - topic1: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', '0xc8dA6BF26964aF9D7eEd9e03E53415D37aA96325'] # Optional topic filter which filters only events with the specified topic. -``` - -## Call Handlers - -While events provide an effective way to collect relevant changes to the state of a contract, many contracts avoid generating logs to optimize gas costs. In these cases, a subgraph can subscribe to calls made to the data source contract. This is achieved by defining call handlers referencing the function signature and the mapping handler that will process calls to this function. To process these calls, the mapping handler will receive an `ethereum.Call` as an argument with the typed inputs to and outputs from the call. Calls made at any depth in a transaction's call chain will trigger the mapping, allowing activity with the data source contract through proxy contracts to be captured. - -Call handlers will only trigger in one of two cases: when the function specified is called by an account other than the contract itself or when it is marked as external in Solidity and called as part of another function in the same contract. - -> **Note:** Call handlers currently depend on the Parity tracing API. Certain networks, such as BNB chain and Arbitrum, does not support this API. If a subgraph indexing one of these networks contain one or more call handlers, it will not start syncing. Subgraph developers should instead use event handlers. These are far more performant than call handlers, and are supported on every evm network. - -### Defining a Call Handler - -To define a call handler in your manifest, simply add a `callHandlers` array under the data source you would like to subscribe to. - -```yaml -dataSources: - - kind: ethereum/contract - name: Gravity - network: mainnet - source: - address: '0x731a10897d267e19b34503ad902d0a29173ba4b1' - abi: Gravity - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Gravatar - - Transaction - abis: - - name: Gravity - file: ./abis/Gravity.json - callHandlers: - - function: createGravatar(string,string) - handler: handleCreateGravatar -``` - -The `function` is the normalized function signature to filter calls by. The `handler` property is the name of the function in your mapping you would like to execute when the target function is called in the data source contract. - -### Mapping Function - -Each call handler takes a single parameter that has a type corresponding to the name of the called function. In the example subgraph above, the mapping contains a handler for when the `createGravatar` function is called and receives a `CreateGravatarCall` parameter as an argument: - -```typescript -import { CreateGravatarCall } from '../generated/Gravity/Gravity' -import { Transaction } from '../generated/schema' - -export function handleCreateGravatar(call: CreateGravatarCall): void { - let id = call.transaction.hash - let transaction = new Transaction(id) - transaction.displayName = call.inputs._displayName - transaction.imageUrl = call.inputs._imageUrl - transaction.save() -} -``` - -The `handleCreateGravatar` function takes a new `CreateGravatarCall` which is a subclass of `ethereum.Call`, provided by `@graphprotocol/graph-ts`, that includes the typed inputs and outputs of the call. The `CreateGravatarCall` type is generated for you when you run `graph codegen`. - -## Block Handlers - -In addition to subscribing to contract events or function calls, a subgraph may want to update its data as new blocks are appended to the chain. To achieve this a subgraph can run a function after every block or after blocks that match a pre-defined filter. - -### Supported Filters - -#### Call Filter - -```yaml -filter: - kind: call -``` - -_The defined handler will be called once for every block which contains a call to the contract (data source) the handler is defined under._ - -> **Note:** The `call` filter currently depend on the Parity tracing API. Certain networks, such as BNB chain and Arbitrum, does not support this API. If a subgraph indexing one of these networks contain one or more block handlers with a `call` filter, it will not start syncing. - -The absence of a filter for a block handler will ensure that the handler is called every block. A data source can only contain one block handler for each filter type. - -```yaml -dataSources: - - kind: ethereum/contract - name: Gravity - network: dev - source: - address: '0x731a10897d267e19b34503ad902d0a29173ba4b1' - abi: Gravity - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - entities: - - Gravatar - - Transaction - abis: - - name: Gravity - file: ./abis/Gravity.json - blockHandlers: - - handler: handleBlock - - handler: handleBlockWithCallToContract - filter: - kind: call -``` - -#### Polling Filter - -> **Requires `specVersion` >= 0.0.8** - -> **Note:** Polling filters are only available on dataSources of `kind: ethereum`. - -```yaml -blockHandlers: - - handler: handleBlock - filter: - kind: polling - every: 10 -``` - -The defined handler will be called once for every `n` blocks, where `n` is the value provided in the `every` field. This configuration allows the subgraph to perform specific operations at regular block intervals. - -#### Once Filter - -> **Requires `specVersion` >= 0.0.8** - -> **Note:** Once filters are only available on dataSources of `kind: ethereum`. - -```yaml -blockHandlers: - - handler: handleOnce - filter: - kind: once -``` - -The defined handler with the once filter will be called only once before all other handlers run. This configuration allows the subgraph to use the handler as an initialization handler, performing specific tasks at the start of indexing. - -```ts -export function handleOnce(block: ethereum.Block): void { - let data = new InitialData(Bytes.fromUTF8('initial')) - data.data = 'Setup data here' - data.save() -} -``` - -### Mapping Function - -The mapping function will receive an `ethereum.Block` as its only argument. Like mapping functions for events, this function can access existing subgraph entities in the store, call smart contracts and create or update entities. - -```typescript -import { ethereum } from '@graphprotocol/graph-ts' - -export function handleBlock(block: ethereum.Block): void { - let id = block.hash - let entity = new Block(id) - entity.save() -} -``` - -## Anonymous Events - -If you need to process anonymous events in Solidity, that can be achieved by providing the topic 0 of the event, as in the example: - -```yaml -eventHandlers: - - event: LogNote(bytes4,address,bytes32,bytes32,uint256,bytes) - topic0: '0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31' - handler: handleGive -``` - -An event will only be triggered when both the signature and topic 0 match. By default, `topic0` is equal to the hash of the event signature. - -## Transaction Receipts in Event Handlers - -Starting from `specVersion` `0.0.5` and `apiVersion` `0.0.7`, event handlers can have access to the receipt for the transaction which emitted them. - -To do so, event handlers must be declared in the subgraph manifest with the new `receipt: true` key, which is optional and defaults to false. - -```yaml -eventHandlers: - - event: NewGravatar(uint256,address,string,string) - handler: handleNewGravatar - receipt: true -``` - -Inside the handler function, the receipt can be accessed in the `Event.receipt` field. When the `receipt` key is set to `false` or omitted in the manifest, a `null` value will be returned instead. - -## Order of Triggering Handlers - -The triggers for a data source within a block are ordered using the following process: - -1. Event and call triggers are first ordered by transaction index within the block. -2. Event and call triggers within the same transaction are ordered using a convention: event triggers first then call triggers, each type respecting the order they are defined in the manifest. -3. Block triggers are run after event and call triggers, in the order they are defined in the manifest. - -These ordering rules are subject to change. - -> **Note:** When new [dynamic data source](#data-source-templates-for-dynamically-created-contracts) are created, the handlers defined for dynamic data sources will only start processing after all existing data source handlers are processed, and will repeat in the same sequence whenever triggered. - -## Data Source Templates - -A common pattern in EVM-compatible smart contracts is the use of registry or factory contracts, where one contract creates, manages, or references an arbitrary number of other contracts that each have their own state and events. - -The addresses of these sub-contracts may or may not be known upfront and many of these contracts may be created and/or added over time. This is why, in such cases, defining a single data source or a fixed number of data sources is impossible and a more dynamic approach is needed: _data source templates_. - -### Data Source for the Main Contract - -First, you define a regular data source for the main contract. The snippet below shows a simplified example data source for the [Uniswap](https://uniswap.org) exchange factory contract. Note the `NewExchange(address,address)` event handler. This is emitted when a new exchange contract is created on-chain by the factory contract. - -```yaml -dataSources: - - kind: ethereum/contract - name: Factory - network: mainnet - source: - address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95' - abi: Factory - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - file: ./src/mappings/factory.ts - entities: - - Directory - abis: - - name: Factory - file: ./abis/factory.json - eventHandlers: - - event: NewExchange(address,address) - handler: handleNewExchange -``` - -### Data Source Templates for Dynamically Created Contracts - -Then, you add _data source templates_ to the manifest. These are identical to regular data sources, except that they lack a pre-defined contract address under `source`. Typically, you would define one template for each type of sub-contract managed or referenced by the parent contract. - -```yaml -dataSources: - - kind: ethereum/contract - name: Factory - # ... other source fields for the main contract ... -templates: - - name: Exchange - kind: ethereum/contract - network: mainnet - source: - abi: Exchange - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - file: ./src/mappings/exchange.ts - entities: - - Exchange - abis: - - name: Exchange - file: ./abis/exchange.json - eventHandlers: - - event: TokenPurchase(address,uint256,uint256) - handler: handleTokenPurchase - - event: EthPurchase(address,uint256,uint256) - handler: handleEthPurchase - - event: AddLiquidity(address,uint256,uint256) - handler: handleAddLiquidity - - event: RemoveLiquidity(address,uint256,uint256) - handler: handleRemoveLiquidity -``` - -### Instantiating a Data Source Template - -In the final step, you update your main contract mapping to create a dynamic data source instance from one of the templates. In this example, you would change the main contract mapping to import the `Exchange` template and call the `Exchange.create(address)` method on it to start indexing the new exchange contract. - -```typescript -import { Exchange } from '../generated/templates' - -export function handleNewExchange(event: NewExchange): void { - // Start indexing the exchange; `event.params.exchange` is the - // address of the new exchange contract - Exchange.create(event.params.exchange) -} -``` - -> **Note:** A new data source will only process the calls and events for the block in which it was created and all following blocks, but will not process historical data, i.e., data that is contained in prior blocks. -> -> If prior blocks contain data relevant to the new data source, it is best to index that data by reading the current state of the contract and creating entities representing that state at the time the new data source is created. - -### Data Source Context - -Data source contexts allow passing extra configuration when instantiating a template. In our example, let's say exchanges are associated with a particular trading pair, which is included in the `NewExchange` event. That information can be passed into the instantiated data source, like so: - -```typescript -import { Exchange } from '../generated/templates' - -export function handleNewExchange(event: NewExchange): void { - let context = new DataSourceContext() - context.setString('tradingPair', event.params.tradingPair) - Exchange.createWithContext(event.params.exchange, context) -} -``` - -Inside a mapping of the `Exchange` template, the context can then be accessed: - -```typescript -import { dataSource } from '@graphprotocol/graph-ts' - -let context = dataSource.context() -let tradingPair = context.getString('tradingPair') -``` - -There are setters and getters like `setString` and `getString` for all value types. - -## Start Blocks - -The `startBlock` is an optional setting that allows you to define from which block in the chain the data source will start indexing. Setting the start block allows the data source to skip potentially millions of blocks that are irrelevant. Typically, a subgraph developer will set `startBlock` to the block in which the smart contract of the data source was created. - -```yaml -dataSources: - - kind: ethereum/contract - name: ExampleSource - network: mainnet - source: - address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95' - abi: ExampleContract - startBlock: 6627917 - mapping: - kind: ethereum/events - apiVersion: 0.0.6 - language: wasm/assemblyscript - file: ./src/mappings/factory.ts - entities: - - User - abis: - - name: ExampleContract - file: ./abis/ExampleContract.json - eventHandlers: - - event: NewEvent(address,address) - handler: handleNewEvent -``` - -> **Note:** The contract creation block can be quickly looked up on Etherscan: -> -> 1. Search for the contract by entering its address in the search bar. -> 2. Click on the creation transaction hash in the `Contract Creator` section. -> 3. Load the transaction details page where you'll find the start block for that contract. - -## Indexer Hints - -The `indexerHints` setting in a subgraph's manifest provides directives for indexers on processing and managing a subgraph. It influences operational decisions across data handling, indexing strategies, and optimizations. Presently, it features the `prune` option for managing historical data retention or pruning. - -> This feature is available from `specVersion: 1.0.0` - -### Prune - -`indexerHints.prune`: Defines the retention of historical block data for a subgraph. Options include: - -1. `"never"`: No pruning of historical data; retains the entire history. -2. `"auto"`: Retains the minimum necessary history as set by the indexer, optimizing query performance. -3. A specific number: Sets a custom limit on the number of historical blocks to retain. - -``` - indexerHints: - prune: auto -``` - -> The term "history" in this context of subgraphs is about storing data that reflects the old states of mutable entities. - -History as of a given block is required for: - -- [Time travel queries](/querying/graphql-api/#time-travel-queries), which enable querying the past states of these entities at specific blocks throughout the subgraph's history -- Using the subgraph as a [graft base](/developing/creating-a-subgraph/#grafting-onto-existing-subgraphs) in another subgraph, at that block -- Rewinding the subgraph back to that block - -If historical data as of the block has been pruned, the above capabilities will not be available. - -> Using `"auto"` is generally recommended as it maximizes query performance and is sufficient for most users who do not require access to extensive historical data. - -For subgraphs leveraging [time travel queries](/querying/graphql-api/#time-travel-queries), it's advisable to either set a specific number of blocks for historical data retention or use `prune: never` to keep all historical entity states. Below are examples of how to configure both options in your subgraph's settings: - -To retain a specific amount of historical data: - -``` - indexerHints: - prune: 1000 # Replace 1000 with the desired number of blocks to retain -``` - -To preserve the complete history of entity states: - -``` -indexerHints: - prune: never -``` diff --git a/website/pages/ha/developing/developer-faqs.mdx b/website/pages/ha/developing/developer-faqs.mdx deleted file mode 100644 index 7e30e6a9db06..000000000000 --- a/website/pages/ha/developing/developer-faqs.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: Developer FAQs ---- - -## 1. What is a subgraph? - -A subgraph is a custom API built on blockchain data. Subgraphs are queried using the GraphQL query language and are deployed to a Graph Node using the Graph CLI. Once deployed and published to The Graph's decentralized network, Indexers process subgraphs and make them available to be queried by subgraph consumers. - -## 2. Can I delete my subgraph? - -It is not possible to delete subgraphs once they are created. - -## 3. Can I change my subgraph name? - -No. Once a subgraph is created, the name cannot be changed. Make sure to think of this carefully before you create your subgraph so it is easily searchable and identifiable by other dapps. - -## 4. Can I change the GitHub account associated with my subgraph? - -No. Once a subgraph is created, the associated GitHub account cannot be changed. Make sure to think of this carefully before you create your subgraph. - -## 5. Am I still able to create a subgraph if my smart contracts don't have events? - -It is highly recommended that you structure your smart contracts to have events associated with data you are interested in querying. Event handlers in the subgraph are triggered by contract events and are by far the fastest way to retrieve useful data. - -If the contracts you are working with do not contain events, your subgraph can use call and block handlers to trigger indexing. Although this is not recommended, as performance will be significantly slower. - -## 6. Is it possible to deploy one subgraph with the same name for multiple networks? - -You will need separate names for multiple networks. While you can't have different subgraphs under the same name, there are convenient ways of having a single codebase for multiple networks. Find more on this in our documentation: [Redeploying a Subgraph](/deploying/deploying-a-subgraph-to-hosted#redeploying-a-subgraph) - -## 7. How are templates different from data sources? - -Templates allow you to create data sources on the fly, while your subgraph is indexing. It might be the case that your contract will spawn new contracts as people interact with it, and since you know the shape of those contracts (ABI, events, etc) upfront you can define how you want to index them in a template and when they are spawned your subgraph will create a dynamic data source by supplying the contract address. - -Check out the "Instantiating a data source template" section on: [Data Source Templates](/developing/creating-a-subgraph#data-source-templates). - -## 8. How do I make sure I'm using the latest version of graph-node for my local deployments? - -You can run the following command: - -```sh -docker pull graphprotocol/graph-node:latest -``` - -**NOTE:** docker / docker-compose will always use whatever graph-node version was pulled the first time you ran it, so it is important to do this to make sure you are up to date with the latest version of graph-node. - -## 9. How do I call a contract function or access a public state variable from my subgraph mappings? - -Take a look at `Access to smart contract` state inside the section [AssemblyScript API](/developing/graph-ts/api). - -## 10. Is it possible to set up a subgraph using `graph init` from `graph-cli` with two contracts? Or should I manually add another datasource in `subgraph.yaml` after running `graph init`? - -Unfortunately, this is currently not possible. `graph init` is intended as a basic starting point, from which you can then add more data sources manually. - -## 11. I want to contribute or add a GitHub issue. Where can I find the open source repositories? - -- [graph-node](https://github.com/graphprotocol/graph-node) -- [graph-cli](https://github.com/graphprotocol/graph-cli) -- [graph-ts](https://github.com/graphprotocol/graph-ts) - -## 12. What is the recommended way to build "autogenerated" ids for an entity when handling events? - -If only one entity is created during the event and if there's nothing better available, then the transaction hash + log index would be unique. You can obfuscate these by converting that to Bytes and then piping it through `crypto.keccak256` but this won't make it more unique. - -## 13. When listening to multiple contracts, is it possible to select the contract order to listen to events? - -Within a subgraph, the events are always processed in the order they appear in the blocks, regardless of whether that is across multiple contracts or not. - -## 14. Is it possible to differentiate between networks (mainnet, Sepolia, local) from within event handlers? - -Yes. You can do this by importing `graph-ts` as per the example below: - -```javascript -import { dataSource } from '@graphprotocol/graph-ts' - -dataSource.network() -dataSource.address() -``` - -## 15. Do you support block and call handlers on Sepolia? - -Yes. Sepolia supports block handlers, call handlers and event handlers. It should be noted that event handlers are far more performant than the other two handlers, and they are supported on every EVM-compatible network. - -## 16. Can I import ethers.js or other JS libraries into my subgraph mappings? - -Not currently, as mappings are written in AssemblyScript. One possible alternative solution to this is to store raw data in entities and perform logic that requires JS libraries on the client. - -## 17. Is it possible to specify what block to start indexing on? - -Yes. `dataSources.source.startBlock` in the `subgraph.yaml` file specifies the number of the block that the data source starts indexing from. In most cases, we suggest using the block in which the contract was created: Start blocks - -## 18. Are there some tips to increase the performance of indexing? My subgraph is taking a very long time to sync - -Yes, you should take a look at the optional start block feature to start indexing from the block that the contract was deployed: [Start blocks](/developing/creating-a-subgraph#start-blocks) - -## 19. Is there a way to query the subgraph directly to determine the latest block number it has indexed? - -Yes! Try the following command, substituting "organization/subgraphName" with the organization under it is published and the name of your subgraph: - -```sh -curl -X POST -d '{ "query": "{indexingStatusForCurrentVersion(subgraphName: \"organization/subgraphName\") { chains { latestBlock { hash number }}}}"}' https://api.thegraph.com/index-node/graphql -``` - -## 20. What networks are supported by The Graph? - -You can find the list of the supported networks [here](/developing/supported-networks). - -## 21. Is it possible to duplicate a subgraph to another account or endpoint without redeploying? - -You have to redeploy the subgraph, but if the subgraph ID (IPFS hash) doesn't change, it won't have to sync from the beginning. - -## 22. Is this possible to use Apollo Federation on top of graph-node? - -Federation is not supported yet, although we do want to support it in the future. At the moment, something you can do is use schema stitching, either on the client or via a proxy service. - -## 23. Is there a limit to how many objects The Graph can return per query? - -By default, query responses are limited to 100 items per collection. If you want to receive more, you can go up to 1000 items per collection and beyond that, you can paginate with: - -```graphql -someCollection(first: 1000, skip: ) { ... } -``` - -## 24. If my dapp frontend uses The Graph for querying, do I need to write my query key into the frontend directly? What if we pay query fees for users – will malicious users cause our query fees to be very high? - -Currently, the recommended approach for a dapp is to add the key to the frontend and expose it to end users. That said, you can limit that key to a hostname, like _yourdapp.io_ and subgraph. The gateway is currently being run by Edge & Node. Part of the responsibility of a gateway is to monitor for abusive behavior and block traffic from malicious clients. - -## 25. Where do I go to find my current subgraph on the hosted service? - -Head over to the hosted service in order to find subgraphs that you or others deployed to the hosted service. You can find it [here](https://thegraph.com/hosted-service). - -## 26. Will the hosted service start charging query fees? - -The Graph will never charge for the hosted service. The Graph is a decentralized protocol, and charging for a centralized service is not aligned with The Graph’s values. The hosted service was always a temporary step to help get to the decentralized network. Developers will have a sufficient amount of time to upgrade to the decentralized network as they are comfortable. - -## 27. How do I update a subgraph on mainnet? - -If you’re a subgraph developer, you can deploy a new version of your subgraph to the Subgraph Studio using the CLI. It’ll be private at that point, but if you’re happy with it, you can publish to the decentralized Graph Explorer. This will create a new version of your subgraph that Curators can start signaling on. diff --git a/website/pages/ha/developing/graph-ts/_meta.js b/website/pages/ha/developing/graph-ts/_meta.js deleted file mode 100644 index 466762da9ce8..000000000000 --- a/website/pages/ha/developing/graph-ts/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../../en/developing/graph-ts/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/developing/graph-ts/api.mdx b/website/pages/ha/developing/graph-ts/api.mdx deleted file mode 100644 index 45bfad8f7bfb..000000000000 --- a/website/pages/ha/developing/graph-ts/api.mdx +++ /dev/null @@ -1,854 +0,0 @@ ---- -title: AssemblyScript API ---- - -> Note: if you created a subgraph prior to `graph-cli`/`graph-ts` version `0.22.0`, you're using an older version of AssemblyScript, we recommend taking a look at the [`Migration Guide`](/release-notes/assemblyscript-migration-guide) - -This page documents what built-in APIs can be used when writing subgraph mappings. Two kinds of APIs are available out of the box: - -- the [Graph TypeScript library](https://github.com/graphprotocol/graph-ts) (`graph-ts`) and -- code generated from subgraph files by `graph codegen`. - -It is also possible to add other libraries as dependencies, as long as they are compatible with [AssemblyScript](https://github.com/AssemblyScript/assemblyscript). Since this is the language mappings are written in, the [AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki) is a good source for language and standard library features. - -## API Reference - -The `@graphprotocol/graph-ts` library provides the following APIs: - -- An `ethereum` API for working with Ethereum smart contracts, events, blocks, transactions, and Ethereum values. -- A `store` API to load and save entities from and to the Graph Node store. -- A `log` API to log messages to the Graph Node output and the Graph Explorer. -- An `ipfs` API to load files from IPFS. -- A `json` API to parse JSON data. -- A `crypto` API to use cryptographic functions. -- Low-level primitives to translate between different type systems such as Ethereum, JSON, GraphQL and AssemblyScript. - -### Versions - -The `apiVersion` in the subgraph manifest specifies the mapping API version which is run by Graph Node for a given subgraph. - -| Version | Release notes | -| :-: | --- | -| 0.0.7 | Added `TransactionReceipt` and `Log` classes to the Ethereum types
Added `receipt` field to the Ethereum Event object | -| 0.0.6 | Added `nonce` field to the Ethereum Transaction object
Added `baseFeePerGas` to the Ethereum Block object | -| 0.0.5 | AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the [`Migration Guide`](/release-notes/assemblyscript-migration-guide))
`ethereum.transaction.gasUsed` renamed to `ethereum.transaction.gasLimit` | -| 0.0.4 | Added `functionSignature` field to the Ethereum SmartContractCall object | -| 0.0.3 | Added `from` field to the Ethereum Call object
`etherem.call.address` renamed to `ethereum.call.to` | -| 0.0.2 | Added `input` field to the Ethereum Transaction object | - -### Built-in Types - -Documentation on the base types built into AssemblyScript can be found in the [AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki/Types). - -The following additional types are provided by `@graphprotocol/graph-ts`. - -#### ByteArray - -```typescript -import { ByteArray } from '@graphprotocol/graph-ts' -``` - -`ByteArray` represents an array of `u8`. - -_Construction_ - -- `fromI32(x: i32): ByteArray` - Decomposes `x` into bytes. -- `fromHexString(hex: string): ByteArray` - Input length must be even. Prefixing with `0x` is optional. - -_Type conversions_ - -- `toHexString(): string` - Converts to a hex string prefixed with `0x`. -- `toString(): string` - Interprets the bytes as a UTF-8 string. -- `toBase58(): string` - Encodes the bytes into a base58 string. -- `toU32(): u32` - Interprets the bytes as a little-endian `u32`. Throws in case of overflow. -- `toI32(): i32` - Interprets the byte array as a little-endian `i32`. Throws in case of overflow. - -_Operators_ - -- `equals(y: ByteArray): bool` – can be written as `x == y`. -- `concat(other: ByteArray) : ByteArray` - return a new `ByteArray` consisting of `this` directly followed by `other` -- `concatI32(other: i32) : ByteArray` - return a new `ByteArray` consisting of `this` directly followed by the byte representation of `other` - -#### BigDecimal - -```typescript -import { BigDecimal } from '@graphprotocol/graph-ts' -``` - -`BigDecimal` is used to represent arbitrary precision decimals. - -> Note: [Internally](https://github.com/graphprotocol/graph-node/blob/master/graph/src/data/store/scalar.rs) `BigDecimal` is stored in [IEEE-754 decimal128 floating-point format](https://en.wikipedia.org/wiki/Decimal128_floating-point_format), which supports 34 decimal digits of significand. This makes `BigDecimal` unsuitable for representing fixed-point types that can span wider than 34 digits, such as a Solidity [`ufixed256x18`](https://docs.soliditylang.org/en/latest/types.html#fixed-point-numbers) or equivalent. - -_Construction_ - -- `constructor(bigInt: BigInt)` – creates a `BigDecimal` from an `BigInt`. -- `static fromString(s: string): BigDecimal` – parses from a decimal string. - -_Type conversions_ - -- `toString(): string` – prints to a decimal string. - -_Math_ - -- `plus(y: BigDecimal): BigDecimal` – can be written as `x + y`. -- `minus(y: BigDecimal): BigDecimal` – can be written as `x - y`. -- `times(y: BigDecimal): BigDecimal` – can be written as `x * y`. -- `div(y: BigDecimal): BigDecimal` – can be written as `x / y`. -- `equals(y: BigDecimal): bool` – can be written as `x == y`. -- `notEqual(y: BigDecimal): bool` – can be written as `x != y`. -- `lt(y: BigDecimal): bool` – can be written as `x < y`. -- `le(y: BigDecimal): bool` – can be written as `x <= y`. -- `gt(y: BigDecimal): bool` – can be written as `x > y`. -- `ge(y: BigDecimal): bool` – can be written as `x >= y`. -- `neg(): BigDecimal` - can be written as `-x`. - -#### BigInt - -```typescript -import { BigInt } from '@graphprotocol/graph-ts' -``` - -`BigInt` is used to represent big integers. This includes Ethereum values of type `uint32` to `uint256` and `int64` to `int256`. Everything below `uint32`, such as `int32`, `uint24` or `int8` is represented as `i32`. - -The `BigInt` class has the following API: - -_Construction_ - -- `BigInt.fromI32(x: i32): BigInt` – creates a `BigInt` from an `i32`. - -- `BigInt.fromString(s: string): BigInt`– Parses a `BigInt` from a string. - -- `BigInt.fromUnsignedBytes(x: Bytes): BigInt` – Interprets `bytes` as an unsigned, little-endian integer. If your input is big-endian, call `.reverse()` first. - -- `BigInt.fromSignedBytes(x: Bytes): BigInt` – Interprets `bytes` as a signed, little-endian integer. If your input is big-endian, call `.reverse()` first. - - _Type conversions_ - -- `x.toHex(): string` – turns `BigInt` into a string of hexadecimal characters. - -- `x.toString(): string` – turns `BigInt` into a decimal number string. - -- `x.toI32(): i32` – returns the `BigInt` as an `i32`; fails if the value does not fit into `i32`. It's a good idea to first check `x.isI32()`. - -- `x.toBigDecimal(): BigDecimal` - converts into a decimal with no fractional part. - -_Math_ - -- `x.plus(y: BigInt): BigInt` – can be written as `x + y`. -- `x.minus(y: BigInt): BigInt` – can be written as `x - y`. -- `x.times(y: BigInt): BigInt` – can be written as `x * y`. -- `x.div(y: BigInt): BigInt` – can be written as `x / y`. -- `x.mod(y: BigInt): BigInt` – can be written as `x % y`. -- `x.equals(y: BigInt): bool` – can be written as `x == y`. -- `x.notEqual(y: BigInt): bool` – can be written as `x != y`. -- `x.lt(y: BigInt): bool` – can be written as `x < y`. -- `x.le(y: BigInt): bool` – can be written as `x <= y`. -- `x.gt(y: BigInt): bool` – can be written as `x > y`. -- `x.ge(y: BigInt): bool` – can be written as `x >= y`. -- `x.neg(): BigInt` – can be written as `-x`. -- `x.divDecimal(y: BigDecimal): BigDecimal` – divides by a decimal, giving a decimal result. -- `x.isZero(): bool` – Convenience for checking if the number is zero. -- `x.isI32(): bool` – Check if the number fits in an `i32`. -- `x.abs(): BigInt` – Absolute value. -- `x.pow(exp: u8): BigInt` – Exponentiation. -- `bitOr(x: BigInt, y: BigInt): BigInt` – can be written as `x | y`. -- `bitAnd(x: BigInt, y: BigInt): BigInt` – can be written as `x & y`. -- `leftShift(x: BigInt, bits: u8): BigInt` – can be written as `x << y`. -- `rightShift(x: BigInt, bits: u8): BigInt` – can be written as `x >> y`. - -#### TypedMap - -```typescript -import { TypedMap } from '@graphprotocol/graph-ts' -``` - -`TypedMap` can be used to store key-value pairs. See [this example](https://github.com/graphprotocol/aragon-subgraph/blob/29dd38680c5e5104d9fdc2f90e740298c67e4a31/individual-dao-subgraph/mappings/constants.ts#L51). - -The `TypedMap` class has the following API: - -- `new TypedMap()` – creates an empty map with keys of type `K` and values of type `V` -- `map.set(key: K, value: V): void` – sets the value of `key` to `value` -- `map.getEntry(key: K): TypedMapEntry | null` – returns the key-value pair for a `key` or `null` if the `key` does not exist in the map -- `map.get(key: K): V | null` – returns the value for a `key` or `null` if the `key` does not exist in the map -- `map.isSet(key: K): bool` – returns `true` if the `key` exists in the map and `false` if it does not - -#### Bytes - -```typescript -import { Bytes } from '@graphprotocol/graph-ts' -``` - -`Bytes` is used to represent arbitrary-length arrays of bytes. This includes Ethereum values of type `bytes`, `bytes32`, etc. - -The `Bytes` class extends AssemblyScript's [Uint8Array](https://github.com/AssemblyScript/assemblyscript/blob/3b1852bc376ae799d9ebca888e6413afac7b572f/std/assembly/typedarray.ts#L64) and this supports all the `Uint8Array` functionality, plus the following new methods: - -_Construction_ - -- `fromHexString(hex: string) : Bytes` - Convert the string `hex` which must consist of an even number of hexadecimal digits to a `ByteArray`. The string `hex` can optionally start with `0x` -- `fromI32(i: i32) : Bytes` - Convert `i` to an array of bytes - -_Type conversions_ - -- `b.toHex()` – returns a hexadecimal string representing the bytes in the array -- `b.toString()` – converts the bytes in the array to a string of unicode characters -- `b.toBase58()` – turns an Ethereum Bytes value to base58 encoding (used for IPFS hashes) - -_Operators_ - -- `b.concat(other: Bytes) : Bytes` - - return new `Bytes` consisting of `this` directly followed by `other` -- `b.concatI32(other: i32) : ByteArray` - return new `Bytes` consisting of `this` directly follow by the byte representation of `other` - -#### Address - -```typescript -import { Address } from '@graphprotocol/graph-ts' -``` - -`Address` extends `Bytes` to represent Ethereum `address` values. - -It adds the following method on top of the `Bytes` API: - -- `Address.fromString(s: string): Address` – creates an `Address` from a hexadecimal string -- `Address.fromBytes(b: Bytes): Address` – create an `Address` from `b` which must be exactly 20 bytes long. Passing in a value with fewer or more bytes will result in an error - -### Store API - -```typescript -import { store } from '@graphprotocol/graph-ts' -``` - -The `store` API allows to load, save and remove entities from and to the Graph Node store. - -Entities written to the store map one-to-one to the `@entity` types defined in the subgraph's GraphQL schema. To make working with these entities convenient, the `graph codegen` command provided by the [Graph CLI](https://github.com/graphprotocol/graph-cli) generates entity classes, which are subclasses of the built-in `Entity` type, with property getters and setters for the fields in the schema as well as methods to load and save these entities. - -#### Creating entities - -The following is a common pattern for creating entities from Ethereum events. - -```typescript -// Import the Transfer event class generated from the ERC20 ABI -import { Transfer as TransferEvent } from '../generated/ERC20/ERC20' - -// Import the Transfer entity type generated from the GraphQL schema -import { Transfer } from '../generated/schema' - -// Transfer event handler -export function handleTransfer(event: TransferEvent): void { - // Create a Transfer entity, using the transaction hash as the entity ID - let id = event.transaction.hash - let transfer = new Transfer(id) - - // Set properties on the entity, using the event parameters - transfer.from = event.params.from - transfer.to = event.params.to - transfer.amount = event.params.amount - - // Save the entity to the store - transfer.save() -} -``` - -When a `Transfer` event is encountered while processing the chain, it is passed to the `handleTransfer` event handler using the generated `Transfer` type (aliased to `TransferEvent` here to avoid a naming conflict with the entity type). This type allows accessing data such as the event's parent transaction and its parameters. - -Each entity must have a unique ID to avoid collisions with other entities. It is fairly common for event parameters to include a unique identifier that can be used. Note: Using the transaction hash as the ID assumes that no other events in the same transaction create entities with this hash as the ID. - -#### Loading entities from the store - -If an entity already exists, it can be loaded from the store with the following: - -```typescript -let id = event.transaction.hash // or however the ID is constructed -let transfer = Transfer.load(id) -if (transfer == null) { - transfer = new Transfer(id) -} - -// Use the Transfer entity as before -``` - -As the entity may not exist in the store yet, the `load` method returns a value of type `Transfer | null`. It may thus be necessary to check for the `null` case before using the value. - -> **Note:** Loading entities is only necessary if the changes made in the mapping depend on the previous data of an entity. See the next section for the two ways of updating existing entities. - -#### Looking up entities created withing a block - -As of `graph-node` v0.31.0, `@graphprotocol/graph-ts` v0.30.0 and `@graphprotocol/graph-cli` v0.49.0 the `loadInBlock` method is available on all entity types. - -The store API facilitates the retrieval of entities that were created or updated in the current block. A typical situation for this is that one handler creates a Transaction from some on-chain event, and a later handler wants to access this transaction if it exists. In the case where the transaction does not exist, the subgraph will have to go to the database just to find out that the entity does not exist; if the subgraph author already knows that the entity must have been created in the same block, using loadInBlock avoids this database roundtrip. For some subgraphs, these missed lookups can contribute significantly to the indexing time. - -```typescript -let id = event.transaction.hash // or however the ID is constructed -let transfer = Transfer.loadInBlock(id) -if (transfer == null) { - transfer = new Transfer(id) -} - -// Use the Transfer entity as before -``` - -> Note: If there is no entity created in the given block, `loadInBlock` will return `null` even if there is an entity with the given ID in the store. - -#### Looking up derived entities - -As of `graph-node` v0.31.0, `@graphprotocol/graph-ts` v0.31.0 and `@graphprotocol/graph-cli` v0.51.0 the `loadRelated` method is available. - -This enables loading derived entity fields from within an event handler. For example, given the following schema: - -```graphql -type Token @entity { - id: ID! - holder: Holder! - color: String -} - -type Holder @entity { - id: ID! - tokens: [Token!]! @derivedFrom(field: "holder") -} -``` - -The following code will load the `Token` entity that the `Holder` entity was derived from: - -```typescript -let holder = Holder.load('test-id') -// Load the Token entities associated with a given holder -let tokens = holder.tokens.load() -``` - -#### Updating existing entities - -There are two ways to update an existing entity: - -1. Load the entity with e.g. `Transfer.load(id)`, set properties on the entity, then `.save()` it back to the store. -2. Simply create the entity with e.g. `new Transfer(id)`, set properties on the entity, then `.save()` it to the store. If the entity already exists, the changes are merged into it. - -Changing properties is straight forward in most cases, thanks to the generated property setters: - -```typescript -let transfer = new Transfer(id) -transfer.from = ... -transfer.to = ... -transfer.amount = ... -``` - -It is also possible to unset properties with one of the following two instructions: - -```typescript -transfer.from.unset() -transfer.from = null -``` - -This only works with optional properties, i.e. properties that are declared without a `!` in GraphQL. Two examples would be `owner: Bytes` or `amount: BigInt`. - -Updating array properties is a little more involved, as the getting an array from an entity creates a copy of that array. This means array properties have to be set again explicitly after changing the array. The following assumes `entity` has a `numbers: [BigInt!]!` field. - -```typescript -// This won't work -entity.numbers.push(BigInt.fromI32(1)) -entity.save() - -// This will work -let numbers = entity.numbers -numbers.push(BigInt.fromI32(1)) -entity.numbers = numbers -entity.save() -``` - -#### Removing entities from the store - -There is currently no way to remove an entity via the generated types. Instead, removing an entity requires passing the name of the entity type and the entity ID to `store.remove`: - -```typescript -import { store } from '@graphprotocol/graph-ts' -... -let id = event.transaction.hash -store.remove('Transfer', id) -``` - -### Ethereum API - -The Ethereum API provides access to smart contracts, public state variables, contract functions, events, transactions, blocks and the encoding/decoding Ethereum data. - -#### Support for Ethereum Types - -As with entities, `graph codegen` generates classes for all smart contracts and events used in a subgraph. For this, the contract ABIs need to be part of the data source in the subgraph manifest. Typically, the ABI files are stored in an `abis/` folder. - -With the generated classes, conversions between Ethereum types and the [built-in types](#built-in-types) take place behind the scenes so that subgraph authors do not have to worry about them. - -The following example illustrates this. Given a subgraph schema like - -```graphql -type Transfer @entity { - id: Bytes! - from: Bytes! - to: Bytes! - amount: BigInt! -} -``` - -and a `Transfer(address,address,uint256)` event signature on Ethereum, the `from`, `to` and `amount` values of type `address`, `address` and `uint256` are converted to `Address` and `BigInt`, allowing them to be passed on to the `Bytes!` and `BigInt!` properties of the `Transfer` entity: - -```typescript -let id = event.transaction.hash -let transfer = new Transfer(id) -transfer.from = event.params.from -transfer.to = event.params.to -transfer.amount = event.params.amount -transfer.save() -``` - -#### Events and Block/Transaction Data - -Ethereum events passed to event handlers, such as the `Transfer` event in the previous examples, not only provide access to the event parameters but also to their parent transaction and the block they are part of. The following data can be obtained from `event` instances (these classes are a part of the `ethereum` module in `graph-ts`): - -```typescript -class Event { - address: Address - logIndex: BigInt - transactionLogIndex: BigInt - logType: string | null - block: Block - transaction: Transaction - parameters: Array - receipt: TransactionReceipt | null -} - -class Block { - hash: Bytes - parentHash: Bytes - unclesHash: Bytes - author: Address - stateRoot: Bytes - transactionsRoot: Bytes - receiptsRoot: Bytes - number: BigInt - gasUsed: BigInt - gasLimit: BigInt - timestamp: BigInt - difficulty: BigInt - totalDifficulty: BigInt - size: BigInt | null - baseFeePerGas: BigInt | null -} - -class Transaction { - hash: Bytes - index: BigInt - from: Address - to: Address | null - value: BigInt - gasLimit: BigInt - gasPrice: BigInt - input: Bytes - nonce: BigInt -} - -class TransactionReceipt { - transactionHash: Bytes - transactionIndex: BigInt - blockHash: Bytes - blockNumber: BigInt - cumulativeGasUsed: BigInt - gasUsed: BigInt - contractAddress: Address - logs: Array - status: BigInt - root: Bytes - logsBloom: Bytes -} - -class Log { - address: Address - topics: Array - data: Bytes - blockHash: Bytes - blockNumber: Bytes - transactionHash: Bytes - transactionIndex: BigInt - logIndex: BigInt - transactionLogIndex: BigInt - logType: string - removed: bool | null -} -``` - -#### Access to Smart Contract State - -The code generated by `graph codegen` also includes classes for the smart contracts used in the subgraph. These can be used to access public state variables and call functions of the contract at the current block. - -A common pattern is to access the contract from which an event originates. This is achieved with the following code: - -```typescript -// Import the generated contract class and generated Transfer event class -import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract' -// Import the generated entity class -import { Transfer } from '../generated/schema' - -export function handleTransfer(event: TransferEvent) { - // Bind the contract to the address that emitted the event - let contract = ERC20Contract.bind(event.address) - - // Access state variables and functions by calling them - let erc20Symbol = contract.symbol() -} -``` - -`Transfer` is aliased to `TransferEvent` here to avoid a naming conflict with the entity type - -As long as the `ERC20Contract` on Ethereum has a public read-only function called `symbol`, it can be called with `.symbol()`. For public state variables a method with the same name is created automatically. - -Any other contract that is part of the subgraph can be imported from the generated code and can be bound to a valid address. - -#### Handling Reverted Calls - -If the read-only methods of your contract may revert, then you should handle that by calling the generated contract method prefixed with `try_`. For example, the Gravity contract exposes the `gravatarToOwner` method. This code would be able to handle a revert in that method: - -```typescript -let gravity = Gravity.bind(event.address) -let callResult = gravity.try_gravatarToOwner(gravatar) -if (callResult.reverted) { - log.info('getGravatar reverted', []) -} else { - let owner = callResult.value -} -``` - -Note that a Graph node connected to a Geth or Infura client may not detect all reverts, if you rely on this we recommend using a Graph node connected to a Parity client. - -#### Encoding/Decoding ABI - -Data can be encoded and decoded according to Ethereum's ABI encoding format using the `encode` and `decode` functions in the `ethereum` module. - -```typescript -import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts' - -let tupleArray: Array = [ - ethereum.Value.fromAddress(Address.fromString('0x0000000000000000000000000000000000000420')), - ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(62)), -] - -let tuple = tupleArray as ethereum.Tuple - -let encoded = ethereum.encode(ethereum.Value.fromTuple(tuple))! - -let decoded = ethereum.decode('(address,uint256)', encoded) -``` - -For more information: - -- [ABI Spec](https://docs.soliditylang.org/en/v0.7.4/abi-spec.html#types) -- Encoding/decoding [Rust library/CLI](https://github.com/rust-ethereum/ethabi) -- More [complex example](https://github.com/graphprotocol/graph-node/blob/6a7806cc465949ebb9e5b8269eeb763857797efc/tests/integration-tests/host-exports/src/mapping.ts#L72). - -### Logging API - -```typescript -import { log } from '@graphprotocol/graph-ts' -``` - -The `log` API allows subgraphs to log information to the Graph Node standard output as well as the Graph Explorer. Messages can be logged using different log levels. A basic format string syntax is provided to compose log messages from argument. - -The `log` API includes the following functions: - -- `log.debug(fmt: string, args: Array): void` - logs a debug message. -- `log.info(fmt: string, args: Array): void` - logs an informational message. -- `log.warning(fmt: string, args: Array): void` - logs a warning. -- `log.error(fmt: string, args: Array): void` - logs an error message. -- `log.critical(fmt: string, args: Array): void` – logs a critical message _and_ terminates the subgraph. - -The `log` API takes a format string and an array of string values. It then replaces placeholders with the string values from the array. The first `{}` placeholder gets replaced by the first value in the array, the second `{}` placeholder gets replaced by the second value and so on. - -```typescript -log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string']) -``` - -#### Logging one or more values - -##### Logging a single value - -In the example below, the string value "A" is passed into an array to become`['A']` before being logged: - -```typescript -let myValue = 'A' - -export function handleSomeEvent(event: SomeEvent): void { - // Displays : "My value is: A" - log.info('My value is: {}', [myValue]) -} -``` - -##### Logging a single entry from an existing array - -In the example below, only the first value of the argument array is logged, despite the array containing three values. - -```typescript -let myArray = ['A', 'B', 'C'] - -export function handleSomeEvent(event: SomeEvent): void { - // Displays : "My value is: A" (Even though three values are passed to `log.info`) - log.info('My value is: {}', myArray) -} -``` - -#### Logging multiple entries from an existing array - -Each entry in the arguments array requires its own placeholder `{}` in the log message string. The below example contains three placeholders `{}` in the log message. Because of this, all three values in `myArray` are logged. - -```typescript -let myArray = ['A', 'B', 'C'] - -export function handleSomeEvent(event: SomeEvent): void { - // Displays : "My first value is: A, second value is: B, third value is: C" - log.info('My first value is: {}, second value is: {}, third value is: {}', myArray) -} -``` - -##### Logging a specific entry from an existing array - -To display a specific value in the array, the indexed value must be provided. - -```typescript -export function handleSomeEvent(event: SomeEvent): void { - // Displays : "My third value is C" - log.info('My third value is: {}', [myArray[2]]) -} -``` - -##### Logging event information - -The example below logs the block number, block hash and transaction hash from an event: - -```typescript -import { log } from '@graphprotocol/graph-ts' - -export function handleSomeEvent(event: SomeEvent): void { - log.debug('Block number: {}, block hash: {}, transaction hash: {}', [ - event.block.number.toString(), // "47596000" - event.block.hash.toHexString(), // "0x..." - event.transaction.hash.toHexString(), // "0x..." - ]) -} -``` - -### IPFS API - -```typescript -import { ipfs } from '@graphprotocol/graph-ts' -``` - -Smart contracts occasionally anchor IPFS files on chain. This allows mappings to obtain the IPFS hashes from the contract and read the corresponding files from IPFS. The file data will be returned as `Bytes`, which usually requires further processing, e.g. with the `json` API documented later on this page. - -Given an IPFS hash or path, reading a file from IPFS is done as follows: - -```typescript -// Put this inside an event handler in the mapping -let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D' -let data = ipfs.cat(hash) - -// Paths like `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile` -// that include files in directories are also supported -let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile' -let data = ipfs.cat(path) -``` - -**Note:** `ipfs.cat` is not deterministic at the moment. If the file cannot be retrieved over the IPFS network before the request times out, it will return `null`. Due to this, it's always worth checking the result for `null`. - -It is also possible to process larger files in a streaming fashion with `ipfs.map`. The function expects the hash or path for an IPFS file, the name of a callback, and flags to modify its behavior: - -```typescript -import { JSONValue, Value } from '@graphprotocol/graph-ts' - -export function processItem(value: JSONValue, userData: Value): void { - // See the JSONValue documentation for details on dealing - // with JSON values - let obj = value.toObject() - let id = obj.get('id') - let title = obj.get('title') - - if (!id || !title) { - return - } - - // Callbacks can also created entities - let newItem = new Item(id) - newItem.title = title.toString() - newitem.parent = userData.toString() // Set parent to "parentId" - newitem.save() -} - -// Put this inside an event handler in the mapping -ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json']) - -// Alternatively, use `ipfs.mapJSON` -ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId')) -``` - -The only flag currently supported is `json`, which must be passed to `ipfs.map`. With the `json` flag, the IPFS file must consist of a series of JSON values, one value per line. The call to `ipfs.map` will read each line in the file, deserialize it into a `JSONValue` and call the callback for each of them. The callback can then use entity operations to store data from the `JSONValue`. Entity changes are stored only when the handler that called `ipfs.map` finishes successfully; in the meantime, they are kept in memory, and the size of the file that `ipfs.map` can process is therefore limited. - -On success, `ipfs.map` returns `void`. If any invocation of the callback causes an error, the handler that invoked `ipfs.map` is aborted, and the subgraph is marked as failed. - -### Crypto API - -```typescript -import { crypto } from '@graphprotocol/graph-ts' -``` - -The `crypto` API makes a cryptographic functions available for use in mappings. Right now, there is only one: - -- `crypto.keccak256(input: ByteArray): ByteArray` - -### JSON API - -```typescript -import { json, JSONValueKind } from '@graphprotocol/graph-ts' -``` - -JSON data can be parsed using the `json` API: - -- `json.fromBytes(data: Bytes): JSONValue` – parses JSON data from a `Bytes` array interpreted as a valid UTF-8 sequence -- `json.try_fromBytes(data: Bytes): Result` – safe version of `json.fromBytes`, it returns an error variant if the parsing failed -- `json.fromString(data: string): JSONValue` – parses JSON data from a valid UTF-8 `String` -- `json.try_fromString(data: string): Result` – safe version of `json.fromString`, it returns an error variant if the parsing failed - -The `JSONValue` class provides a way to pull values out of an arbitrary JSON document. Since JSON values can be booleans, numbers, arrays and more, `JSONValue` comes with a `kind` property to check the type of a value: - -```typescript -let value = json.fromBytes(...) -if (value.kind == JSONValueKind.BOOL) { - ... -} -``` - -In addition, there is a method to check if the value is `null`: - -- `value.isNull(): boolean` - -When the type of a value is certain, it can be converted to a [built-in type](#built-in-types) using one of the following methods: - -- `value.toBool(): boolean` -- `value.toI64(): i64` -- `value.toF64(): f64` -- `value.toBigInt(): BigInt` -- `value.toString(): string` -- `value.toArray(): Array` - (and then convert `JSONValue` with one of the 5 methods above) - -### Type Conversions Reference - -| Source(s) | Destination | Conversion function | -| -------------------- | -------------------- | ---------------------------- | -| Address | Bytes | none | -| Address | String | s.toHexString() | -| BigDecimal | String | s.toString() | -| BigInt | BigDecimal | s.toBigDecimal() | -| BigInt | String (hexadecimal) | s.toHexString() or s.toHex() | -| BigInt | String (unicode) | s.toString() | -| BigInt | i32 | s.toI32() | -| Boolean | Boolean | none | -| Bytes (signed) | BigInt | BigInt.fromSignedBytes(s) | -| Bytes (unsigned) | BigInt | BigInt.fromUnsignedBytes(s) | -| Bytes | String (hexadecimal) | s.toHexString() or s.toHex() | -| Bytes | String (unicode) | s.toString() | -| Bytes | String (base58) | s.toBase58() | -| Bytes | i32 | s.toI32() | -| Bytes | u32 | s.toU32() | -| Bytes | JSON | json.fromBytes(s) | -| int8 | i32 | none | -| int32 | i32 | none | -| int32 | BigInt | BigInt.fromI32(s) | -| uint24 | i32 | none | -| int64 - int256 | BigInt | none | -| uint32 - uint256 | BigInt | none | -| JSON | boolean | s.toBool() | -| JSON | i64 | s.toI64() | -| JSON | u64 | s.toU64() | -| JSON | f64 | s.toF64() | -| JSON | BigInt | s.toBigInt() | -| JSON | string | s.toString() | -| JSON | Array | s.toArray() | -| JSON | Object | s.toObject() | -| String | Address | Address.fromString(s) | -| Bytes | Address | Address.fromBytes(s) | -| String | BigInt | BigInt.fromString(s) | -| String | BigDecimal | BigDecimal.fromString(s) | -| String (hexadecimal) | Bytes | ByteArray.fromHexString(s) | -| String (UTF-8) | Bytes | ByteArray.fromUTF8(s) | - -### Data Source Metadata - -You can inspect the contract address, network and context of the data source that invoked the handler through the `dataSource` namespace: - -- `dataSource.address(): Address` -- `dataSource.network(): string` -- `dataSource.context(): DataSourceContext` - -### Entity and DataSourceContext - -The base `Entity` class and the child `DataSourceContext` class have helpers to dynamically set and get fields: - -- `setString(key: string, value: string): void` -- `setI32(key: string, value: i32): void` -- `setBigInt(key: string, value: BigInt): void` -- `setBytes(key: string, value: Bytes): void` -- `setBoolean(key: string, value: bool): void` -- `setBigDecimal(key, value: BigDecimal): void` -- `getString(key: string): string` -- `getI32(key: string): i32` -- `getBigInt(key: string): BigInt` -- `getBytes(key: string): Bytes` -- `getBoolean(key: string): boolean` -- `getBigDecimal(key: string): BigDecimal` - -### DataSourceContext in Manifest - -The `context` section within `dataSources` allows you to define key-value pairs that are accessible within your subgraph mappings. The available types are `Bool`, `String`, `Int`, `Int8`, `BigDecimal`, `Bytes`, `List`, and `BigInt`. - -Here is a YAML example illustrating the usage of various types in the `context` section: - -```yaml -dataSources: - - kind: ethereum/contract - name: ContractName - network: mainnet - context: - bool_example: - type: Bool - data: true - string_example: - type: String - data: 'hello' - int_example: - type: Int - data: 42 - int8_example: - type: Int8 - data: 127 - big_decimal_example: - type: BigDecimal - data: '10.99' - bytes_example: - type: Bytes - data: '0x68656c6c6f' - list_example: - type: List - data: - - type: Int - data: 1 - - type: Int - data: 2 - - type: Int - data: 3 - big_int_example: - type: BigInt - data: '1000000000000000000000000' -``` - -- `Bool`: Specifies a Boolean value (`true` or `false`). -- `String`: Specifies a String value. -- `Int`: Specifies a 32-bit integer. -- `Int8`: Specifies an 8-bit integer. -- `BigDecimal`: Specifies a decimal number. Must be quoted. -- `Bytes`: Specifies a hexadecimal string. -- `List`: Specifies a list of items. Each item needs to specify its type and data. -- `BigInt`: Specifies a large integer value. Must be quoted due to its large size. - -This context is then accessible in your subgraph mapping files, enabling more dynamic and configurable subgraphs. diff --git a/website/pages/ha/developing/graph-ts/common-issues.mdx b/website/pages/ha/developing/graph-ts/common-issues.mdx deleted file mode 100644 index 5b99efa8f493..000000000000 --- a/website/pages/ha/developing/graph-ts/common-issues.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Common AssemblyScript Issues ---- - -There are certain [AssemblyScript](https://github.com/AssemblyScript/assemblyscript) issues that are common to run into during subgraph development. They range in debug difficulty, however, being aware of them may help. The following is a non-exhaustive list of these issues: - -- `Private` class variables are not enforced in [AssembyScript](https://www.assemblyscript.org/status.html#language-features). There is no way to protect class variables from being directly changed from the class object. -- Scope is not inherited into [closure functions](https://www.assemblyscript.org/status.html#on-closures), i.e. variables declared outside of closure functions cannot be used. Explanation in [Developer Highlights #3](https://www.youtube.com/watch?v=1-8AW-lVfrA&t=3243s). diff --git a/website/pages/ha/developing/substreams-powered-subgraphs-faq.mdx b/website/pages/ha/developing/substreams-powered-subgraphs-faq.mdx deleted file mode 100644 index 02592fd21457..000000000000 --- a/website/pages/ha/developing/substreams-powered-subgraphs-faq.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Substreams-powered subgraphs FAQ ---- - -## What are Substreams? - -Developed by [StreamingFast](https://www.streamingfast.io/), Substreams is an exceptionally powerful processing engine capable of consuming rich streams of blockchain data. Substreams allow you to refine and shape blockchain data for fast and seamless digestion by end-user applications. More specifically, Substreams is a blockchain-agnostic, parallelized, and streaming-first engine, serving as a blockchain data transformation layer. Powered by the [Firehose](https://firehose.streamingfast.io/), it ​​enables developers to write Rust modules, build upon community modules, provide extremely high-performance indexing, and [sink](https://substreams.streamingfast.io/developers-guide/sink-targets) their data anywhere. - -Go to the [Substreams Documentation](/substreams) to learn more about Substreams. - -## What are Substreams-powered subgraphs? - -[Substreams-powered subgraphs](/cookbook/substreams-powered-subgraphs/) combine the power of Substreams with the queryability of subgraphs. When publishing a Substreams-powered Subgraph, the data produced by the Substreams transformations, can [output entity changes](https://github.com/streamingfast/substreams-sink-entity-changes/blob/develop/substreams-entity-change/src/tables.rs), which are compatible with subgraph entities. - -If you are already familiar with subgraph development, then note that Substreams-powered subgraphs can then be queried, just as if it had been produced by the AssemblyScript transformation layer, with all the Subgraph benefits, like providing a dynamic and flexible GraphQL API. - -## How are Substreams-powered subgraphs different from subgraphs? - -Subgraphs are made up of datasources which specify on-chain events, and how those events should be transformed via handlers written in Assemblyscript. These events are processed sequentially, based on the order in which events happen on-chain. - -By contrast, substreams-powered subgraphs have a single datasource which references a substreams package, which is processed by the Graph Node. Substreams have access to additional granular on-chain data compared to conventional subgraphs, and can also benefit from massively parallelised processing, which can mean much faster processing times. - -## What are the benefits of using Substreams-powered subgraphs? - -Substreams-powered subgraphs combine all the benefits of Substreams with the queryability of subgraphs. They bring greater composability and high-performance indexing to The Graph. They also enable new data use cases; for example, once you've built your Substreams-powered Subgraph, you can reuse your [Substreams modules](https://substreams.streamingfast.io/developers-guide/modules) to output to different [sinks](https://substreams.streamingfast.io/developers-guide/sink-targets) such as PostgreSQL, MongoDB, and Kafka. - -## What are the benefits of Substreams? - -There are many benefits to using Substreams, including: - -- Composable: You can stack Substreams modules like LEGO blocks, and build upon community modules, further refining public data. - -- High-performance indexing: Orders of magnitude faster indexing through large-scale clusters of parallel operations (think BigQuery). - -- Sink anywhere: Sink your data to anywhere you want: PostgreSQL, MongoDB, Kafka, subgraphs, flat files, Google Sheets. - -- Programmable: Use code to customize extraction, do transformation-time aggregations, and model your output for multiple sinks. - -- Access to additional data which is not available as part of the JSON RPC - -- All the benefits of the Firehose. - -## What is the Firehose? - -Developed by [StreamingFast](https://www.streamingfast.io/), the Firehose is a blockchain data extraction layer designed from scratch to process the full history of blockchains at speeds that were previously unseen. Providing a files-based and streaming-first approach, it is a core component of StreamingFast's suite of open-source technologies and the foundation for Substreams. - -Go to the [documentation](https://firehose.streamingfast.io/) to learn more about the Firehose. - -## What are the benefits of the Firehose? - -There are many benefits to using Firehose, including: - -- Lowest latency & no polling: In a streaming-first fashion, the Firehose nodes are designed to race to push out the block data first. - -- Prevents downtimes: Designed from the ground up for High Availability. - -- Never miss a beat: The Firehose stream cursor is designed to handle forks and to continue where you left off in any condition. - -- Richest data model:  Best data model that includes the balance changes, the full call tree, internal transactions, logs, storage changes, gas costs, and more. - -- Leverages flat files: Blockchain data is extracted into flat files, the cheapest and most optimized computing resource available. - -## Where can developers access more information about Substreams-powered subgraphs and Substreams? - -The [Substreams documentation](/substreams) will teach you how to build Substreams modules. - -The [Substreams-powered subgraphs documentation](/cookbook/substreams-powered-subgraphs/) will show you how to package them for deployment on The Graph. - -## What is the role of Rust modules in Substreams? - -Rust modules are the equivalent of the AssemblyScript mappers in subgraphs. They are compiled to WASM in a similar way, but the programming model allows for parallel execution. They define the sort of transformations and aggregations you want to apply to the raw blockchain data. - -See [modules documentation](https://substreams.streamingfast.io/developers-guide/modules) for details. - -## What makes Substreams composable? - -When using Substreams, the composition happens at the transformation layer enabling cached modules to be re-used. - -As an example, Alice can build a DEX price module, Bob can use it to build a volume aggregator for some tokens of his interest, and Lisa can combine four individual DEX price modules to create a price oracle. A single Substreams request will package all of these individual's modules, link them together, to offer a much more refined stream of data. That stream can then be used to populate a subgraph, and be queried by consumers. - -## How can you build and deploy a Substreams-powered Subgraph? - -After [defining](/cookbook/substreams-powered-subgraphs/) a Substreams-powered Subgraph, you can use the Graph CLI to deploy it in [Subgraph Studio](https://thegraph.com/studio/). - -## Where can I find examples of Substreams and Substreams-powered subgraphs? - -You can visit [this Github repo](https://github.com/pinax-network/awesome-substreams) to find examples of Substreams and Substreams-powered subgraphs. - -## What do Substreams and Substreams-powered subgraphs mean for The Graph Network? - -The integration promises many benefits, including extremely high-performance indexing and greater composability by leveraging community modules and building on them. diff --git a/website/pages/ha/developing/supported-networks.json b/website/pages/ha/developing/supported-networks.json deleted file mode 100644 index 5d06eb1bf08d..000000000000 --- a/website/pages/ha/developing/supported-networks.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "network": "Network", - "cliName": "CLI Name", - "chainId": "Chain ID", - "hostedService": "Hosted Service", - "subgraphStudio": "Subgraph Studio", - "decentralizedNetwork": "Decentralized Network" -} diff --git a/website/pages/ha/developing/supported-networks.mdx b/website/pages/ha/developing/supported-networks.mdx deleted file mode 100644 index 46d2f078a352..000000000000 --- a/website/pages/ha/developing/supported-networks.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Supported Networks ---- - -import { getStaticPropsForSupportedNetworks } from '@/src/buildGetStaticProps' -import { SupportedNetworksTable } from '@/src/supportedNetworks' - -export const getStaticProps = getStaticPropsForSupportedNetworks(__filename) - - - -\* Preliminary network support via the [upgrade Indexer](https://thegraph.com/blog/upgrade-indexer/) -⁠ Supports Substreams - -The hosted service relies on the stability and reliability of the underlying technologies, namely the provided JSON RPC endpoints. - -Ropsten, Rinkeby and Kovan are being deprecated. Read more on the [Ethereum Foundation Blog](https://blog.ethereum.org/2022/06/21/testnet-deprecation). As of Feb 25th 2023, Ropsten, Rinkeby and Kovan are no longer supported by the hosted service. Sepolia will be maintained by client developers post-merge, and is also supported by the hosted service. Developers who currently use Ropsten, Rinkeby or Kovan as their staging/testing environment are encouraged to migrate to Sepolia. - -Subgraphs indexing Gnosis Chain can now be deployed with the `gnosis` network identifier. `xdai` is still supported for existing hosted service subgraphs. - -For a full list of which features are supported on the decentralized network, see [this page](https://github.com/graphprotocol/indexer/blob/main/docs/feature-support-matrix.md). - -Substreams-powered subgraphs indexing `mainnet` Ethereum are supported on the Subgraph Studio and decentralized network. - -## Graph Node - -If your preferred network isn't supported on The Graph's decentralized network, you can run your own [Graph Node](https://github.com/graphprotocol/graph-node) to index any EVM-compatible network. Make sure that the [version](https://github.com/graphprotocol/graph-node/releases) you are using supports the network and you have the needed configuration. - -Graph Node can also index other protocols, via a Firehose integration. Firehose integrations have been created for NEAR, Arweave and Cosmos-based networks. diff --git a/website/pages/ha/developing/unit-testing-framework.mdx b/website/pages/ha/developing/unit-testing-framework.mdx deleted file mode 100644 index 850434eb8c98..000000000000 --- a/website/pages/ha/developing/unit-testing-framework.mdx +++ /dev/null @@ -1,1099 +0,0 @@ ---- -title: Unit Testing Framework ---- - -Matchstick is a unit testing framework, developed by [LimeChain](https://limechain.tech/), that enables subgraph developers to test their mapping logic in a sandboxed environment and deploy their subgraphs with confidence! - -## Getting Started - -### Install dependencies - -In order to use the test helper methods and run the tests, you will need to install the following dependencies: - -```sh -yarn add --dev matchstick-as -``` - -❗ `graph-node` depends on PostgreSQL, so if you don't already have it, you will need to install it. We highly advise using the commands below as adding it in any other way may cause unexpected errors! - -#### MacOS - -Postgres installation command: - -```sh -brew install postgresql -``` - -Create a symlink to the latest libpq.5.lib _You may need to create this dir first_ `/usr/local/opt/postgresql/lib/` - -```sh -ln -sf /usr/local/opt/postgresql@14/lib/postgresql@14/libpq.5.dylib /usr/local/opt/postgresql/lib/libpq.5.dylib -``` - -#### Linux - -Postgres installation command (depends on your distro): - -```sh -sudo apt install postgresql -``` - -### WSL (Windows Subsystem for Linux) - -You can use Matchstick on WSL both using the Docker approach and the binary approach. As WSL can be a bit tricky, here's a few tips in case you encounter issues like - -``` -static BYTES = Symbol("Bytes") SyntaxError: Unexpected token = -``` - -or - -``` -/node_modules/gluegun/build/index.js:13 throw up; -``` - -Please make sure you're on a newer version of Node.js graph-cli doesn't support **v10.19.0** anymore, and that is still the default version for new Ubuntu images on WSL. For instance Matchstick is confirmed to be working on WSL with **v18.1.0**, you can switch to it either via **nvm** or if you update your global Node.js. Don't forget to delete `node_modules` and to run `npm install` again after updating you nodejs! Then, make sure you have **libpq** installed, you can do that by running - -``` -sudo apt-get install libpq-dev -``` - -And finally, do not use `graph test` (which uses your global installation of graph-cli and for some reason that looks like it's broken on WSL currently), instead use `yarn test` or `npm run test` (that will use the local, project-level instance of graph-cli, which works like a charm). For that you would of course need to have a `"test"` script in your `package.json` file which can be something as simple as - -```json -{ - "name": "demo-subgraph", - "version": "0.1.0", - "scripts": { - "test": "graph test", - ... - }, - "dependencies": { - "@graphprotocol/graph-cli": "^0.30.0", - "@graphprotocol/graph-ts": "^0.27.0", - "matchstick-as": "^0.5.0" - } -} -``` - -### Usage - -To use **Matchstick** in your subgraph project just open up a terminal, navigate to the root folder of your project and simply run `graph test [options] ` - it downloads the latest **Matchstick** binary and runs the specified test or all tests in a test folder (or all existing tests if no datasource flag is specified). - -### CLI options - -This will run all tests in the test folder: - -```sh -graph test -``` - -This will run a test named gravity.test.ts and/or all test inside of a folder named gravity: - -```sh -graph test gravity -``` - -This will run only that specific test file: - -```sh -graph test path/to/file.test.ts -``` - -**Options:** - -```sh --c, --coverage Run the tests in coverage mode --d, --docker Run the tests in a docker container (Note: Please execute from the root folder of the subgraph) --f, --force Binary: Redownloads the binary. Docker: Redownloads the Dockerfile and rebuilds the docker image. --h, --help Show usage information --l, --logs Logs to the console information about the OS, CPU model and download url (debugging purposes) --r, --recompile Forces tests to be recompiled --v, --version Choose the version of the rust binary that you want to be downloaded/used -``` - -### Docker - -From `graph-cli 0.25.2`, the `graph test` command supports running `matchstick` in a docker container with the `-d` flag. The docker implementation uses [bind mount](https://docs.docker.com/storage/bind-mounts/) so it does not have to rebuild the docker image every time the `graph test -d` command is executed. Alternatively you can follow the instructions from the [matchstick](https://github.com/LimeChain/matchstick#docker-) repository to run docker manually. - -❗ If you have previously ran `graph test` you may encounter the following error during docker build: - -```sh - error from sender: failed to xattr node_modules/binary-install-raw/bin/binary-: permission denied -``` - -In this case create a `.dockerignore` in the root folder and add `node_modules/binary-install-raw/bin` - -### Configuration - -Matchstick can be configured to use a custom tests, libs and manifest path via `matchstick.yaml` config file: - -```yaml -testsFolder: path/to/tests -libsFolder: path/to/libs -manifestPath: path/to/subgraph.yaml -``` - -### Demo subgraph - -You can try out and play around with the examples from this guide by cloning the [Demo Subgraph repo](https://github.com/LimeChain/demo-subgraph) - -### Video tutorials - -Also you can check out the video series on ["How to use Matchstick to write unit tests for your subgraphs"](https://www.youtube.com/playlist?list=PLTqyKgxaGF3SNakGQwczpSGVjS_xvOv3h) - -## Tests structure (>=0.5.0) - -_**IMPORTANT: Requires matchstick-as >=0.5.0**_ - -### describe() - -`describe(name: String , () => {})` - Defines a test group. - -**_Notes:_** - -- _Describes are not mandatory. You can still use test() the old way, outside of the describe() blocks_ - -Example: - -```typescript -import { describe, test } from "matchstick-as/assembly/index" -import { handleNewGravatar } from "../../src/gravity" - -describe("handleNewGravatar()", () => { - test("Should create a new Gravatar entity", () => { - ... - }) -}) -``` - -Nested `describe()` example: - -```typescript -import { describe, test } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar } from "../../src/gravity" - -describe("handleUpdatedGravatar()", () => { - describe("When entity exists", () => { - test("updates the entity", () => { - ... - }) - }) - - describe("When entity does not exists", () => { - test("it creates a new entity", () => { - ... - }) - }) -}) -``` - ---- - -### test() - -`test(name: String, () =>, should_fail: bool)` - Defines a test case. You can use test() inside of describe() blocks or independently. - -Example: - -```typescript -import { describe, test } from "matchstick-as/assembly/index" -import { handleNewGravatar } from "../../src/gravity" - -describe("handleNewGravatar()", () => { - test("Should create a new Entity", () => { - ... - }) -}) -``` - -or - -```typescript -test("handleNewGravatar() should create a new entity", () => { - ... -}) - - -``` - ---- - -### beforeAll() - -Runs a code block before any of the tests in the file. If `beforeAll` is declared inside of a `describe` block, it runs at the beginning of that `describe` block. - -Examples: - -Code inside `beforeAll` will execute once before _all_ tests in the file. - -```typescript -import { describe, test, beforeAll } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" -import { Gravatar } from "../../generated/schema" - -beforeAll(() => { - let gravatar = new Gravatar("0x0") - gravatar.displayName = “First Gravatar” - gravatar.save() - ... -}) - -describe("When the entity does not exist", () => { - test("it should create a new Gravatar with id 0x1", () => { - ... - }) -}) - -describe("When entity already exists", () => { - test("it should update the Gravatar with id 0x0", () => { - ... - }) -}) -``` - -Code inside `beforeAll` will execute once before all tests in the first describe block - -```typescript -import { describe, test, beforeAll } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" -import { Gravatar } from "../../generated/schema" - -describe("handleUpdatedGravatar()", () => { - beforeAll(() => { - let gravatar = new Gravatar("0x0") - gravatar.displayName = “First Gravatar” - gravatar.save() - ... - }) - - test("updates Gravatar with id 0x0", () => { - ... - }) - - test("creates new Gravatar with id 0x1", () => { - ... - }) -}) -``` - ---- - -### afterAll() - -Runs a code block after all of the tests in the file. If `afterAll` is declared inside of a `describe` block, it runs at the end of that `describe` block. - -Example: - -Code inside `afterAll` will execute once after _all_ tests in the file. - -```typescript -import { describe, test, afterAll } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" -import { store } from "@graphprotocol/graph-ts" - -afterAll(() => { - store.remove("Gravatar", "0x0") - ... -}) - -describe("handleNewGravatar, () => { - test("creates Gravatar with id 0x0", () => { - ... - }) -}) - -describe("handleUpdatedGravatar", () => { - test("updates Gravatar with id 0x0", () => { - ... - }) -}) -``` - -Code inside `afterAll` will execute once after all tests in the first describe block - -```typescript -import { describe, test, afterAll, clearStore } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" - -describe("handleNewGravatar", () => { - afterAll(() => { - store.remove("Gravatar", "0x1") - ... - }) - - test("It creates a new entity with Id 0x0", () => { - ... - }) - - test("It creates a new entity with Id 0x1", () => { - ... - }) -}) - -describe("handleUpdatedGravatar", () => { - test("updates Gravatar with id 0x0", () => { - ... - }) -}) -``` - ---- - -### beforeEach() - -Runs a code block before every test. If `beforeEach` is declared inside of a `describe` block, it runs before each test in that `describe` block. - -Examples: Code inside `beforeEach` will execute before each tests. - -```typescript -import { describe, test, beforeEach, clearStore } from "matchstick-as/assembly/index" -import { handleNewGravatars } from "./utils" - -beforeEach(() => { - clearStore() // <-- clear the store before each test in the file -}) - -describe("handleNewGravatars, () => { - test("A test that requires a clean store", () => { - ... - }) - - test("Second that requires a clean store", () => { - ... - }) -}) - - ... -``` - -Code inside `beforeEach` will execute only before each test in the that describe - -```typescript -import { describe, test, beforeEach } from 'matchstick-as/assembly/index' -import { handleUpdatedGravatar, handleNewGravatar } from '../../src/gravity' - -describe('handleUpdatedGravatars', () => { - beforeEach(() => { - let gravatar = new Gravatar('0x0') - gravatar.displayName = 'First Gravatar' - gravatar.imageUrl = '' - gravatar.save() - }) - - test('Upates the displayName', () => { - assert.fieldEquals('Gravatar', '0x0', 'displayName', 'First Gravatar') - - // code that should update the displayName to 1st Gravatar - - assert.fieldEquals('Gravatar', '0x0', 'displayName', '1st Gravatar') - store.remove('Gravatar', '0x0') - }) - - test('Updates the imageUrl', () => { - assert.fieldEquals('Gravatar', '0x0', 'imageUrl', '') - - // code that should changes the imageUrl to https://www.gravatar.com/avatar/0x0 - - assert.fieldEquals('Gravatar', '0x0', 'imageUrl', 'https://www.gravatar.com/avatar/0x0') - store.remove('Gravatar', '0x0') - }) -}) -``` - ---- - -### afterEach() - -Runs a code block after every test. If `afterEach` is declared inside of a `describe` block, it runs after each test in that `describe` block. - -Examples: - -Code inside `afterEach` will execute after every test. - -```typescript -import { describe, test, beforeEach, afterEach } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" - -beforeEach(() => { - let gravatar = new Gravatar("0x0") - gravatar.displayName = “First Gravatar” - gravatar.save() -}) - -afterEach(() => { - store.remove("Gravatar", "0x0") -}) - -describe("handleNewGravatar", () => { - ... -}) - -describe("handleUpdatedGravatar", () => { - test("Upates the displayName", () => { - assert.fieldEquals("Gravatar", "0x0", "displayName", "First Gravatar") - - // code that should update the displayName to 1st Gravatar - - assert.fieldEquals("Gravatar", "0x0", "displayName", "1st Gravatar") - }) - - test("Updates the imageUrl", () => { - assert.fieldEquals("Gravatar", "0x0", "imageUrl", "") - - // code that should changes the imageUrl to https://www.gravatar.com/avatar/0x0 - - assert.fieldEquals("Gravatar", "0x0", "imageUrl", "https://www.gravatar.com/avatar/0x0") - }) -}) -``` - -Code inside `afterEach` will execute after each test in that describe - -```typescript -import { describe, test, beforeEach, afterEach } from "matchstick-as/assembly/index" -import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity" - -describe("handleNewGravatar", () => { - ... -}) - -describe("handleUpdatedGravatar", () => { - beforeEach(() => { - let gravatar = new Gravatar("0x0") - gravatar.displayName = "First Gravatar" - gravatar.imageUrl = "" - gravatar.save() - }) - - afterEach(() => { - store.remove("Gravatar", "0x0") - }) - - test("Upates the displayName", () => { - assert.fieldEquals("Gravatar", "0x0", "displayName", "First Gravatar") - - // code that should update the displayName to 1st Gravatar - - assert.fieldEquals("Gravatar", "0x0", "displayName", "1st Gravatar") - }) - - test("Updates the imageUrl", () => { - assert.fieldEquals("Gravatar", "0x0", "imageUrl", "") - - // code that should changes the imageUrl to https://www.gravatar.com/avatar/0x0 - - assert.fieldEquals("Gravatar", "0x0", "imageUrl", "https://www.gravatar.com/avatar/0x0") - }) -}) -``` - -## Asserts - -```typescript -fieldEquals(entityType: string, id: string, fieldName: string, expectedVal: string) - -equals(expected: ethereum.Value, actual: ethereum.Value) - -notInStore(entityType: string, id: string) - -addressEquals(address1: Address, address2: Address) - -bytesEquals(bytes1: Bytes, bytes2: Bytes) - -i32Equals(number1: i32, number2: i32) - -bigIntEquals(bigInt1: BigInt, bigInt2: BigInt) - -booleanEquals(bool1: boolean, bool2: boolean) - -stringEquals(string1: string, string2: string) - -arrayEquals(array1: Array, array2: Array) - -tupleEquals(tuple1: ethereum.Tuple, tuple2: ethereum.Tuple) - -assertTrue(value: boolean) - -assertNull(value: T) - -assertNotNull(value: T) - -entityCount(entityType: string, expectedCount: i32) -``` - -## Write a Unit Test - -Let's see how a simple unit test would look like using the Gravatar examples in the [Demo Subgraph](https://github.com/LimeChain/demo-subgraph/blob/main/src/gravity.ts). - -Assuming we have the following handler function (along with two helper functions to make our life easier): - -```typescript -export function handleNewGravatar(event: NewGravatar): void { - let gravatar = new Gravatar(event.params.id.toHex()) - gravatar.owner = event.params.owner - gravatar.displayName = event.params.displayName - gravatar.imageUrl = event.params.imageUrl - gravatar.save() -} - -export function handleNewGravatars(events: NewGravatar[]): void { - events.forEach((event) => { - handleNewGravatar(event) - }) -} - -export function createNewGravatarEvent( - id: i32, - ownerAddress: string, - displayName: string, - imageUrl: string, -): NewGravatar { - let mockEvent = newMockEvent() - let newGravatarEvent = new NewGravatar( - mockEvent.address, - mockEvent.logIndex, - mockEvent.transactionLogIndex, - mockEvent.logType, - mockEvent.block, - mockEvent.transaction, - mockEvent.parameters, - ) - newGravatarEvent.parameters = new Array() - let idParam = new ethereum.EventParam('id', ethereum.Value.fromI32(id)) - let addressParam = new ethereum.EventParam( - 'ownderAddress', - ethereum.Value.fromAddress(Address.fromString(ownerAddress)), - ) - let displayNameParam = new ethereum.EventParam('displayName', ethereum.Value.fromString(displayName)) - let imageUrlParam = new ethereum.EventParam('imageUrl', ethereum.Value.fromString(imageUrl)) - - newGravatarEvent.parameters.push(idParam) - newGravatarEvent.parameters.push(addressParam) - newGravatarEvent.parameters.push(displayNameParam) - newGravatarEvent.parameters.push(imageUrlParam) - - return newGravatarEvent -} -``` - -We first have to create a test file in our project. This is an example of how that might look like: - -```typescript -import { clearStore, test, assert } from 'matchstick-as/assembly/index' -import { Gravatar } from '../../generated/schema' -import { NewGravatar } from '../../generated/Gravity/Gravity' -import { createNewGravatarEvent, handleNewGravatars } from '../mappings/gravity' - -test('Can call mappings with custom events', () => { - // Create a test entity and save it in the store as initial state (optional) - let gravatar = new Gravatar('gravatarId0') - gravatar.save() - - // Create mock events - let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac') - let anotherGravatarEvent = createNewGravatarEvent(3546, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac') - - // Call mapping functions passing the events we just created - handleNewGravatars([newGravatarEvent, anotherGravatarEvent]) - - // Assert the state of the store - assert.fieldEquals('Gravatar', 'gravatarId0', 'id', 'gravatarId0') - assert.fieldEquals('Gravatar', '12345', 'owner', '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7') - assert.fieldEquals('Gravatar', '3546', 'displayName', 'cap') - - // Clear the store in order to start the next test off on a clean slate - clearStore() -}) - -test('Next test', () => { - //... -}) -``` - -That's a lot to unpack! First off, an important thing to notice is that we're importing things from `matchstick-as`, our AssemblyScript helper library (distributed as an npm module). You can find the repository [here](https://github.com/LimeChain/matchstick-as). `matchstick-as` provides us with useful testing methods and also defines the `test()` function which we will use to build our test blocks. The rest of it is pretty straightforward - here's what happens: - -- We're setting up our initial state and adding one custom Gravatar entity; -- We define two `NewGravatar` event objects along with their data, using the `createNewGravatarEvent()` function; -- We're calling out handler methods for those events - `handleNewGravatars()` and passing in the list of our custom events; -- We assert the state of the store. How does that work? - We're passing a unique combination of Entity type and id. Then we check a specific field on that Entity and assert that it has the value we expect it to have. We're doing this both for the initial Gravatar Entity we added to the store, as well as the two Gravatar entities that gets added when the handler function is called; -- And lastly - we're cleaning the store using `clearStore()` so that our next test can start with a fresh and empty store object. We can define as many test blocks as we want. - -There we go - we've created our first test! 👏 - -Now in order to run our tests you simply need to run the following in your subgraph root folder: - -`graph test Gravity` - -And if all goes well you should be greeted with the following: - -![Matchstick saying “All tests passed!”](/img/matchstick-tests-passed.png) - -## Common test scenarios - -### Hydrating the store with a certain state - -Users are able to hydrate the store with a known set of entities. Here's an example to initialise the store with a Gravatar entity: - -```typescript -let gravatar = new Gravatar('entryId') -gravatar.save() -``` - -### Calling a mapping function with an event - -A user can create a custom event and pass it to a mapping function that is bound to the store: - -```typescript -import { store } from 'matchstick-as/assembly/store' -import { NewGravatar } from '../../generated/Gravity/Gravity' -import { handleNewGravatars, createNewGravatarEvent } from './mapping' - -let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac') - -handleNewGravatar(newGravatarEvent) -``` - -### Calling all of the mappings with event fixtures - -Users can call the mappings with test fixtures. - -```typescript -import { NewGravatar } from '../../generated/Gravity/Gravity' -import { store } from 'matchstick-as/assembly/store' -import { handleNewGravatars, createNewGravatarEvent } from './mapping' - -let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac') - -let anotherGravatarEvent = createNewGravatarEvent(3546, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac') - -handleNewGravatars([newGravatarEvent, anotherGravatarEvent]) -``` - -``` -export function handleNewGravatars(events: NewGravatar[]): void { - events.forEach(event => { - handleNewGravatar(event); - }); -} -``` - -### Mocking contract calls - -Users can mock contract calls: - -```typescript -import { addMetadata, assert, createMockedFunction, clearStore, test } from 'matchstick-as/assembly/index' -import { Gravity } from '../../generated/Gravity/Gravity' -import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts' - -let contractAddress = Address.fromString('0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7') -let expectedResult = Address.fromString('0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947') -let bigIntParam = BigInt.fromString('1234') -createMockedFunction(contractAddress, 'gravatarToOwner', 'gravatarToOwner(uint256):(address)') - .withArgs([ethereum.Value.fromSignedBigInt(bigIntParam)]) - .returns([ethereum.Value.fromAddress(Address.fromString('0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947'))]) - -let gravity = Gravity.bind(contractAddress) -let result = gravity.gravatarToOwner(bigIntParam) - -assert.equals(ethereum.Value.fromAddress(expectedResult), ethereum.Value.fromAddress(result)) -``` - -As demonstrated, in order to mock a contract call and hardcore a return value, the user must provide a contract address, function name, function signature, an array of arguments, and of course - the return value. - -Users can also mock function reverts: - -```typescript -let contractAddress = Address.fromString('0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7') -createMockedFunction(contractAddress, 'getGravatar', 'getGravatar(address):(string,string)') - .withArgs([ethereum.Value.fromAddress(contractAddress)]) - .reverts() -``` - -### Mocking IPFS files (from matchstick 0.4.1) - -Users can mock IPFS files by using `mockIpfsFile(hash, filePath)` function. The function accepts two arguments, the first one is the IPFS file hash/path and the second one is the path to a local file. - -NOTE: When testing `ipfs.map/ipfs.mapJSON`, the callback function must be exported from the test file in order for matchstck to detect it, like the `processGravatar()` function in the test example bellow: - -`.test.ts` file: - -```typescript -import { assert, test, mockIpfsFile } from 'matchstick-as/assembly/index' -import { ipfs } from '@graphprotocol/graph-ts' -import { gravatarFromIpfs } from './utils' - -// Export ipfs.map() callback in order for matchstck to detect it -export { processGravatar } from './utils' - -test('ipfs.cat', () => { - mockIpfsFile('ipfsCatfileHash', 'tests/ipfs/cat.json') - - assert.entityCount(GRAVATAR_ENTITY_TYPE, 0) - - gravatarFromIpfs() - - assert.entityCount(GRAVATAR_ENTITY_TYPE, 1) - assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '1', 'imageUrl', 'https://i.ytimg.com/vi/MELP46s8Cic/maxresdefault.jpg') - - clearStore() -}) - -test('ipfs.map', () => { - mockIpfsFile('ipfsMapfileHash', 'tests/ipfs/map.json') - - assert.entityCount(GRAVATAR_ENTITY_TYPE, 0) - - ipfs.map('ipfsMapfileHash', 'processGravatar', Value.fromString('Gravatar'), ['json']) - - assert.entityCount(GRAVATAR_ENTITY_TYPE, 3) - assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '1', 'displayName', 'Gravatar1') - assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '2', 'displayName', 'Gravatar2') - assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '3', 'displayName', 'Gravatar3') -}) -``` - -`utils.ts` file: - -```typescript -import { Address, ethereum, JSONValue, Value, ipfs, json, Bytes } from "@graphprotocol/graph-ts" -import { Gravatar } from "../../generated/schema" - -... - -// ipfs.map callback -export function processGravatar(value: JSONValue, userData: Value): void { - // See the JSONValue documentation for details on dealing - // with JSON values - let obj = value.toObject() - let id = obj.get('id') - - if (!id) { - return - } - - // Callbacks can also created entities - let gravatar = new Gravatar(id.toString()) - gravatar.displayName = userData.toString() + id.toString() - gravatar.save() -} - -// function that calls ipfs.cat -export function gravatarFromIpfs(): void { - let rawData = ipfs.cat("ipfsCatfileHash") - - if (!rawData) { - return - } - - let jsonData = json.fromBytes(rawData as Bytes).toObject() - - let id = jsonData.get('id') - let url = jsonData.get("imageUrl") - - if (!id || !url) { - return - } - - let gravatar = new Gravatar(id.toString()) - gravatar.imageUrl = url.toString() - gravatar.save() -} -``` - -### Asserting the state of the store - -Users are able to assert the final (or midway) state of the store through asserting entities. In order to do this, the user has to supply an Entity type, the specific ID of an Entity, a name of a field on that Entity, and the expected value of the field. Here's a quick example: - -```typescript -import { assert } from 'matchstick-as/assembly/index' -import { Gravatar } from '../generated/schema' - -let gravatar = new Gravatar('gravatarId0') -gravatar.save() - -assert.fieldEquals('Gravatar', 'gravatarId0', 'id', 'gravatarId0') -``` - -Running the assert.fieldEquals() function will check for equality of the given field against the given expected value. The test will fail and an error message will be outputted if the values are **NOT** equal. Otherwise the test will pass successfully. - -### Interacting with Event metadata - -Users can use default transaction metadata, which could be returned as an ethereum.Event by using the `newMockEvent()` function. The following example shows how you can read/write to those fields on the Event object: - -```typescript -// Read -let logType = newGravatarEvent.logType - -// Write -let UPDATED_ADDRESS = '0xB16081F360e3847006dB660bae1c6d1b2e17eC2A' -newGravatarEvent.address = Address.fromString(UPDATED_ADDRESS) -``` - -### Asserting variable equality - -```typescript -assert.equals(ethereum.Value.fromString("hello"); ethereum.Value.fromString("hello")); -``` - -### Asserting that an Entity is **not** in the store - -Users can assert that an entity does not exist in the store. The function takes an entity type and an id. If the entity is in fact in the store, the test will fail with a relevant error message. Here's a quick example of how to use this functionality: - -```typescript -assert.notInStore('Gravatar', '23') -``` - -### Printing the whole store (for debug purposes) - -You can print the whole store to the console using this helper function: - -```typescript -import { logStore } from 'matchstick-as/assembly/store' - -logStore() -``` - -### Expected failure - -Users can have expected test failures, using the shouldFail flag on the test() functions: - -```typescript -test( - 'Should throw an error', - () => { - throw new Error() - }, - true, -) -``` - -If the test is marked with shouldFail = true but DOES NOT fail, that will show up as an error in the logs and the test block will fail. Also, if it's marked with shouldFail = false (the default state), the test executor will crash. - -### Logging - -Having custom logs in the unit tests is exactly the same as logging in the mappings. The difference is that the log object needs to be imported from matchstick-as rather than graph-ts. Here's a simple example with all non-critical log types: - -```typescript -import { test } from "matchstick-as/assembly/index"; -import { log } from "matchstick-as/assembly/log"; - -test("Success", () => { - log.success("Success!". []); -}); -test("Error", () => { - log.error("Error :( ", []); -}); -test("Debug", () => { - log.debug("Debugging...", []); -}); -test("Info", () => { - log.info("Info!", []); -}); -test("Warning", () => { - log.warning("Warning!", []); -}); -``` - -Users can also simulate a critical failure, like so: - -```typescript -test('Blow everything up', () => { - log.critical('Boom!') -}) -``` - -Logging critical errors will stop the execution of the tests and blow everything up. After all - we want to make sure you're code doesn't have critical logs in deployment, and you should notice right away if that were to happen. - -### Testing derived fields - -Testing derived fields is a feature which (as the example below shows) allows the user to set a field in a certain entity and have another entity be updated automatically if it derives one of its fields from the first entity. Important thing to note is that the first entity needs to be reloaded as the automatic update happens in the store in rust of which the AS code is agnostic. - -```typescript -test('Derived fields example test', () => { - let mainAccount = new GraphAccount('12') - mainAccount.save() - let operatedAccount = new GraphAccount('1') - operatedAccount.operators = ['12'] - operatedAccount.save() - let nst = new NameSignalTransaction('1234') - nst.signer = '12' - nst.save() - - assert.assertNull(mainAccount.get('nameSignalTransactions')) - assert.assertNull(mainAccount.get('operatorOf')) - - mainAccount = GraphAccount.load('12')! - - assert.i32Equals(1, mainAccount.nameSignalTransactions.length) - assert.stringEquals('1', mainAccount.operatorOf[0]) -}) -``` - -### Testing dynamic data sources - -Testing dynamic data sources can be be done by mocking the return value of the `context()`, `address()` and `network()` functions of the dataSource namespace. These functions currently return the following: `context()` - returns an empty entity (DataSourceContext), `address()` - returns `0x0000000000000000000000000000000000000000`, `network()` - returns `mainnet`. The `create(...)` and `createWithContext(...)` functions are mocked to do nothing so they don't need to be called in the tests at all. Changes to the return values can be done through the functions of the `dataSourceMock` namespace in `matchstick-as` (version 0.3.0+). - -Example below: - -First we have the following event handler (which has been intentionally repurposed to showcase datasource mocking): - -```typescript -export function handleApproveTokenDestinations(event: ApproveTokenDestinations): void { - let tokenLockWallet = TokenLockWallet.load(dataSource.address().toHexString())! - if (dataSource.network() == 'rinkeby') { - tokenLockWallet.tokenDestinationsApproved = true - } - let context = dataSource.context() - if (context.get('contextVal')!.toI32() > 0) { - tokenLockWallet.setBigInt('tokensReleased', BigInt.fromI32(context.get('contextVal')!.toI32())) - } - tokenLockWallet.save() -} -``` - -And then we have the test using one of the methods in the dataSourceMock namespace to set a new return value for all of the dataSource functions: - -```typescript -import { assert, test, newMockEvent, dataSourceMock } from 'matchstick-as/assembly/index' -import { BigInt, DataSourceContext, Value } from '@graphprotocol/graph-ts' - -import { handleApproveTokenDestinations } from '../../src/token-lock-wallet' -import { ApproveTokenDestinations } from '../../generated/templates/GraphTokenLockWallet/GraphTokenLockWallet' -import { TokenLockWallet } from '../../generated/schema' - -test('Data source simple mocking example', () => { - let addressString = '0xA16081F360e3847006dB660bae1c6d1b2e17eC2A' - let address = Address.fromString(addressString) - - let wallet = new TokenLockWallet(address.toHexString()) - wallet.save() - let context = new DataSourceContext() - context.set('contextVal', Value.fromI32(325)) - dataSourceMock.setReturnValues(addressString, 'rinkeby', context) - let event = changetype(newMockEvent()) - - assert.assertTrue(!wallet.tokenDestinationsApproved) - - handleApproveTokenDestinations(event) - - wallet = TokenLockWallet.load(address.toHexString())! - assert.assertTrue(wallet.tokenDestinationsApproved) - assert.bigIntEquals(wallet.tokensReleased, BigInt.fromI32(325)) - - dataSourceMock.resetValues() -}) -``` - -Notice that dataSourceMock.resetValues() is called at the end. That's because the values are remembered when they are changed and need to be reset if you want to go back to the default values. - -## Test Coverage - -Using **Matchstick**, subgraph developers are able to run a script that will calculate the test coverage of the written unit tests. - -The test coverage tool takes the compiled test `wasm` binaries and converts them to `wat` files, which can then be easily inspected to see whether or not the handlers defined in `subgraph.yaml` have been called. Since code coverage (and testing as whole) is in very early stages in AssemblyScript and WebAssembly, **Matchstick** cannot check for branch coverage. Instead we rely on the assertion that if a given handler has been called, the event/function for it have been properly mocked. - -### Prerequisites - -To run the test coverage functionality provided in **Matchstick**, there are a few things you need to prepare beforehand: - -#### Export your handlers - -In order for **Matchstick** to check which handlers are being run, those handlers need to be exported from the **test file**. So for instance in our example, in our gravity.test.ts file we have the following handler being imported: - -```typescript -import { handleNewGravatar } from '../../src/gravity' -``` - -In order for that function to be visible (for it to be included in the `wat` file **by name**) we need to also export it, like this: - -```typescript -export { handleNewGravatar } -``` - -### Usage - -Once that's all set up, to run the test coverage tool, simply run: - -```sh -graph test -- -c -``` - -You could also add a custom `coverage` command to your `package.json` file, like so: - -```typescript - "scripts": { - /.../ - "coverage": "graph test -- -c" - }, -``` - -That will execute the coverage tool and you should see something like this in the terminal: - -```sh -$ graph test -c -Skipping download/install step because binary already exists at /Users/petko/work/demo-subgraph/node_modules/binary-install-raw/bin/0.4.0 - -___ ___ _ _ _ _ _ -| \/ | | | | | | | (_) | | -| . . | __ _| |_ ___| |__ ___| |_ _ ___| | __ -| |\/| |/ _` | __/ __| '_ \/ __| __| |/ __| |/ / -| | | | (_| | || (__| | | \__ \ |_| | (__| < -\_| |_/\__,_|\__\___|_| |_|___/\__|_|\___|_|\_\ - -Compiling... - -Running in coverage report mode. - ️ -Reading generated test modules... 🔎️ - -Generating coverage report 📝 - -Handlers for source 'Gravity': -Handler 'handleNewGravatar' is tested. -Handler 'handleUpdatedGravatar' is not tested. -Handler 'handleCreateGravatar' is tested. -Test coverage: 66.7% (2/3 handlers). - -Handlers for source 'GraphTokenLockWallet': -Handler 'handleTokensReleased' is not tested. -Handler 'handleTokensWithdrawn' is not tested. -Handler 'handleTokensRevoked' is not tested. -Handler 'handleManagerUpdated' is not tested. -Handler 'handleApproveTokenDestinations' is not tested. -Handler 'handleRevokeTokenDestinations' is not tested. -Test coverage: 0.0% (0/6 handlers). - -Global test coverage: 22.2% (2/9 handlers). -``` - -### Test run time duration in the log output - -The log output includes the test run duration. Here's an example: - -`[Thu, 31 Mar 2022 13:54:54 +0300] Program executed in: 42.270ms.` - -## Common compiler errors - -> Critical: Could not create WasmInstance from valid module with context: unknown import: wasi_snapshot_preview1::fd_write has not been defined - -This means you have used `console.log` in your code, which is not supported by AssemblyScript. Please consider using the [Logging API](/developing/graph-ts/api/#logging-api) - -> ERROR TS2554: Expected ? arguments, but got ?. -> -> return new ethereum.Block(defaultAddressBytes, defaultAddressBytes, defaultAddressBytes, defaultAddress, defaultAddressBytes, defaultAddressBytes, defaultAddressBytes, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt); -> -> in ~lib/matchstick-as/assembly/defaults.ts(18,12) -> -> ERROR TS2554: Expected ? arguments, but got ?. -> -> return new ethereum.Transaction(defaultAddressBytes, defaultBigInt, defaultAddress, defaultAddress, defaultBigInt, defaultBigInt, defaultBigInt, defaultAddressBytes, defaultBigInt); -> -> in ~lib/matchstick-as/assembly/defaults.ts(24,12) - -The mismatch in arguments is caused by mismatch in `graph-ts` and `matchstick-as`. The best way to fix issues like this one is to update everything to the latest released version. - -## Feedback - -If you have any questions, feedback, feature requests or just want to reach out, the best place would be The Graph Discord where we have a dedicated channel for Matchstick, called 🔥| unit-testing. diff --git a/website/pages/ha/docsearch.json b/website/pages/ha/docsearch.json deleted file mode 100644 index 8cfff967936d..000000000000 --- a/website/pages/ha/docsearch.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "button": { - "buttonText": "Search", - "buttonAriaLabel": "Search" - }, - "modal": { - "searchBox": { - "resetButtonTitle": "Clear the query", - "resetButtonAriaLabel": "Clear the query", - "cancelButtonText": "Cancel", - "cancelButtonAriaLabel": "Cancel" - }, - "startScreen": { - "recentSearchesTitle": "Recent", - "noRecentSearchesText": "No recent searches", - "saveRecentSearchButtonTitle": "Save this search", - "removeRecentSearchButtonTitle": "Remove this search from history", - "favoriteSearchesTitle": "Favorite", - "removeFavoriteSearchButtonTitle": "Remove this search from favorites" - }, - "errorScreen": { - "titleText": "Unable to fetch results", - "helpText": "You might want to check your network connection." - }, - "footer": { - "selectText": "to select", - "selectKeyAriaLabel": "Enter key", - "navigateText": "to navigate", - "navigateUpKeyAriaLabel": "Arrow up", - "navigateDownKeyAriaLabel": "Arrow down", - "closeText": "to close", - "closeKeyAriaLabel": "Escape key", - "searchByText": "Search by" - }, - "noResultsScreen": { - "noResultsText": "No results for", - "suggestedQueryText": "Try searching for", - "reportMissingResultsText": "Believe this query should return results?", - "reportMissingResultsLinkText": "Let us know." - } - } -} diff --git a/website/pages/ha/firehose.mdx b/website/pages/ha/firehose.mdx deleted file mode 100644 index 02f0d63c72db..000000000000 --- a/website/pages/ha/firehose.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Firehose ---- - -![Firehose Logo](/img/firehose-logo.png) - -Firehose is a new technology developed by StreamingFast working with The Graph Foundation. The product provides **previously unseen capabilities and speeds for indexing blockchain data** using a files-based and streaming-first approach. - -Firehose extracts, transforms and saves blockchain data in a highly performant file-based strategy. Blockchain developers can then access data extracted by Firehose through binary data streams. Firehose is intended to stand as a replacement for The Graph’s original blockchain data extraction layer. - -## Firehose Documentation - -The Firehose documentation is currently maintained by the StreamingFast team [on the StreamingFast website](https://firehose.streamingfast.io/). - -### Getting Started - -- Read this [Firehose introduction](https://firehose.streamingfast.io/introduction/firehose-overview) to get an overview of what it is and why it was built. -- Learn about the [Prerequisites](https://firehose.streamingfast.io/introduction/prerequisites) to install and deploy Firehose. - -### Expand Your Knowledge - -- Learn about the different [Firehose components](https://firehose.streamingfast.io/architecture/components) available. diff --git a/website/pages/ha/global.json b/website/pages/ha/global.json deleted file mode 100644 index 6a3eb234bfce..000000000000 --- a/website/pages/ha/global.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "collapse": "Collapse", - "expand": "Expand", - "previous": "Previous", - "next": "Next", - "editPage": "Edit page", - "pageSections": "Page Sections", - "linkToThisSection": "Link to this section", - "technicalLevelRequired": "Technical Level Required", - "notFoundTitle": "Oops! This page was lost in space...", - "notFoundSubtitle": "Check if you’re using the right address or explore our website by clicking on the link below.", - "goHome": "Go Home", - "video": "Video" -} diff --git a/website/pages/ha/glossary.mdx b/website/pages/ha/glossary.mdx deleted file mode 100644 index ef24dc0178e0..000000000000 --- a/website/pages/ha/glossary.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Glossary ---- - -- **The Graph**: A decentralized protocol for indexing and querying data. - -- **Query**: A request for data. In the case of The Graph, a query is a request for data from a subgraph that will be answered by an Indexer. - -- **GraphQL**: A query language for APIs and a runtime for fulfilling those queries with your existing data. The Graph uses GraphQL to query subgraphs. - -- **Endpoint**: A URL that can be used to query a subgraph. The testing endpoint for Subgraph Studio is `https://api.studio.thegraph.com/query///` and the Graph Explorer endpoint is `https://gateway.thegraph.com/api//subgraphs/id/`. The Graph Explorer endpoint is used to query subgraphs on The Graph's decentralized network. - -- **Subgraph**: A custom API built on blockchain data that can be queried using [GraphQL](https://graphql.org/). Developers can build, deploy and publish subgraphs to The Graph's decentralized network. Then, Indexers can begin indexing subgraphs to make them available to be queried by subgraph consumers. - -- **Hosted service**: A temporary scaffold service for building and querying subgraphs as The Graph's decentralized network is maturing its cost of service, quality of service, and developer experience. - -- **Indexers**: Network participants that run indexing nodes to index data from blockchains and serve GraphQL queries. - -- **Indexer Revenue Streams**: Indexers are rewarded in GRT with two components: query fee rebates and indexing rewards. - - 1. **Query Fee Rebates**: Payments from subgraph consumers for serving queries on the network. - - 2. **Indexing Rewards**: The rewards that Indexers receive for indexing subgraphs. Indexing rewards are generated via new issuance of 3% GRT annually. - -- **Indexer's Self Stake**: The amount of GRT that Indexers stake to participate in the decentralized network. The minimum is 100,000 GRT, and there is no upper limit. - -- **Upgrade Indexer**: A temporary Indexer designed to act as a fallback for subgraph queries not serviced by other Indexers on the network. It ensures a seamless transition for subgraphs upgrading from the hosted service by readily serving their queries upon being published. The upgrade Indexer is not competitive with other Indexers. It supports numerous blockchains that were previously only available on the hosted service. - -- **Delegators**: Network participants who own GRT and delegate their GRT to Indexers. This allows Indexers to increase their stake in subgraphs on the network. In return, Delegators receive a portion of the Indexing Rewards that Indexers receive for processing subgraphs. - -- **Delegation Tax**: A 0.5% fee paid by Delegators when they delegate GRT to Indexers. The GRT used to pay the fee is burned. - -- **Curators**: Network participants that identify high-quality subgraphs, and “curate” them (i.e., signal GRT on them) in exchange for curation shares. When Indexers claim query fees on a subgraph, 10% is distributed to the Curators of that subgraph. Indexers earn indexing rewards proportional to the signal on a subgraph. We see a correlation between the amount of GRT signalled and the number of Indexers indexing a subgraph. - -- **Curation Tax**: A 1% fee paid by Curators when they signal GRT on subgraphs. The GRT used to pay the fee is burned. - -- **Subgraph Consumer**: Any application or user that queries a subgraph. - -- **Subgraph Developer**: A developer who builds and deploys a subgraph to The Graph's decentralized network. - -- **Subgraph Manifest**: A JSON file that describes the subgraph's GraphQL schema, data sources, and other metadata. [Here](https://ipfs.io/ipfs/QmVQdzeGdPUiLiACeqXRpKAYpyj8Z1yfWLMUq7A7WundUf) is an example. - -- **Epoch**: A unit of time within the network. Currently, one epoch is 6,646 blocks or approximately 1 day. - -- **Allocation**: An Indexer can allocate their total GRT stake (including Delegators' stake) towards subgraphs that have been published on The Graph's decentralized network. Allocations exist in one of four phases. - - 1. **Active**: An allocation is considered active when it is created on-chain. This is called opening an allocation, and indicates to the network that the Indexer is actively indexing and serving queries for a particular subgraph. Active allocations accrue indexing rewards proportional to the signal on the subgraph, and the amount of GRT allocated. - - 2. **Closed**: An Indexer may claim the accrued indexing rewards on a given subgraph by submitting a recent, and valid, Proof of Indexing (POI). This is known as closing an allocation. An allocation must have been open for a minimum of one epoch before it can be closed. The maximum allocation period is 28 epochs. If an indexer leaves an allocation open beyond 28 epochs, it is known as a stale allocation. When an allocation is in the **Closed** state, a Fisherman can still open a dispute to challenge an Indexer for serving false data. - -- **Subgraph Studio**: A powerful dapp for building, deploying, and publishing subgraphs. - -- **Fishermen**: A role within The Graph Network held by participants who monitor the accuracy and integrity of data served by Indexers. When a Fisherman identifies a query response or a POI they believe to be incorrect, they can initiate a dispute against the Indexer. If the dispute rules in favor of the Fisherman, the Indexer is slashed. Specifically, the Indexer will lose 2.5% of their self-stake of GRT. Of this amount, 50% is awarded to the Fisherman as a bounty for their vigilance, and the remaining 50% is removed from circulation (burned). This mechanism is designed to encourage Fishermen to help maintain the reliability of the network by ensuring that Indexers are held accountable for the data they provide. - -- **Arbitrators**: Arbitrators are network participants appointed through a governance process. The role of the Arbitrator is to decide the outcome of indexing and query disputes. Their goal is to maximize the utility and reliability of The Graph Network. - -- **Slashing**: Indexers can have their self-staked GRT slashed for providing an incorrect POI or for serving inaccurate data. or for serving inaccurate data. The slashing percentage is a protocol parameter currently set to 2.5% of an Indexer's self stake. 50% of the slashed GRT goes to the Fisherman that disputed the inaccurate data or incorrect POI. The other 50% is burned. - -- **Indexing Rewards**: The rewards that Indexers receive for indexing subgraphs. Indexing rewards are distributed in GRT. - -- **Delegation Rewards**: The rewards that Delegators receive for delegating GRT to Indexers. Delegation rewards are distributed in GRT. - -- **GRT**: The Graph's work utility token. GRT provides economic incentives to network participants for contributing to the network. - -- **POI or Proof of Indexing**: When an Indexer closes their allocation and wants to claim their accrued indexing rewards on a given subgraph, they must provide a valid and recent Proof of Indexing (POI). Fishermen may dispute the POI provided by an Indexer. A dispute resolved in the Fisherman's favor will result in slashing of the Indexer. - -- **Graph Node**: Graph Node is the component which indexes subgraphs, and makes the resulting data available to query via a GraphQL API. As such it is central to the indexer stack, and correct operation of Graph Node is crucial to running a successful indexer. - -- **Indexer agent**: The Indexer agent is part of the indexer stack. It facilitates the Indexer's interactions on-chain, including registering on the network, managing subgraph deployments to its Graph Node(s), and managing allocations. - -- **The Graph Client**: A library for building GraphQL-based dapps in a decentralized way. - -- **Graph Explorer**: A dapp designed for network participants to explore subgraphs and interact with the protocol. - -- **Graph CLI**: A command line interface tool for building and deploying to The Graph. - -- **Cooldown Period**: The time remaining until an Indexer who changed their delegation parameters can do so again. - -- **L2 Transfer Tools**: Smart contracts and UI that enable network participants to transfer network related assets from Ethereum mainnet to Arbitrum One. Network participants can transfer delegated GRT, subgraphs, curation shares, and Indexer's self stake. - -- **_Upgrading_ a subgraph to The Graph Network**: The process of moving a subgraph from the hosted service to The Graph Network. - -- **_Updating_ a subgraph**: The process of releasing a new subgraph version with updates to the subgraph's manifest, schema, or mappings. - -- **Migrating**: The process of curation shares moving from an old version of a subgraph to a new version of a subgraph (e.g. when v0.0.1 is updated to v0.0.2). diff --git a/website/pages/ha/graphcast.mdx b/website/pages/ha/graphcast.mdx deleted file mode 100644 index 28a374637e81..000000000000 --- a/website/pages/ha/graphcast.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Graphcast ---- - -## Introduction - -Is there something you'd like to learn from or share with your fellow Indexers in an automated manner, but it's too much hassle or costs too much gas? - -Currently, the cost to broadcast information to other network participants is determined by gas fees on the Ethereum blockchain. Graphcast solves this problem by acting as an optional decentralized, distributed peer-to-peer (P2P) communication tool that allows Indexers across the network to exchange information in real time. The cost of exchanging P2P messages is near zero, with the tradeoff of no data integrity guarantees. Nevertheless, Graphcast aims to provide message validity guarantees (i.e. that the message is valid and signed by a known protocol participant) with an open design space of reputation models. - -The Graphcast SDK (Software Development Kit) allows developers to build Radios, which are gossip-powered applications that Indexers can run to serve a given purpose. We also intend to create a few Radios (or provide support to other developers/teams that wish to build Radios) for the following use cases: - -- Real-time cross-checking of subgraph data integrity ([Subgraph Radio](https://docs.graphops.xyz/graphcast/radios/subgraph-radio)). -- Conducting auctions and coordination for warp syncing subgraphs, substreams, and Firehose data from other Indexers. -- Self-reporting on active query analytics, including subgraph request volumes, fee volumes, etc. -- Self-reporting on indexing analytics, including subgraph indexing time, handler gas costs, indexing errors encountered, etc. -- Self-reporting on stack information including graph-node version, Postgres version, Ethereum client version, etc. - -### Learn More - -If you would like to learn more about Graphcast, [check out the documentation here.](https://docs.graphops.xyz/graphcast/intro) diff --git a/website/pages/ha/index.json b/website/pages/ha/index.json deleted file mode 100644 index 4d6352633874..000000000000 --- a/website/pages/ha/index.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "title": "Get Started", - "intro": "Learn about The Graph, a decentralized protocol for indexing and querying data from blockchains.", - "shortcuts": { - "aboutTheGraph": { - "title": "About The Graph", - "description": "Learn more about The Graph" - }, - "quickStart": { - "title": "Quick Start", - "description": "Jump in and start with The Graph" - }, - "developerFaqs": { - "title": "Developer FAQs", - "description": "Frequently asked questions" - }, - "queryFromAnApplication": { - "title": "Query from an Application", - "description": "Learn to query from an application" - }, - "createASubgraph": { - "title": "Create a Subgraph", - "description": "Use Studio to create subgraphs" - } - }, - "networkRoles": { - "title": "Network Roles", - "description": "Learn about The Graph’s network roles.", - "roles": { - "developer": { - "title": "Developer", - "description": "Create a subgraph or use existing subgraphs in a dapp" - }, - "indexer": { - "title": "Indexer", - "description": "Operate a node to index data and serve queries" - }, - "curator": { - "title": "Curator", - "description": "Organize data by signaling on subgraphs" - }, - "delegator": { - "title": "Delegator", - "description": "Secure the network by delegating GRT to Indexers" - } - } - }, - "readMore": "Read more", - "products": { - "title": "Products", - "products": { - "subgraphStudio": { - "title": "Subgraph Studio", - "description": "Create, manage and publish subgraphs and API keys" - }, - "graphExplorer": { - "title": "Graph Explorer", - "description": "Explore subgraphs and interact with the protocol" - }, - "hostedService": { - "title": "Hosted Service", - "description": "Create and explore subgraphs on the hosted service" - } - } - }, - "supportedNetworks": { - "title": "Supported Networks", - "description": "The Graph supports the following networks on The Graph Network and the hosted service.", - "graphNetworkAndHostedService": "The Graph Network & hosted service", - "hostedService": "hosted service" - } -} diff --git a/website/pages/ha/managing/_meta.js b/website/pages/ha/managing/_meta.js deleted file mode 100644 index a7c7b3d79464..000000000000 --- a/website/pages/ha/managing/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/managing/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/managing/delete-a-subgraph.mdx b/website/pages/ha/managing/delete-a-subgraph.mdx deleted file mode 100644 index 68ef0a37da75..000000000000 --- a/website/pages/ha/managing/delete-a-subgraph.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Delete a Subgraph ---- - -Delete your subgraph using [Subgraph Studio](https://thegraph.com/studio/). - -> Deleting your subgraph will remove all published versions from The Graph Network, but it will remain visible on Graph Explorer and Subgraph Studio for users who have signaled on it. - -## Step-by-Step - -1. Visit the subgraph's page on [Subgraph Studio](https://thegraph.com/studio/). -2. Click on the three-dots to the right of the "publish" button. -3. Click on the option to "delete this subgraph": - - ![Delete-subgraph](/img/Delete-subgraph.png) - -4. Depending on the subgraph's status, you will be prompted with various options. - - - If the subgraph is not published, simply click “delete” and confirm. - - If the subgraph is published, you will need to confirm on your wallet before the subgraph can be deleted from Studio. If a subgraph is published to multiple networks, such as testnet and mainnet, additional steps may be required. - -> If the owner of the subgraph has signal on it, the signaled GRT will be returned to the owner. - -### Important Reminders - -- Once you delete a subgraph, it will **not** appear on Graph Explorer's homepage. However, users who have signaled on it will still be able to view it on their profile pages and remove their signal. -- Curators will not be able to signal on the subgraph anymore. -- Curators that already signaled on the subgraph can withdraw their signal at an average share price. -- Deleted subgraphs will show an error message. diff --git a/website/pages/ha/managing/transfer-a-subgraph.mdx b/website/pages/ha/managing/transfer-a-subgraph.mdx deleted file mode 100644 index c4060284d5d9..000000000000 --- a/website/pages/ha/managing/transfer-a-subgraph.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Transfer and Deprecate a Subgraph ---- - -## Transferring ownership of a subgraph - -Subgraphs published to the decentralized network have an NFT minted to the address that published the subgraph. The NFT is based on a standard ERC721, which facilitates transfers between accounts on The Graph Network. - -**Please note the following:** - -- Whoever owns the NFT controls the subgraph. -- If the owner decides to sell or transfer the NFT, they will no longer be able to edit or update that subgraph on the network. -- You can easily move control of a subgraph to a multi-sig. -- A community member can create a subgraph on behalf of a DAO. - -### View your subgraph as an NFT - -To view your subgraph as an NFT, you can visit an NFT marketplace like **OpenSea**: - -``` -https://opensea.io/your-wallet-address -``` - -Or a wallet explorer like **Rainbow.me**: - -``` -https://rainbow.me/your-wallet-addres -``` - -### Step-by-Step - -To transfer ownership of a subgraph, do the following: - -1. Use the UI built into Subgraph Studio: - - ![Subgraph Ownership Transfer](/img/subgraph-ownership-transfer-1.png) - -2. Choose the address that you would like to transfer the subgraph to: - - ![Subgraph Ownership Trasfer](/img/subgraph-ownership-transfer-2.png) - -Optionally, you can also use the built-in UI of NFT marketplaces like OpenSea: - -![Subgraph Ownership Transfer from NFT marketplace](/img/subgraph-ownership-transfer-nft-marketplace.png) - -## Deprecating a subgraph - -Although you cannot delete a subgraph, you can deprecate it on Graph Explorer. - -### Step-by-Step - -To deprecate your subgraph, do the following: - -1. Visit the contract address for Arbitrum One subgraphs [here](https://arbiscan.io/address/0xec9A7fb6CbC2E41926127929c2dcE6e9c5D33Bec#writeProxyContract). -2. Call `deprecateSubgraph` with your `SubgraphID` as your argument. -3. Your subgraph will no longer appear in searches on Graph Explorer. - -**Please note the following:** - -- The owner's wallet should call the `deprecateSubgraph` function. -- Curators will not be able to signal on the subgraph anymore. -- Curators that already signaled on the subgraph can withdraw their signal at an average share price. -- Deprecated subgraphs will show an error message. - -> If you interacted with the deprecated subgraph, you can find it in your user profile under the "Subgraphs", "Indexing", or "Curating" tab, respectively. diff --git a/website/pages/ha/network/_meta.js b/website/pages/ha/network/_meta.js deleted file mode 100644 index 49858537c885..000000000000 --- a/website/pages/ha/network/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/network/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/network/benefits.mdx b/website/pages/ha/network/benefits.mdx deleted file mode 100644 index 864672b16515..000000000000 --- a/website/pages/ha/network/benefits.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: The Graph Network vs. Self Hosting -socialImage: https://thegraph.com/docs/img/seo/benefits.jpg ---- - -The Graph’s decentralized network has been engineered and refined to create a robust indexing and querying experience—and it’s getting better every day thanks to thousands of contributors around the world. - -The benefits of this decentralized protocol cannot be replicated by running a `graph-node` locally. The Graph Network is more reliable, more efficient, and less expensive. - -Here is an analysis: - -## Why You Should Use The Graph Network - -- 60-98% lower monthly cost -- $0 infrastructure setup costs -- Superior uptime -- Access to hundreds of independent Indexers around the world -- 24/7 technical support by global community - -## The Benefits Explained - -### Lower & more Flexible Cost Structure - -No contracts. No monthly fees. Only pay for the queries you use—with an average cost-per-query of $0.0002. Queries are priced in USD and paid in GRT. - -Query costs may vary; the quoted cost is the average at time of publication (December 2022). - -## Low Volume User (less than 30,000 queries per month) - -| Cost Comparison | Self Hosted | Graph Network | -| :-: | :-: | :-: | -| Monthly server cost\* | $350 per month | $0 | -| Query costs | $0+ | ~$15 per month | -| Engineering time | $400 per month | None, built into the network with globally distributed Indexers | -| Queries per month | Limited to infra capabilities | 30,000 (autoscaling) | -| Cost per query | $0 | $0.0005 | -| Infrastructure | Centralized | Decentralized | -| Geographic redundancy | $750+ per additional node | Included | -| Uptime | Varies | 99.9%+ | -| Total Monthly Costs | $750+ | ~$15 | - -## Medium Volume User (3,000,000+ queries per month) - -| Cost Comparison | Self Hosted | Graph Network | -| :-: | :-: | :-: | -| Monthly server cost\* | $350 per month | $0 | -| Query costs | $500 per month | $750 per month | -| Engineering time | $800 per month | None, built into the network with globally distributed Indexers | -| Queries per month | Limited to infra capabilities | 3,000,000+ | -| Cost per query | $0 | $0.00025 | -| Infrastructure | Centralized | Decentralized | -| Engineering expense | $200 per hour | Included | -| Geographic redundancy | $1,200 in total costs per additional node | Included | -| Uptime | Varies | 99.9%+ | -| Total Monthly Costs | $1,650+ | $750 | - -## High Volume User (30,000,000+ queries per month) - -| Cost Comparison | Self Hosted | Graph Network | -| :-: | :-: | :-: | -| Monthly server cost\* | $1100 per month, per node | $0 | -| Query costs | $4000 | $4,500 per month | -| Number of nodes needed | 10 | Not applicable | -| Engineering time | $6,000 or more per month | None, built into the network with globally distributed Indexers | -| Queries per month | Limited to infra capabilities | 30,000,000+ | -| Cost per query | $0 | $0.00015 | -| Infrastructure | Centralized | Decentralized | -| Geographic redundancy | $1,200 in total costs per additional node | Included | -| Uptime | Varies | 99.9%+ | -| Total Monthly Costs | $11,000+ | $4,500 | - -\*including costs for backup: $50-$100 per month - -Engineering time based on $200 per hour assumption - -using the max query budget function in the budget billing tab, while maintaining high quality of service - -Estimated costs are only for Ethereum Mainnet subgraphs — costs are even higher when self hosting a `graph-node` on other networks. - -Curating signal on a subgraph is an optional one-time, net-zero cost (e.g., $1k in signal can be curated on a subgraph, and later withdrawn—with potential to earn returns in the process). - -Some users may need to update their subgraph to a new version. Due to Ethereum gas fees, an update costs ~$50 at time of writing. - -Note that gas fees on [Arbitrum](/arbitrum/arbitrum-faq) are substantially lower than Ethereum mainnet. - -## No Setup Costs & Greater Operational Efficiency - -Zero setup fees. Get started immediately with no setup or overhead costs. No hardware requirements. No outages due to centralized infrastructure, and more time to concentrate on your core product . No need for backup servers, troubleshooting, or expensive engineering resources. - -## Reliability & Resiliency - -The Graph’s decentralized network gives users access to geographic redundancy that does not exist when self-hosting a `graph-node`. Queries are served reliably thanks to 99.9%+ uptime, achieved by hundreds of independent Indexers securing the network globally. - -Bottom line: The Graph Network is less expensive, easier to use, and produces superior results compared to running a `graph-node` locally. - -Start using The Graph Network today, and learn how to [upgrade your subgraph to The Graph's decentralized network](/cookbook/upgrading-a-subgraph). diff --git a/website/pages/ha/network/contracts.mdx b/website/pages/ha/network/contracts.mdx deleted file mode 100644 index 6abd80577ced..000000000000 --- a/website/pages/ha/network/contracts.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Protocol Contracts ---- - -import { ProtocolContractsTable } from '@/src/contracts' - -Below are the deployed contracts which power The Graph Network. Visit the official [contracts repository](https://github.com/graphprotocol/contracts) to learn more. - -## Arbitrum - -This is the principal deployment of The Graph Network. - - - -## Mainnet - -This was the original deployment of The Graph Network. [Learn more](/arbitrum/arbitrum-faq) about The Graph's scaling with Arbitrum. - - - -## Arbitrum Sepolia - -This is the primary testnet for The Graph Network. Testnet is predominantly used by core developers and ecosystem participants for testing purposes. There are no guarantees of service or availability on The Graph's testnets. - - - -## Sepolia - - diff --git a/website/pages/ha/network/curating.mdx b/website/pages/ha/network/curating.mdx deleted file mode 100644 index 797d9b9dd896..000000000000 --- a/website/pages/ha/network/curating.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Curating ---- - -Curators are critical to the Graph decentralized economy. They use their knowledge of the web3 ecosystem to assess and signal on the subgraphs that should be indexed by The Graph Network. Through the Explorer, curators are able to view network data to make signaling decisions. The Graph Network rewards curators who signal on good quality subgraphs with a share of the query fees that subgraphs generate. Curators are economically incentivized to signal early. These cues from curators are important for Indexers, who can then process or index the data from these signaled subgraphs. - -When signaling, curators can decide to signal on a specific version of the subgraph or to signal using auto-migrate. When signaling using auto-migrate, a Curator’s shares will always be migrated to the latest version published by the developer. If you decide to signal on a specific version instead, shares will always stay on this specific version. - -Remember that curation is risky. Please do your diligence to make sure you curate on subgraphs you trust. Creating a subgraph is permissionless, so people can create subgraphs and call them any name they'd like. For more guidance on curation risks, check out [The Graph Academy's Curation Guide.](https://thegraph.academy/curators/) - -## Bonding Curve 101 - -First, we take a step back. Each subgraph has a bonding curve on which curation shares are minted when a user adds signal **into** the curve. Each subgraph’s bonding curve is unique. The bonding curves are architected so that the price to mint a curation share on a subgraph increases linearly, over the number of shares minted. - -![Price per shares](/img/price-per-share.png) - -As a result, price increases linearly, meaning that it will get more expensive to purchase a share over time. Here’s an example of what we mean, see the bonding curve below: - -![Bonding curve](/img/bonding-curve.png) - -Consider we have two curators that mint shares for a subgraph: - -- Curator A is the first to signal on the subgraph. By adding 120,000 GRT into the curve, they are able to mint 2000 shares. -- Curator B’s signal is on the subgraph at some point in time later. To receive the same amount of shares as Curator A, they would have to add 360,000 GRT into the curve. -- Since both curators hold half the total of curation shares, they would receive an equal amount of curator royalties. -- If any of the curators were now to burn their 2000 curation shares, they would receive 360,000 GRT. -- The remaining curator would now receive all the curator royalties for that subgraph. If they were to burn their shares to withdraw GRT, they would receive 120,000 GRT. -- **TLDR:** The GRT valuation of curation shares is determined by the bonding curve and can be volatile. There is potential to incur big losses. Signaling early means you put in less GRT for each share. By extension, this means you earn more curator royalties per GRT than later curators for the same subgraph. - -In general, a bonding curve is a mathematical curve that defines the relationship between token supply and asset price. In the specific case of subgraph curation, **the price of each subgraph share increases with each token invested** and the **price of each share decreases with each token sold.** - -In the case of The Graph, [Bancor’s implementation of a bonding curve formula](https://drive.google.com/file/d/0B3HPNP-GDn7aRkVaV3dkVl9NS2M/view?resourcekey=0-mbIgrdd0B9H8dPNRaeB_TA) is leveraged. - -## How to Signal - -Now that we’ve covered the basics about how the bonding curve works, this is how you will proceed to signal on a subgraph. Within the Curator tab on the Graph Explorer, curators will be able to signal and unsignal on certain subgraphs based on network stats. For a step-by-step overview of how to do this in the Explorer, [click here.](/network/explorer) - -A curator can choose to signal on a specific subgraph version, or they can choose to have their signal automatically migrate to the newest production build of that subgraph. Both are valid strategies and come with their own pros and cons. - -Signaling on a specific version is especially useful when one subgraph is used by multiple dApps. One dApp might need to regularly update the subgraph with new features. Another dApp might prefer to use an older, well-tested subgraph version. Upon initial curation, a 1% standard tax is incurred. - -Having your signal automatically migrate to the newest production build can be valuable to ensure you keep accruing query fees. Every time you curate, a 1% curation tax is incurred. You will also pay a 0.5% curation tax on every migration. Subgraph developers are discouraged from frequently publishing new versions - they have to pay a 0.5% curation tax on all auto-migrated curation shares. - -> **Note**: The first address to signal a particular subgraph is considered the first curator and will have to do much more gas-intensive work than the rest of the following curators because the first curator initializes the curation share tokens, initializes the bonding curve, and also transfers tokens into the Graph proxy. - -## What does Signaling mean for The Graph Network? - -For end consumers to be able to query a subgraph, the subgraph must first be indexed. Indexing is a process where files, data, and metadata are looked at, cataloged, and then indexed so that results can be found faster. In order for a subgraph’s data to be searchable, it needs to be organized. - -And so, if Indexers had to guess which subgraphs they should index, there would be a low chance that they would earn robust query fees because they’d have no way of validating which subgraphs are good quality. Enter curation. - -Curators make The Graph network efficient and signaling is the process that curators use to let Indexers know that a subgraph is good to index, where GRT is added to a bonding curve for a subgraph. Indexers can inherently trust the signal from a curator because upon signaling, curators mint a curation share for the subgraph, entitling them to a portion of future query fees that the subgraph drives. Curator signal is represented as ERC20 tokens called Graph Curation Shares (GCS). Curators that want to earn more query fees should signal their GRT to subgraphs that they predict will generate a strong flow of fees to the network. Curators cannot be slashed for bad behavior, but there is a deposit tax on Curators to disincentivize poor decision-making that could harm the integrity of the network. Curators also earn fewer query fees if they choose to curate on a low-quality Subgraph since there will be fewer queries to process or fewer Indexers to process those queries. See the diagram below! - -![Signaling diagram](/img/curator-signaling.png) - -Indexers can find subgraphs to index based on curation signals they see in The Graph Explorer (screenshot below). - -![Explorer subgraphs](/img/explorer-subgraphs.png) - -## Risks - -1. The query market is inherently young at The Graph and there is risk that your %APY may be lower than you expect due to nascent market dynamics. -2. Curation Fee - when a Curator signals GRT on a subgraph, they incur a 1% curation tax. This fee is burned and the rest is deposited into the reserve supply of the bonding curve. -3. When curators burn their shares to withdraw GRT, the GRT valuation of the remaining shares will be reduced. Be aware that in some cases, curators may decide to burn their shares **all at once**. This situation may be common if a dApp developer stops versioning/improving and querying their subgraph or if a subgraph fails. As a result, remaining curators might only be able to withdraw a fraction of their initial GRT. For a network role with a lower risk profile, see [Delegators](/network/delegating). -4. A subgraph can fail due to a bug. A failed subgraph does not accrue query fees. As a result, you’ll have to wait until the developer fixes the bug and deploys a new version. - - If you are subscribed to the newest version of a subgraph, your shares will auto-migrate to that new version. This will incur a 0.5% curation tax. - - If you have signaled on a specific subgraph version and it fails, you will have to manually burn your curation shares. Note that you may receive more or less GRT than you initially deposited into the curation curve, which is a risk associated with being a curator. You can then signal on the new subgraph version, thus incurring a 1% curation tax. - -## Curation FAQs - -### 1. What % of query fees do Curators earn? - -By signalling on a subgraph, you will earn a share of all the query fees that this subgraph generates. 10% of all query fees goes to the Curators pro-rata to their curation shares. This 10% is subject to governance. - -### 2. How do I decide which subgraphs are high quality to signal on? - -Finding high-quality subgraphs is a complex task, but it can be approached in many different ways. As a Curator, you want to look for trustworthy subgraphs that are driving query volume. A trustworthy subgraph may be valuable if it is complete, accurate, and supports a dApp’s data needs. A poorly architected subgraph might need to be revised or re-published, and can also end up failing. It is critical for Curators to review a subgraph’s architecture or code in order to assess if a subgraph is valuable. As a result: - -- Curators can use their understanding of a network to try and predict how an individual subgraph may generate a higher or lower query volume in the future -- Curators should also understand the metrics that are available through The Graph Explorer. Metrics like past query volume and who the subgraph developer is can help determine whether or not a subgraph is worth signalling on. - -### 3. What’s the cost of updating a subgraph? - -Migrating your curation shares to a new subgraph version incurs a curation tax of 1%. Curators can choose to subscribe to the newest version of a subgraph. When curation shares get auto-migrated to a new version, Curators will also pay half curation tax, ie. 0.5%, because updating subgraphs is an on-chain action that costs gas. - -### 4. How often can I update my subgraph? - -It’s suggested that you don’t update your subgraphs too frequently. See the question above for more details. - -### 5. Can I sell my curation shares? - -Curation shares cannot be "bought" or "sold" like other ERC20 tokens that you may be familiar with. They can only be minted (created) or burned (destroyed) along the bonding curve for a particular subgraph. The amount of GRT needed to mint a new signal, and the amount of GRT you receive when you burn your existing signal are determined by that bonding curve. As a Curator, you need to know that when you burn your curation shares to withdraw GRT, you can end up with more or less GRT than you initially deposited. - -Still confused? Check out our Curation video guide below: - - diff --git a/website/pages/ha/network/delegating.mdx b/website/pages/ha/network/delegating.mdx deleted file mode 100644 index 4a6d6e00b73e..000000000000 --- a/website/pages/ha/network/delegating.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Delegating ---- - -Delegators are network participants who delegate (i.e., "stake") GRT to one or more Indexers. Delegators contribute to securing the network without running a Graph Node themselves. - -By delegating to an Indexer, Delegators earn a portion of the Indexer's query fees and rewards. The amount of queries an Indexer can process depends on the Indexer's own (and delegated) stake and the price the Indexer charges for each query, so the more stake that is allocated to an Indexer, the more potential queries they can process. - -## Delegator Guide - -This guide will explain how to be an effective Delegator in the Graph Network. Delegators share earnings of the protocol alongside all Indexers based on their delegated stake. A Delegator must use their best judgment to choose Indexers based on multiple factors. Please note this guide will not go over steps such as setting up Metamask properly, as that information is widely available on the internet. There are three sections in this guide: - -- The risks of delegating tokens in The Graph Network -- How to calculate expected returns as a Delegator -- A video guide showing the steps to delegate in the Graph Network UI - -## Delegation Risks - -Listed below are the main risks of being a Delegator in the protocol. - -### The delegation tax - -Delegators cannot be slashed for bad behavior, but there is a tax on Delegators to disincentivize poor decision-making that could harm the integrity of the network. - -It is important to understand that every time you delegate, you will be charged 0.5%. This means if you are delegating 1000 GRT, you will automatically burn 5 GRT. - -This means that to be safe, a Delegator should calculate what their return will be by delegating to an Indexer. For example, a Delegator might calculate how many days it will take before they have earned back the 0.5% tax on their delegation. - -### The delegation unbonding period - -Whenever a Delegator wants to undelegate, their tokens are subject to a 28-day unbonding period. This means they cannot transfer their tokens, or earn any rewards for 28 days. - -One thing to consider as well is choosing an Indexer wisely. If you choose an Indexer who was not trustworthy, or not doing a good job, you will want to undelegate, which means you will be losing a lot of opportunities to earn rewards, which can be just as bad as burning GRT. - -
- ![Delegation unbonding](/img/Delegation-Unbonding.png) _Note the 0.5% fee in the Delegation UI, as well as the 28 day - unbonding period._ -
- -### Choosing a trustworthy Indexer with a fair reward payout for Delegators - -This is an important part to understand. First let's discuss three very important values, which are the Delegation Parameters. - -Indexing Reward Cut - The indexing reward cut is the portion of the rewards that the Indexer will keep for themselves. That means if it is set to 100%, as a Delegator you will get 0 indexing rewards. If you see 80% in the UI, that means as a Delegator, you will receive 20%. An important note - at the beginning of the network, Indexing Rewards will account for the majority of the rewards. - -
- ![Indexing Reward Cut](/img/Indexing-Reward-Cut.png) *The top Indexer is giving Delegators 90% of the rewards. The - middle one is giving Delegators 20%. The bottom one is giving Delegators ~83%.* -
- -- Query Fee Cut - This works exactly like the Indexing Reward Cut. However, this is specifically for returns on the query fees the Indexer collects. It should be noted that at the start of the network, returns from query fees will be very small compared to the indexing reward. It is recommended to pay attention to the network to determine when the query fees in the network will start to be more significant. - -As you can see, there is a lot of thought that must go into choosing the right Indexer. This is why we highly recommend you explore The Graph Discord to determine who the Indexers are with the best social reputation, and technical reputation, to reward Delegators consistently. Many of the Indexers are very active in Discord and will be happy to answer your questions. Many of them have been Indexing for months in the testnet, and are doing their best to help Delegators earn a good return, as it improves the health and success of the network. - -### Calculating Delegators expected return - -A Delegator has to consider a lot of factors when determining the return. These include: - -- A technical Delegator can also look at the Indexer's ability to use the Delegated tokens available to them. If an Indexer is not allocating all the tokens available, they are not earning the maximum profit they could be for themselves or their Delegators. -- Right now in the network an Indexer can choose to close an allocation and collect rewards anytime between 1 and 28 days. So it is possible that an Indexer has a lot of rewards they have not collected yet, and thus, their total rewards are low. This should be taken into consideration in the early days. - -### Considering the query fee cut and indexing fee cut - -As described in the above sections, you should choose an Indexer that is transparent and honest about setting their Query Fee Cut and Indexing Fee Cuts. A Delegator should also look at the Parameters Cooldown time to see how much of a time buffer they have. After that is done, it is fairly simple to calculate the amount of rewards the Delegators are getting. The formula is: - -![Delegation Image 3](/img/Delegation-Reward-Formula.png) - -### Considering the Indexer's delegation pool - -Another thing a Delegator has to consider is what proportion of the Delegation Pool they own. All delegation rewards are shared evenly, with a simple rebalancing of the pool determined by the amount the Delegator has deposited into the pool. This gives the Delegator a share of the pool: - -![Share formula](/img/Share-Forumla.png) - -Using this formula, we can see that it is actually possible for an Indexer who is offering only 20% to Delegators, to actually be giving Delegators an even better reward than an Indexer who is giving 90% to Delegators. - -A Delegator can therefore do the math to determine that the Indexer offering 20% to Delegators, is offering a better return. - -### Considering the delegation capacity - -Another thing to consider is the delegation capacity. Currently, the Delegation Ratio is set to 16. This means that if an Indexer has staked 1,000,000 GRT, their Delegation Capacity is 16,000,000 GRT of Delegated tokens that they can use in the protocol. Any delegated tokens over this amount will dilute all the Delegator rewards. - -Imagine an Indexer has 100,000,000 GRT delegated to them, and their capacity is only 16,000,000 GRT. This means effectively, 84,000,000 GRT tokens are not being used to earn tokens. And all the Delegators, and the Indexer, are earning way less rewards than they could be. - -Therefore a Delegator should always consider the Delegation Capacity of an Indexer, and factor it into their decision making. - -## Delegator FAQs and Bugs - -### MetaMask "Pending Transaction" Bug - -**When I try to delegate my transaction in MetaMask appears as "Pending" or "Queued" for longer than expected. What should I do?** - -At times, attempts to delegate to indexers via MetaMask can fail and result in prolonged periods of "Pending" or "Queued" transaction attempts. For example, a user may attempt to delegate with an insufficient gas fee relative to the current prices, resulting in the transaction attempt displaying as "Pending" in their MetaMask wallet for 15+ minutes. When this occurs, subsequent transactions can be attempted by a user, but these will not be processed until the initial transaction is mined, as transactions for an address must be processed in order. In such cases, these transactions can be cancelled in MetaMask, but the transactions attempts will accrue gas fees without any guarantee that subsequent attempts will be successful. A simpler resolution to this bug is restarting the browsesr (e.g., using "abort:restart" in the address bar), which will cancel all previous attempts without gas being subtracted from the wallet. Several users that have encountered this issue and have reported successful transactions after restarting their browser and attempting to delegate. - -## Video guide for the network UI - -This guide provides a full review of this document, and how to consider everything in this document while interacting with the UI. - - diff --git a/website/pages/ha/network/developing.mdx b/website/pages/ha/network/developing.mdx deleted file mode 100644 index 9c543348259d..000000000000 --- a/website/pages/ha/network/developing.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Developing ---- - -Developers are the demand side of The Graph ecosystem. Developers build subgraphs and publish them to The Graph Network. Then, they query live subgraphs with GraphQL in order to power their applications. - -## Subgraph Lifecycle - -Subgraphs deployed to the network have a defined lifecycle. - -### Build locally - -As with all subgraph development, it starts with local development and testing. Developers can use the same local setup whether they are building for The Graph Network, the hosted service or a local Graph Node, leveraging `graph-cli` and `graph-ts` to build their subgraph. Developers are encouraged to use tools such as [Matchstick](https://github.com/LimeChain/matchstick) for unit testing to improve the robustness of their subgraphs. - -> There are certain constraints on The Graph Network, in terms of feature and network support. Only subgraphs on [supported networks](/developing/supported-networks) will earn indexing rewards, and subgraphs which fetch data from IPFS are also not eligible. - -### Deploy to the Subgraph Studio - -Once defined, the subgraph can be built and deployed to the [Subgraph Studio](https://thegraph.com/docs/en/deploying/subgraph-studio-faqs/). The Subgraph Studio is a sandbox environment which will index the deployed subgraph and make it available for rate-limited development and testing. This gives developers an opportunity to verify that their subgraph does not encounter any indexing errors, and works as expected. - -### Publish to the Network - -When the developer is happy with their subgraph, they can publish it to The Graph Network. This is an on-chain action, which registers the subgraph so that it is discoverable by Indexers. Published subgraphs have a corresponding NFT, which is then easily transferable. The published subgraph has associated metadata, which provides other network participants with useful context and information. - -### Signal to Encourage Indexing - -Published subgraphs are unlikely to be picked up by Indexers without the addition of signal. Signal is locked GRT associated with a given subgraph, which indicates to Indexers that a given subgraph will receive query volume, and also contributes to the indexing rewards available for processing it. Subgraph developers will generally add signal to their subgraph, in order to encourage indexing. Third party Curators may also signal on a given subgraph, if they deem the subgraph likely to drive query volume. - -### Querying & Application Development - -Once a subgraph has been processed by Indexers and is available for querying, developers can start to use the subgraph in their applications. Developers query subgraphs via a gateway, which forwards their queries to an Indexer who has processed the subgraph, paying query fees in GRT. - -In order to make queries, developers must generate an API key, which can be done in the Subgraph Studio. This API key must be funded with GRT, in order to pay query fees. Developers can set a maximum query fee, in order to control their costs, and limit their API key to a given subgraph or origin domain. The Subgraph Studio provides developers with data on their API key usage over time. - -Developers are also able to express an Indexer preference to the gateway, for example preferring Indexers whose query response is faster, or whose data is most up to date. These controls are set in the Subgraph Studio. - -### Updating Subgraphs - -After a time a subgraph developer may want to update their subgraph, perhaps fixing a bug or adding new functionality. The subgraph developer may deploy new version(s) of their subgraph to the Subgraph Studio for rate-limited development and testing. - -Once the Subgraph Developer is ready to update, they can initiate a transaction to point their subgraph at the new version. Updating the subgraph migrates any signal to the new version (assuming the user who applied the signal selected "auto-migrate"), which also incurs a migration tax. This signal migration should prompt Indexers to start indexing the new version of the subgraph, so it should soon become available for querying. - -### Deprecating Subgraphs - -At some point a developer may decide that they no longer need a published subgraph. At that point they may deprecate the subgraph, which returns any signalled GRT to the Curators. - -### Diverse Developer Roles - -Some developers will engage with the full subgraph lifecycle on the network, publishing, querying and iterating on their own subgraphs. Some may be focused on subgraph development, building open APIs which others can build on. Some may be application focused, querying subgraphs deployed by others. - -### Developers and Network Economics - -Developers are a key economic actor in the network, locking up GRT in order to encourage indexing, and crucially querying subgraphs, which is the network's primary value exchange. Subgraph developers also burn GRT whenever a subgraph is updated. diff --git a/website/pages/ha/network/explorer.mdx b/website/pages/ha/network/explorer.mdx deleted file mode 100644 index b3a549900b83..000000000000 --- a/website/pages/ha/network/explorer.mdx +++ /dev/null @@ -1,203 +0,0 @@ ---- -title: Graph Explorer ---- - -Welcome to the Graph Explorer, or as we like to call it, your decentralized portal into the world of subgraphs and network data. 👩🏽‍🚀 The Graph Explorer consists of multiple parts where you can interact with other subgraph developers, dapp developers, Curators, Indexers, and Delegators. For a general overview of the Graph Explorer, check out the video below (or keep reading below): - - - -## Subgraphs - -First things first, if you just finished deploying and publishing your subgraph in the Subgraph Studio, the Subgraphs tab on the top of the navigation bar is the place to view your own finished subgraphs (and the subgraphs of others) on the decentralized network. Here, you’ll be able to find the exact subgraph you’re looking for based on the date created, signal amount, or name. - -![Explorer Image 1](/img/Subgraphs-Explorer-Landing.png) - -When you click into a subgraph, you’ll be able to test queries in the playground and be able to leverage network details to make informed decisions. You’ll also be able to signal GRT on your own subgraph or the subgraphs of others to make indexers aware of its importance and quality. This is critical because signaling on a subgraph incentivizes it to be indexed, which means that it’ll surface on the network to eventually serve queries. - -![Explorer Image 2](/img/Subgraph-Details.png) - -On each subgraph’s dedicated page, several details are surfaced. These include: - -- Signal/Un-signal on subgraphs -- View more details such as charts, current deployment ID, and other metadata -- Switch versions to explore past iterations of the subgraph -- Query subgraphs via GraphQL -- Test subgraphs in the playground -- View the Indexers that are indexing on a certain subgraph -- Subgraph stats (allocations, Curators, etc) -- View the entity who published the subgraph - -![Explorer Image 3](/img/Explorer-Signal-Unsignal.png) - -## Participants - -Within this tab, you’ll get a bird’s eye view of all the people that are participating in the network activities, such as Indexers, Delegators, and Curators. Below, we’ll go into an in-depth review of what each tab means for you. - -### 1. Indexers - -![Explorer Image 4](/img/Indexer-Pane.png) - -Let’s start with the Indexers. Indexers are the backbone of the protocol, being the ones that stake on subgraphs, index them, and serve queries to anyone consuming subgraphs. In the Indexers table, you’ll be able to see an Indexers’ delegation parameters, their stake, how much they have staked to each subgraph, and how much revenue they have made off of query fees and indexing rewards. Deep dives below: - -- Query Fee Cut - the % of the query fee rebates that the Indexer keeps when splitting with Delegators -- Effective Reward Cut - the indexing reward cut applied to the delegation pool. If it’s negative, it means that the Indexer is giving away part of their rewards. If it’s positive, it means that the Indexer is keeping some of their rewards -- Cooldown Remaining - the time remaining until the Indexer can change the above delegation parameters. Cooldown periods are set up by Indexers when they update their delegation parameters -- Owned - This is the Indexer’s deposited stake, which may be slashed for malicious or incorrect behavior -- Delegated - Stake from Delegators which can be allocated by the Indexer, but cannot be slashed -- Allocated - Stake that Indexers are actively allocating towards the subgraphs they are indexing -- Available Delegation Capacity - the amount of delegated stake the Indexers can still receive before they become over-delegated -- Max Delegation Capacity - the maximum amount of delegated stake the Indexer can productively accept. An excess delegated stake cannot be used for allocations or rewards calculations. -- Query Fees - this is the total fees that end users have paid for queries from an Indexer over all time -- Indexer Rewards - this is the total indexer rewards earned by the Indexer and their Delegators over all time. Indexer rewards are paid through GRT issuance. - -Indexers can earn both query fees and indexing rewards. Functionally, this happens when network participants delegate GRT to an Indexer. This enables Indexers to receive query fees and rewards depending on their Indexer parameters. Indexing parameters are set by clicking on the right-hand side of the table, or by going into an Indexer’s profile and clicking the “Delegate” button. - -To learn more about how to become an Indexer, you can take a look at the [official documentation](/network/indexing) or [The Graph Academy Indexer guides.](https://thegraph.academy/delegators/choosing-indexers/) - -![Indexing details pane](/img/Indexing-Details-Pane.png) - -### 2. Curators - -Curators analyze subgraphs to identify which subgraphs are of the highest quality. Once a Curator has found a potentially attractive subgraph, they can curate it by signaling on its bonding curve. In doing so, Curators let Indexers know which subgraphs are high quality and should be indexed. - -Curators can be community members, data consumers, or even subgraph developers who signal on their own subgraphs by depositing GRT tokens into a bonding curve. By depositing GRT, Curators mint curation shares of a subgraph. As a result, Curators are eligible to earn a portion of the query fees that the subgraph they have signaled on generates. The bonding curve incentivizes Curators to curate the highest quality data sources. The Curator table in this section will allow you to see: - -- The date the Curator started curating -- The number of GRT that was deposited -- The number of shares a Curator owns - -![Explorer Image 6](/img/Curation-Overview.png) - -If you want to learn more about the Curator role, you can do so by visiting the following links of [The Graph Academy](https://thegraph.academy/curators/) or [official documentation.](/network/curating) - -### 3. Delegators - -Delegators play a key role in maintaining the security and decentralization of The Graph Network. They participate in the network by delegating (i.e., “staking”) GRT tokens to one or multiple indexers. Without Delegators, Indexers are less likely to earn significant rewards and fees. Therefore, Indexers seek to attract Delegators by offering them a portion of the indexing rewards and query fees that they earn. - -Delegators, in turn, select Indexers based on a number of different variables, such as past performance, indexing reward rates, and query fee cuts. Reputation within the community can also play a factor in this! It’s recommended to connect with the indexers selected via [The Graph’s Discord](https://discord.gg/graphprotocol) or [The Graph Forum](https://forum.thegraph.com/)! - -![Explorer Image 7](/img/Delegation-Overview.png) - -The Delegators table will allow you to see the active Delegators in the community, as well as metrics such as: - -- The number of Indexers a Delegator is delegating towards -- A Delegator’s original delegation -- The rewards they have accumulated but have not withdrawn from the protocol -- The realized rewards they withdrew from the protocol -- Total amount of GRT they have currently in the protocol -- The date they last delegated at - -If you want to learn more about how to become a Delegator, look no further! All you have to do is to head over to the [official documentation](/network/delegating) or [The Graph Academy](https://docs.thegraph.academy/official-docs/delegator/choosing-indexers). - -## Network - -In the Network section, you will see global KPIs as well as the ability to switch to a per-epoch basis and analyze network metrics in more detail. These details will give you a sense of how the network is performing over time. - -### Activity - -The activity section has all the current network metrics as well as some cumulative metrics over time. Here you can see things like: - -- The current total network stake -- The stake split between the Indexers and their Delegators -- Total supply, minted, and burned GRT since the network inception -- Total Indexing rewards since the inception of the protocol -- Protocol parameters such as curation reward, inflation rate, and more -- Current epoch rewards and fees - -A few key details that are worth mentioning: - -- **Query fees represent the fees generated by the consumers**, and they can be claimed (or not) by the Indexers after a period of at least 7 epochs (see below) after their allocations towards the subgraphs have been closed and the data they served has been validated by the consumers. -- **Indexing rewards represent the amount of rewards the Indexers claimed from the network issuance during the epoch.** Although the protocol issuance is fixed, the rewards only get minted once the Indexers close their allocations towards the subgraphs they’ve been indexing. Thus the per-epoch number of rewards varies (ie. during some epochs, Indexers might’ve collectively closed allocations that have been open for many days). - -![Explorer Image 8](/img/Network-Stats.png) - -### Epochs - -In the Epochs section, you can analyze on a per-epoch basis, metrics such as: - -- Epoch start or end block -- Query fees generated and indexing rewards collected during a specific epoch -- Epoch status, which refers to the query fee collection and distribution and can have different states: - - The active epoch is the one in which Indexers are currently allocating stake and collecting query fees - - The settling epochs are the ones in which the state channels are being settled. This means that the Indexers are subject to slashing if the consumers open disputes against them. - - The distributing epochs are the epochs in which the state channels for the epochs are being settled and Indexers can claim their query fee rebates. - - The finalized epochs are the epochs that have no query fee rebates left to claim by the Indexers, thus being finalized. - -![Explorer Image 9](/img/Epoch-Stats.png) - -## Your User Profile - -Now that we’ve talked about the network stats, let’s move on to your personal profile. Your personal profile is the place for you to see your network activity, no matter how you’re participating on the network. Your crypto wallet will act as your user profile, and with the User Dashboard, you’ll be able to see: - -### Profile Overview - -This is where you can see any current actions you took. This is also where you can find your profile information, description, and website (if you added one). - -![Explorer Image 10](/img/Profile-Overview.png) - -### Subgraphs Tab - -If you click into the Subgraphs tab, you’ll see your published subgraphs. This will not include any subgraphs deployed with the CLI for testing purposes – subgraphs will only show up when they are published to the decentralized network. - -![Explorer Image 11](/img/Subgraphs-Overview.png) - -### Indexing Tab - -If you click into the Indexing tab, you’ll find a table with all the active and historical allocations towards the subgraphs, as well as charts that you can analyze and see your past performance as an Indexer. - -This section will also include details about your net Indexer rewards and net query fees. You’ll see the following metrics: - -- Delegated Stake - the stake from Delegators that can be allocated by you but cannot be slashed -- Total Query Fees - the total fees that users have paid for queries served by you over time -- Indexer Rewards - the total amount of Indexer rewards you have received, in GRT -- Fee Cut - the % of query fee rebates that you will keep when you split with Delegators -- Rewards Cut - the % of Indexer rewards that you will keep when splitting with Delegators -- Owned - your deposited stake, which could be slashed for malicious or incorrect behavior - -![Explorer Image 12](/img/Indexer-Stats.png) - -### Delegating Tab - -Delegators are important to the Graph Network. A Delegator must use their knowledge to choose an Indexer that will provide a healthy return on rewards. Here you can find details of your active and historical delegations, along with the metrics of the Indexers that you delegated towards. - -In the first half of the page, you can see your delegation chart, as well as the rewards-only chart. To the left, you can see the KPIs that reflect your current delegation metrics. - -The Delegator metrics you’ll see here in this tab include: - -- Total delegation rewards -- Total unrealized rewards -- Total realized rewards - -In the second half of the page, you have the delegations table. Here you can see the Indexers that you delegated towards, as well as their details (such as rewards cuts, cooldown, etc). - -With the buttons on the right side of the table, you can manage your delegation - delegate more, undelegate, or withdraw your delegation after the thawing period. - -Keep in mind that this chart is horizontally scrollable, so if you scroll all the way to the right, you can also see the status of your delegation (delegating, undelegating, withdrawable). - -![Explorer Image 13](/img/Delegation-Stats.png) - -### Curating Tab - -In the Curation tab, you’ll find all the subgraphs you’re signaling on (thus enabling you to receive query fees). Signaling allows Curators to highlight to Indexers which subgraphs are valuable and trustworthy, thus signaling that they need to be indexed on. - -Within this tab, you’ll find an overview of: - -- All the subgraphs you're curating on with signal details -- Share totals per subgraph -- Query rewards per subgraph -- Updated at date details - -![Explorer Image 14](/img/Curation-Stats.png) - -## Your Profile Settings - -Within your user profile, you’ll be able to manage your personal profile details (like setting up an ENS name). If you’re an Indexer, you have even more access to settings at your fingertips. In your user profile, you’ll be able to set up your delegation parameters and operators. - -- Operators take limited actions in the protocol on the Indexer's behalf, such as opening and closing allocations. Operators are typically other Ethereum addresses, separate from their staking wallet, with gated access to the network that Indexers can personally set -- Delegation parameters allow you to control the distribution of GRT between you and your Delegators. - -![Explorer Image 15](/img/Profile-Settings.png) - -As your official portal into the world of decentralized data, The Graph Explorer allows you to take a variety of actions, no matter your role in the network. You can get to your profile settings by opening the dropdown menu next to your address, then clicking on the Settings button. - -
![Wallet details](/img/Wallet-Details.png)
diff --git a/website/pages/ha/network/indexing.mdx b/website/pages/ha/network/indexing.mdx deleted file mode 100644 index 9bdc2fb2eb7e..000000000000 --- a/website/pages/ha/network/indexing.mdx +++ /dev/null @@ -1,801 +0,0 @@ ---- -title: Indexing ---- - -Indexers are node operators in The Graph Network that stake Graph Tokens (GRT) in order to provide indexing and query processing services. Indexers earn query fees and indexing rewards for their services. They also earn query fees that are rebated according to an exponential rebate function. - -GRT that is staked in the protocol is subject to a thawing period and can be slashed if Indexers are malicious and serve incorrect data to applications or if they index incorrectly. Indexers also earn rewards for delegated stake from Delegators, to contribute to the network. - -Indexers select subgraphs to index based on the subgraph’s curation signal, where Curators stake GRT in order to indicate which subgraphs are high-quality and should be prioritized. Consumers (eg. applications) can also set parameters for which Indexers process queries for their subgraphs and set preferences for query fee pricing. - - - -## FAQ - -### What is the minimum stake required to be an Indexer on the network? - -The minimum stake for an Indexer is currently set to 100K GRT. - -### What are the revenue streams for an Indexer? - -**Query fee rebates** - Payments for serving queries on the network. These payments are mediated via state channels between an Indexer and a gateway. Each query request from a gateway contains a payment and the corresponding response a proof of query result validity. - -**Indexing rewards** - Generated via a 3% annual protocol wide inflation, the indexing rewards are distributed to Indexers who are indexing subgraph deployments for the network. - -### How are indexing rewards distributed? - -Indexing rewards come from protocol inflation which is set to 3% annual issuance. They are distributed across subgraphs based on the proportion of all curation signal on each, then distributed proportionally to Indexers based on their allocated stake on that subgraph. **An allocation must be closed with a valid proof of indexing (POI) that meets the standards set by the arbitration charter in order to be eligible for rewards.** - -Numerous tools have been created by the community for calculating rewards; you'll find a collection of them organized in the [Community Guides collection](https://www.notion.so/Community-Guides-abbb10f4dba040d5ba81648ca093e70c). You can also find an up to date list of tools in the #Delegators and #Indexers channels on the [Discord server](https://discord.gg/graphprotocol). Here we link a [recommended allocation optimiser](https://github.com/graphprotocol/AllocationOpt.jl) integrated with the indexer software stack. - -### What is a proof of indexing (POI)? - -POIs are used in the network to verify that an Indexer is indexing the subgraphs they have allocated on. A POI for the first block of the current epoch must be submitted when closing an allocation for that allocation to be eligible for indexing rewards. A POI for a block is a digest for all entity store transactions for a specific subgraph deployment up to and including that block. - -### When are indexing rewards distributed? - -Allocations are continuously accruing rewards while they're active and allocated within 28 epochs. Rewards are collected by the Indexers, and distributed whenever their allocations are closed. That happens either manually, whenever the Indexer wants to force close them, or after 28 epochs a Delegator can close the allocation for the Indexer, but this results in no rewards. 28 epochs is the max allocation lifetime (right now, one epoch lasts for ~24h). - -### Can pending indexing rewards be monitored? - -The RewardsManager contract has a read-only [getRewards](https://github.com/graphprotocol/contracts/blob/master/contracts/rewards/RewardsManager.sol#L317) function that can be used to check the pending rewards for a specific allocation. - -Many of the community-made dashboards include pending rewards values and they can be easily checked manually by following these steps: - -1. Query the [mainnet subgraph](https://thegraph.com/hosted-service/subgraph/graphprotocol/graph-network-mainnet) to get the IDs for all active allocations: - -```graphql -query indexerAllocations { - indexer(id: "") { - allocations { - activeForIndexer { - allocations { - id - } - } - } - } -} -``` - -Use Etherscan to call `getRewards()`: - -- Navigate to [Etherscan interface to Rewards contract](https://etherscan.io/address/0x9Ac758AB77733b4150A901ebd659cbF8cB93ED66#readProxyContract) - -* To call `getRewards()`: - - Expand the **10. getRewards** dropdown. - - Enter the **allocationID** in the input. - - Click the **Query** button. - -### What are disputes and where can I view them? - -Indexer's queries and allocations can both be disputed on The Graph during the dispute period. The dispute period varies, depending on the type of dispute. Queries/attestations have 7 epochs dispute window, whereas allocations have 56 epochs. After these periods pass, disputes cannot be opened against either of allocations or queries. When a dispute is opened, a deposit of a minimum of 10,000 GRT is required by the Fishermen, which will be locked until the dispute is finalized and a resolution has been given. Fisherman are any network participants that open disputes. - -Disputes have **three** possible outcomes, so does the deposit of the Fishermen. - -- If the dispute is rejected, the GRT deposited by the Fishermen will be burned, and the disputed Indexer will not be slashed. -- If the dispute is settled as a draw, the Fishermen's deposit will be returned, and the disputed Indexer will not be slashed. -- If the dispute is accepted, the GRT deposited by the Fishermen will be returned, the disputed Indexer will be slashed and the Fishermen will earn 50% of the slashed GRT. - -Disputes can be viewed in the UI in an Indexer's profile page under the `Disputes` tab. - -### What are query fee rebates and when are they distributed? - -Query fees are collected by the gateway and distributed to indexers according to the exponential rebate function (see GIP [here](https://forum.thegraph.com/t/gip-0051-exponential-query-fee-rebates-for-indexers/4162)). The exponential rebate function is proposed as a way to ensure indexers achieve the best outcome by faithfully serving queries. It works by incentivizing Indexers to allocate a large amount of stake (which can be slashed for erring when serving a query) relative to the amount of query fees they may collect. - -Once an allocation has been closed the rebates are available to be claimed by the Indexer. Upon claiming, the query fee rebates are distributed to the Indexer and their Delegators based on the query fee cut and the exponential rebate function. - -### What is query fee cut and indexing reward cut? - -The `queryFeeCut` and `indexingRewardCut` values are delegation parameters that the Indexer may set along with cooldownBlocks to control the distribution of GRT between the Indexer and their Delegators. See the last steps in [Staking in the Protocol](/network/indexing#stake-in-the-protocol) for instructions on setting the delegation parameters. - -- **queryFeeCut** - the % of query fee rebates that will be distributed to the Indexer. If this is set to 95%, the Indexer will receive 95% of the query fees earned when an allocation is closed with the other 5% going to the Delegators. - -- **indexingRewardCut** - the % of indexing rewards that will be distributed to the Indexer. If this is set to 95%, the Indexer will receive 95% of the indexing rewards when an allocation is closed and the Delegators will split the other 5%. - -### How do Indexers know which subgraphs to index? - -Indexers may differentiate themselves by applying advanced techniques for making subgraph indexing decisions but to give a general idea we'll discuss several key metrics used to evaluate subgraphs in the network: - -- **Curation signal** - The proportion of network curation signal applied to a particular subgraph is a good indicator of the interest in that subgraph, especially during the bootstrap phase when query voluming is ramping up. - -- **Query fees collected** - The historical data for volume of query fees collected for a specific subgraph is a good indicator of future demand. - -- **Amount staked** - Monitoring the behavior of other Indexers or looking at proportions of total stake allocated towards specific subgraphs can allow an Indexer to monitor the supply side for subgraph queries to identify subgraphs that the network is showing confidence in or subgraphs that may show a need for more supply. - -- **Subgraphs with no indexing rewards** - Some subgraphs do not generate indexing rewards mainly because they are using unsupported features like IPFS or because they are querying another network outside of mainnet. You will see a message on a subgraph if it is not generating indexing rewards. - -### What are the hardware requirements? - -- **Small** - Enough to get started indexing several subgraphs, will likely need to be expanded. -- **Standard** - Default setup, this is what is used in the example k8s/terraform deployment manifests. -- **Medium** - Production Indexer supporting 100 subgraphs and 200-500 requests per second. -- **Large** - Prepared to index all currently used subgraphs and serve requests for the related traffic. - -| Setup | Postgres
(CPUs) | Postgres
(memory in GBs) | Postgres
(disk in TBs) | VMs
(CPUs) | VMs
(memory in GBs) | -| --- | :-: | :-: | :-: | :-: | :-: | -| Small | 4 | 8 | 1 | 4 | 16 | -| Standard | 8 | 30 | 1 | 12 | 48 | -| Medium | 16 | 64 | 2 | 32 | 64 | -| Large | 72 | 468 | 3.5 | 48 | 184 | - -### What are some basic security precautions an Indexer should take? - -- **Operator wallet** - Setting up an operator wallet is an important precaution because it allows an Indexer to maintain separation between their keys that control stake and those that are in control of day-to-day operations. See [Stake in Protocol](/network/indexing#stake-in-the-protocol) for instructions. - -- **Firewall** - Only the Indexer service needs to be exposed publicly and particular attention should be paid to locking down admin ports and database access: the Graph Node JSON-RPC endpoint (default port: 8030), the Indexer management API endpoint (default port: 18000), and the Postgres database endpoint (default port: 5432) should not be exposed. - -## Infrastructure - -At the center of an Indexer's infrastructure is the Graph Node which monitors the indexed networks, extracts and loads data per a subgraph definition and serves it as a [GraphQL API](/about/#how-the-graph-works). The Graph Node needs to be connected to an endpoint exposing data from each indexed network; an IPFS node for sourcing data; a PostgreSQL database for its store; and Indexer components which facilitate its interactions with the network. - -- **PostgreSQL database** - The main store for the Graph Node, this is where subgraph data is stored. The Indexer service and agent also use the database to store state channel data, cost models, indexing rules, and allocation actions. - -- **Data endpoint** - For EVM-compatible networks, Graph Node needs to be connected to an endpoint that exposes an EVM-compatible JSON-RPC API. This may take the form of a single client or it could be a more complex setup that load balances across multiple. It's important to be aware that certain subgraphs will require particular client capabilities such as archive mode and/or the parity tracing API. - -- **IPFS node (version less than 5)** - Subgraph deployment metadata is stored on the IPFS network. The Graph Node primarily accesses the IPFS node during subgraph deployment to fetch the subgraph manifest and all linked files. Network Indexers do not need to host their own IPFS node, an IPFS node for the network is hosted at https://ipfs.network.thegraph.com. - -- **Indexer service** - Handles all required external communications with the network. Shares cost models and indexing statuses, passes query requests from gateways on to a Graph Node, and manages the query payments via state channels with the gateway. - -- **Indexer agent** - Facilitates the Indexers interactions on chain including registering on the network, managing subgraph deployments to its Graph Node/s, and managing allocations. - -- **Prometheus metrics server** - The Graph Node and Indexer components log their metrics to the metrics server. - -Note: To support agile scaling, it is recommended that query and indexing concerns are separated between different sets of nodes: query nodes and index nodes. - -### Ports overview - -> **Important**: Be careful about exposing ports publicly - **administration ports** should be kept locked down. This includes the the Graph Node JSON-RPC and the Indexer management endpoints detailed below. - -#### Graph Node - -| Port | Purpose | Routes | CLI Argument | Environment Variable | -| --- | --- | --- | --- | --- | -| 8000 | GraphQL HTTP server
(for subgraph queries) | /subgraphs/id/...
/subgraphs/name/.../... | --http-port | - | -| 8001 | GraphQL WS
(for subgraph subscriptions) | /subgraphs/id/...
/subgraphs/name/.../... | --ws-port | - | -| 8020 | JSON-RPC
(for managing deployments) | / | --admin-port | - | -| 8030 | Subgraph indexing status API | /graphql | --index-node-port | - | -| 8040 | Prometheus metrics | /metrics | --metrics-port | - | - -#### Indexer Service - -| Port | Purpose | Routes | CLI Argument | Environment Variable | -| --- | --- | --- | --- | --- | -| 7600 | GraphQL HTTP server
(for paid subgraph queries) | /subgraphs/id/...
/status
/channel-messages-inbox | --port | `INDEXER_SERVICE_PORT` | -| 7300 | Prometheus metrics | /metrics | --metrics-port | - | - -#### Indexer Agent - -| Port | Purpose | Routes | CLI Argument | Environment Variable | -| ---- | ---------------------- | ------ | ------------------------- | --------------------------------------- | -| 8000 | Indexer management API | / | --indexer-management-port | `INDEXER_AGENT_INDEXER_MANAGEMENT_PORT` | - -### Setup server infrastructure using Terraform on Google Cloud - -> Note: Indexers can alternatively use AWS, Microsoft Azure, or Alibaba. - -#### Install prerequisites - -- Google Cloud SDK -- Kubectl command line tool -- Terraform - -#### Create a Google Cloud Project - -- Clone or navigate to the Indexer repository. - -- Navigate to the ./terraform directory, this is where all commands should be executed. - -```sh -cd terraform -``` - -- Authenticate with Google Cloud and create a new project. - -```sh -gcloud auth login -project= -gcloud projects create --enable-cloud-apis $project -``` - -- Use the Google Cloud Console's billing page to enable billing for the new project. - -- Create a Google Cloud configuration. - -```sh -proj_id=$(gcloud projects list --format='get(project_id)' --filter="name=$project") -gcloud config configurations create $project -gcloud config set project "$proj_id" -gcloud config set compute/region us-central1 -gcloud config set compute/zone us-central1-a -``` - -- Enable required Google Cloud APIs. - -```sh -gcloud services enable compute.googleapis.com -gcloud services enable container.googleapis.com -gcloud services enable servicenetworking.googleapis.com -gcloud services enable sqladmin.googleapis.com -``` - -- Create a service account. - -```sh -svc_name= -gcloud iam service-accounts create $svc_name \ - --description="Service account for Terraform" \ - --display-name="$svc_name" -gcloud iam service-accounts list -# Get the email of the service account from the list -svc=$(gcloud iam service-accounts list --format='get(email)' ---filter="displayName=$svc_name") -gcloud iam service-accounts keys create .gcloud-credentials.json \ - --iam-account="$svc" -gcloud projects add-iam-policy-binding $proj_id \ - --member serviceAccount:$svc \ - --role roles/editor -``` - -- Enable peering between database and Kubernetes cluster that will be created in the next step. - -```sh -gcloud compute addresses create google-managed-services-default \ - --prefix-length=20 \ - --purpose=VPC_PEERING \ - --network default \ - --global \ - --description 'IP Range for peer networks.' -gcloud services vpc-peerings connect \ - --network=default \ - --ranges=google-managed-services-default -``` - -- Create minimal terraform configuration file (update as needed). - -```sh -indexer= -cat > terraform.tfvars < \ - -f Dockerfile.indexer-service \ - -t indexer-service:latest \ -# Indexer agent -docker build \ - --build-arg NPM_TOKEN= \ - -f Dockerfile.indexer-agent \ - -t indexer-agent:latest \ -``` - -- Run the components - -```sh -docker run -p 7600:7600 -it indexer-service:latest ... -docker run -p 18000:8000 -it indexer-agent:latest ... -``` - -**NOTE**: After starting the containers, the Indexer service should be accessible at [http://localhost:7600](http://localhost:7600) and the Indexer agent should be exposing the Indexer management API at [http://localhost:18000/](http://localhost:18000/). - -#### Using K8s and Terraform - -See the [Setup Server Infrastructure Using Terraform on Google Cloud](/network/indexing#setup-server-infrastructure-using-terraform-on-google-cloud) section - -#### Usage - -> **NOTE**: All runtime configuration variables may be applied either as parameters to the command on startup or using environment variables of the format `COMPONENT_NAME_VARIABLE_NAME`(ex. `INDEXER_AGENT_ETHEREUM`). - -#### Indexer agent - -```sh -graph-indexer-agent start \ - --ethereum \ - --ethereum-network mainnet \ - --mnemonic \ - --indexer-address \ - --graph-node-query-endpoint http://localhost:8000/ \ - --graph-node-status-endpoint http://localhost:8030/graphql \ - --graph-node-admin-endpoint http://localhost:8020/ \ - --public-indexer-url http://localhost:7600/ \ - --indexer-geo-coordinates \ - --index-node-ids default \ - --indexer-management-port 18000 \ - --metrics-port 7040 \ - --network-subgraph-endpoint https://gateway.network.thegraph.com/network \ - --default-allocation-amount 100 \ - --register true \ - --inject-dai true \ - --postgres-host localhost \ - --postgres-port 5432 \ - --postgres-username \ - --postgres-password \ - --postgres-database indexer \ - --allocation-management auto \ - | pino-pretty -``` - -#### Indexer service - -```sh -SERVER_HOST=localhost \ -SERVER_PORT=5432 \ -SERVER_DB_NAME=is_staging \ -SERVER_DB_USER= \ -SERVER_DB_PASSWORD= \ -graph-indexer-service start \ - --ethereum \ - --ethereum-network mainnet \ - --mnemonic \ - --indexer-address \ - --port 7600 \ - --metrics-port 7300 \ - --graph-node-query-endpoint http://localhost:8000/ \ - --graph-node-status-endpoint http://localhost:8030/graphql \ - --postgres-host localhost \ - --postgres-port 5432 \ - --postgres-username \ - --postgres-password \ - --postgres-database is_staging \ - --network-subgraph-endpoint https://gateway.network.thegraph.com/network \ - | pino-pretty -``` - -#### Indexer CLI - -The Indexer CLI is a plugin for [`@graphprotocol/graph-cli`](https://www.npmjs.com/package/@graphprotocol/graph-cli) accessible in the terminal at `graph indexer`. - -```sh -graph indexer connect http://localhost:18000 -graph indexer status -``` - -#### Indexer management using Indexer CLI - -The suggested tool for interacting with the **Indexer Management API** is the **Indexer CLI**, an extension to the **Graph CLI**. The Indexer agent needs input from an Indexer in order to autonomously interact with the network on the behalf of the Indexer. The mechanism for defining Indexer agent behavior are **allocation management** mode and **indexing rules**. Under auto mode, an Indexer can use **indexing rules** to apply their specific strategy for picking subgraphs to index and serve queries for. Rules are managed via a GraphQL API served by the agent and known as the Indexer Management API. Under manual mode, an Indexer can create allocation actions using **actions queue** and explicitly approve them before they get executed. Under oversight mode, **indexing rules** are used to populate **actions queue** and also require explicit approval for execution. - -#### Usage - -The **Indexer CLI** connects to the Indexer agent, typically through port-forwarding, so the CLI does not need to run on the same server or cluster. To help you get started, and to provide some context, the CLI will briefly be described here. - -- `graph indexer connect ` - Connect to the Indexer management API. Typically the connection to the server is opened via port forwarding, so the CLI can be easily operated remotely. (Example: `kubectl port-forward pod/ 8000:8000`) - -- `graph indexer rules get [options] [ ...]` - Get one or more indexing rules using `all` as the `` to get all rules, or `global` to get the global defaults. An additional argument `--merged` can be used to specify that deployment specific rules are merged with the global rule. This is how they are applied in the Indexer agent. - -- `graph indexer rules set [options] ...` - Set one or more indexing rules. - -- `graph indexer rules start [options] ` - Start indexing a subgraph deployment if available and set its `decisionBasis` to `always`, so the Indexer agent will always choose to index it. If the global rule is set to always then all available subgraphs on the network will be indexed. - -- `graph indexer rules stop [options] ` - Stop indexing a deployment and set its `decisionBasis` to never, so it will skip this deployment when deciding on deployments to index. - -- `graph indexer rules maybe [options] ` — Set the `decisionBasis` for a deployment to `rules`, so that the Indexer agent will use indexing rules to decide whether to index this deployment. - -- `graph indexer actions get [options] ` - Fetch one or more actions using `all` or leave `action-id` empty to get all actions. An additonal argument `--status` can be used to print out all actions of a certain status. - -- `graph indexer action queue allocate ` - Queue allocation action - -- `graph indexer action queue reallocate ` - Queue reallocate action - -- `graph indexer action queue unallocate ` - Queue unallocate action - -- `graph indexer actions cancel [ ...]` - Cancel all action in the queue if id is unspecified, otherwise cancel array of id with space as separator - -- `graph indexer actions approve [ ...]` - Approve multiple actions for execution - -- `graph indexer actions execute approve` - Force the worker to execute approved actions immediately - -All commands which display rules in the output can choose between the supported output formats (`table`, `yaml`, and `json`) using the `-output` argument. - -#### Indexing rules - -Indexing rules can either be applied as global defaults or for specific subgraph deployments using their IDs. The `deployment` and `decisionBasis` fields are mandatory, while all other fields are optional. When an indexing rule has `rules` as the `decisionBasis`, then the Indexer agent will compare non-null threshold values on that rule with values fetched from the network for the corresponding deployment. If the subgraph deployment has values above (or below) any of the thresholds it will be chosen for indexing. - -For example, if the global rule has a `minStake` of **5** (GRT), any subgraph deployment which has more than 5 (GRT) of stake allocated to it will be indexed. Threshold rules include `maxAllocationPercentage`, `minSignal`, `maxSignal`, `minStake`, and `minAverageQueryFees`. - -Data model: - -```graphql -type IndexingRule { - identifier: string - identifierType: IdentifierType - decisionBasis: IndexingDecisionBasis! - allocationAmount: number | null - allocationLifetime: number | null - autoRenewal: boolean - parallelAllocations: number | null - maxAllocationPercentage: number | null - minSignal: string | null - maxSignal: string | null - minStake: string | null - minAverageQueryFees: string | null - custom: string | null - requireSupported: boolean | null - } - -IdentifierType { - deployment - subgraph - group -} - -IndexingDecisionBasis { - rules - never - always - offchain -} -``` - -Example usage of indexing rule: - -``` -graph indexer rules offchain QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK - -graph indexer rules set QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK decisionBasis always allocationAmount 123321 allocationLifetime 14 autoRenewal false requireSupported false - -graph indexer rules stop QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK - -graph indexer rules delete QmZfeJYR86UARzp9HiXbURWunYgC9ywvPvoePNbuaATrEK -``` - -#### Actions queue CLI - -The indexer-cli provides an `actions` module for manually working with the action queue. It uses the **Graphql API** hosted by the indexer management server to interact with the actions queue. - -The action execution worker will only grab items from the queue to execute if they have `ActionStatus = approved`. In the recommended path actions are added to the queue with ActionStatus = queued, so they must then be approved in order to be executed on-chain. The general flow will look like: - -- Action added to the queue by the 3rd party optimizer tool or indexer-cli user -- Indexer can use the `indexer-cli` to view all queued actions -- Indexer (or other software) can approve or cancel actions in the queue using the `indexer-cli`. The approve and cancel commands take an array of action ids as input. -- The execution worker regularly polls the queue for approved actions. It will grab the `approved` actions from the queue, attempt to execute them, and update the values in the db depending on the status of execution to `success` or `failed`. -- If an action is successful the worker will ensure that there is an indexing rule present that tells the agent how to manage the allocation moving forward, useful when taking manual actions while the agent is in `auto` or `oversight` mode. -- The indexer can monitor the action queue to see a history of action execution and if needed re-approve and update action items if they failed execution. The action queue provides a history of all actions queued and taken. - -Data model: - -```graphql -Type ActionInput { - status: ActionStatus - type: ActionType - deploymentID: string | null - allocationID: string | null - amount: string | null - poi: string | null - force: boolean | null - source: string - reason: string | null - priority: number | null -} - -ActionStatus { - queued - approved - pending - success - failed - canceled -} - -ActionType { - allocate - unallocate - reallocate - collect -} -``` - -Example usage from source: - -```bash -graph indexer actions get all - -graph indexer actions get --status queued - -graph indexer actions queue allocate QmeqJ6hsdyk9dVbo1tvRgAxWrVS3rkERiEMsxzPShKLco6 5000 - -graph indexer actions queue reallocate QmeqJ6hsdyk9dVbo1tvRgAxWrVS3rkERiEMsxzPShKLco6 0x4a58d33e27d3acbaecc92c15101fbc82f47c2ae5 55000 - -graph indexer actions queue unallocate QmeqJ6hsdyk9dVbo1tvRgAxWrVS3rkERiEMsxzPShKLco6 0x4a58d33e27d3acbaecc92c15101fbc82f47c2ae - -graph indexer actions cancel - -graph indexer actions approve 1 3 5 - -graph indexer actions execute approve -``` - -Note that supported action types for allocation management have different input requirements: - -- `Allocate` - allocate stake to a specific subgraph deployment - - - required action params: - - deploymentID - - amount - -- `Unallocate` - close allocation, freeing up the stake to reallocate elsewhere - - - required action params: - - allocationID - - deploymentID - - optional action params: - - poi - - force (forces using the provided POI even if it doesn’t match what the graph-node provides) - -- `Reallocate` - atomically close allocation and open a fresh allocation for the same subgraph deployment - - - required action params: - - allocationID - - deploymentID - - amount - - optional action params: - - poi - - force (forces using the provided POI even if it doesn’t match what the graph-node provides) - -#### Cost models - -Cost models provide dynamic pricing for queries based on market and query attributes. The Indexer Service shares a cost model with the gateways for each subgraph for which they intend to respond to queries. The gateways, in turn, use the cost model to make Indexer selection decisions per query and to negotiate payment with chosen Indexers. - -#### Agora - -The Agora language provides a flexible format for declaring cost models for queries. An Agora price model is a sequence of statements that execute in order for each top-level query in a GraphQL query. For each top-level query, the first statement which matches it determines the price for that query. - -A statement is comprised of a predicate, which is used for matching GraphQL queries, and a cost expression which when evaluated outputs a cost in decimal GRT. Values in the named argument position of a query may be captured in the predicate and used in the expression. Globals may also be set and substituted in for placeholders in an expression. - -Example cost model: - -``` -# This statement captures the skip value, -# uses a boolean expression in the predicate to match specific queries that use `skip` -# and a cost expression to calculate the cost based on the `skip` value and the SYSTEM_LOAD global -query { pairs(skip: $skip) { id } } when $skip > 2000 => 0.0001 * $skip * $SYSTEM_LOAD; - -# This default will match any GraphQL expression. -# It uses a Global substituted into the expression to calculate cost -default => 0.1 * $SYSTEM_LOAD; -``` - -Example query costing using the above model: - -| Query | Price | -| ---------------------------------------------------------------------------- | ------- | -| { pairs(skip: 5000) { id } } | 0.5 GRT | -| { tokens { symbol } } | 0.1 GRT | -| { pairs(skip: 5000) { id { tokens } symbol } } | 0.6 GRT | - -#### Applying the cost model - -Cost models are applied via the Indexer CLI, which passes them to the Indexer Management API of the Indexer agent for storing in the database. The Indexer Service will then pick them up and serve the cost models to gateways whenever they ask for them. - -```sh -indexer cost set variables '{ "SYSTEM_LOAD": 1.4 }' -indexer cost set model my_model.agora -``` - -## Interacting with the network - -### Stake in the protocol - -The first steps to participating in the network as an Indexer are to approve the protocol, stake funds, and (optionally) set up an operator address for day-to-day protocol interactions. _ **Note**: For the purposes of these instructions Remix will be used for contract interaction, but feel free to use your tool of choice ([OneClickDapp](https://oneclickdapp.com/), [ABItopic](https://abitopic.io/), and [MyCrypto](https://www.mycrypto.com/account) are a few other known tools)._ - -Once an Indexer has staked GRT in the protocol, the [Indexer components](/network/indexing#indexer-components) can be started up and begin their interactions with the network. - -#### Approve tokens - -1. Open the [Remix app](https://remix.ethereum.org/) in a browser - -2. In the `File Explorer` create a file named **GraphToken.abi** with the [token ABI](https://raw.githubusercontent.com/graphprotocol/contracts/mainnet-deploy-build/build/abis/GraphToken.json). - -3. With `GraphToken.abi` selected and open in the editor, switch to the Deploy and `Run Transactions` section in the Remix interface. - -4. Under environment select `Injected Web3` and under `Account` select your Indexer address. - -5. Set the GraphToken contract address - Paste the GraphToken contract address (`0xc944E90C64B2c07662A292be6244BDf05Cda44a7`) next to `At Address` and click the `At address` button to apply. - -6. Call the `approve(spender, amount)` function to approve the Staking contract. Fill in `spender` with the Staking contract address (`0xF55041E37E12cD407ad00CE2910B8269B01263b9`) and `amount` with the tokens to stake (in wei). - -#### Stake tokens - -1. Open the [Remix app](https://remix.ethereum.org/) in a browser - -2. In the `File Explorer` create a file named **Staking.abi** with the staking ABI. - -3. With `Staking.abi` selected and open in the editor, switch to the `Deploy` and `Run Transactions` section in the Remix interface. - -4. Under environment select `Injected Web3` and under `Account` select your Indexer address. - -5. Set the Staking contract address - Paste the Staking contract address (`0xF55041E37E12cD407ad00CE2910B8269B01263b9`) next to `At Address` and click the `At address` button to apply. - -6. Call `stake()` to stake GRT in the protocol. - -7. (Optional) Indexers may approve another address to be the operator for their Indexer infrastructure in order to separate the keys that control the funds from those that are performing day to day actions such as allocating on subgraphs and serving (paid) queries. In order to set the operator call `setOperator()` with the operator address. - -8. (Optional) In order to control the distribution of rewards and strategically attract Delegators Indexers can update their delegation parameters by updating their indexingRewardCut (parts per million), queryFeeCut (parts per million), and cooldownBlocks (number of blocks). To do so call `setDelegationParameters()`. The following example sets the queryFeeCut to distribute 95% of query rebates to the Indexer and 5% to Delegators, set the indexingRewardCutto distribute 60% of indexing rewards to the Indexer and 40% to Delegators, and set `thecooldownBlocks` period to 500 blocks. - -``` -setDelegationParameters(950000, 600000, 500) -``` - -### The life of an allocation - -After being created by an Indexer a healthy allocation goes through four states. - -- **Active** - Once an allocation is created on-chain ([allocateFrom()](https://github.com/graphprotocol/contracts/blob/master/contracts/staking/Staking.sol#L873)) it is considered **active**. A portion of the Indexer's own and/or delegated stake is allocated towards a subgraph deployment, which allows them to claim indexing rewards and serve queries for that subgraph deployment. The Indexer agent manages creating allocations based on the Indexer rules. - -- **Closed** - An Indexer is free to close an allocation once 1 epoch has passed ([closeAllocation()](https://github.com/graphprotocol/contracts/blob/master/contracts/staking/Staking.sol#L873)) or their Indexer agent will automatically close the allocation after the **maxAllocationEpochs** (currently 28 days). When an allocation is closed with a valid proof of indexing (POI) their indexing rewards are distributed to the Indexer and its Delegators (see "how are rewards distributed?" below to learn more). - -Indexers are recommended to utilize offchain syncing functionality to sync subgraph deployments to chainhead before creating the allocation on-chain. This feature is especially useful for subgraphs that may take longer than 28 epochs to sync or have some chances of failing undeterministically. diff --git a/website/pages/ha/network/overview.mdx b/website/pages/ha/network/overview.mdx deleted file mode 100644 index bee546908372..000000000000 --- a/website/pages/ha/network/overview.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Network Overview ---- - -The Graph Network is a decentralized indexing protocol for organizing blockchain data. Applications use GraphQL to query open APIs called subgraphs, to retrieve data that is indexed on the network. With The Graph, developers can build serverless applications that run entirely on public infrastructure. - -## Overview - -The Graph Network consists of Indexers, Curators and Delegators that provide services to the network, and serve data to Web3 applications. Consumers use the applications and consume the data. - -![Token Economics](/img/Network-roles@2x.png) - -To ensure economic security of The Graph Network and the integrity of data being queried, participants stake and use Graph Tokens ([GRT](/tokenomics)). GRT is a work utility token that is an ERC-20 used to allocate resources in the network. - -Active Indexers, Curators and Delegators can provide services and earn income from the network, proportional to the amount of work they perform and their GRT stake. diff --git a/website/pages/ha/new-chain-integration.mdx b/website/pages/ha/new-chain-integration.mdx deleted file mode 100644 index b5492d5061af..000000000000 --- a/website/pages/ha/new-chain-integration.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Integrating New Networks ---- - -Graph Node can currently index data from the following chain types: - -- Ethereum, via EVM JSON-RPC and [Ethereum Firehose](https://github.com/streamingfast/firehose-ethereum) -- NEAR, via a [NEAR Firehose](https://github.com/streamingfast/near-firehose-indexer) -- Cosmos, via a [Cosmos Firehose](https://github.com/graphprotocol/firehose-cosmos) -- Arweave, via an [Arweave Firehose](https://github.com/graphprotocol/firehose-arweave) - -If you are interested in any of those chains, integration is a matter of Graph Node configuration and testing. - -If you are interested in a different chain type, a new with Graph Node must be built. Our recommended approach is developing a new Firehose for the chain in question and then the integration of that Firehose with Graph Node. More info below. - -**1. EVM JSON-RPC** - -If the blockchain is EVM equivalent and the client/node exposes the standard EVM JSON-RPC API, Graph Node should be able to index the new chain. For more information, refer to [Testing an EVM JSON-RPC](new-chain-integration#testing-an-evm-json-rpc). - -**2. Firehose** - -For non-EVM-based chains, Graph Node must ingest blockchain data via gRPC and known type definitions. This can be done via [Firehose](firehose/), a new technology developed by [StreamingFast](https://www.streamingfast.io/) that provides a highly-scalable indexing blockchain solution using a files-based and streaming-first approach. Reach out to the [StreamingFast team](mailto:integrations@streamingfast.io/) if you need help with Firehose development. - -## Difference between EVM JSON-RPC & Firehose - -While the two are suitable for subgraphs, a Firehose is always required for developers wanting to build with [Substreams](substreams/), like building [Substreams-powered subgraphs](cookbook/substreams-powered-subgraphs/). In addition, Firehose allows for improved indexing speeds when compared to JSON-RPC. - -New EVM chain integrators may also consider the Firehose-based approach, given the benefits of substreams and its massive parallelized indexing capabilities. Supporting both allows developers to choose between building substreams or subgraphs for the new chain. - -> **NOTE**: A Firehose-based integration for EVM chains will still require Indexers to run the chain's archive RPC node to properly index subgraphs. This is due to the Firehose's inability to provide smart contract state typically accessible by the `eth_call` RPC method. (It's worth reminding that eth_calls are [not a good practice for developers](https://thegraph.com/blog/improve-subgraph-performance-reduce-eth-calls/)) - ---- - -## Testing an EVM JSON-RPC - -For Graph Node to be able to ingest data from an EVM chain, the RPC node must expose the following EVM JSON RPC methods: - -- `eth_getLogs` -- `eth_call` \_(for historical blocks, with EIP-1898 - requires archive node): -- `eth_getBlockByNumber` -- `eth_getBlockByHash` -- `net_version` -- `eth_getTransactionReceipt`, in a JSON-RPC batch request -- _`trace_filter`_ _(optionally required for Graph Node to support call handlers)_ - -### Graph Node Configuration - -**Start by preparing your local environment** - -1. [Clone Graph Node](https://github.com/graphprotocol/graph-node) -2. Modify [this line](https://github.com/graphprotocol/graph-node/blob/master/docker/docker-compose.yml#L22) to include the new network name and the EVM JSON RPC compliant URL - > Do not change the env var name itself. It must remain `ethereum` even if the network name is different. -3. Run an IPFS node or use the one used by The Graph: https://api.thegraph.com/ipfs/ - -**Test the integration by locally deploying a subgraph** - -1. Install [graph-cli](https://github.com/graphprotocol/graph-cli) -2. Create a simple example subgraph. Some options are below: - 1. The pre-packed [Gravitar](https://github.com/graphprotocol/example-subgraph/tree/f89bdd4628efa4badae7367d4919b3f648083323) smart contract and subgraph is a good starting point - 2. Bootstrap a local subgraph from any existing smart contract or solidity dev environment [using Hardhat with a Graph plugin](https://github.com/graphprotocol/hardhat-graph) -3. Adapt the resulting `subgraph.yaml` by changing [`dataSources.network`](http://dataSources.network) to the same name previously passed on to Graph Node. -4. Create your subgraph in Graph Node: `graph create $SUBGRAPH_NAME --node $GRAPH_NODE_ENDPOINT` -5. Publish your subgraph to Graph Node: `graph deploy $SUBGRAPH_NAME --ipfs $IPFS_ENDPOINT --node $GRAPH_NODE_ENDPOINT` - -Graph Node should be syncing the deployed subgraph if there are no errors. Give it time to sync, then send some GraphQL queries to the API endpoint printed in the logs. - ---- - -## Integrating a new Firehose-enabled chain - -Integrating a new chain is also possible using the Firehose approach. This is currently the best option for non-EVM chains and a requirement for substreams support. Additional documentation focuses on how Firehose works, adding Firehose support for a new chain and integrating it with Graph Node. Recommended docs for integrators: - -1. [General docs on Firehose](firehose/) -2. [Adding Firehose support for a new chain](https://firehose.streamingfast.io/integrate-new-chains/integration-overview) -3. [Integrating Graph Node with a new chain via Firehose](https://github.com/graphprotocol/graph-node/blob/master/docs/implementation/add-chain.md) diff --git a/website/pages/ha/operating-graph-node.mdx b/website/pages/ha/operating-graph-node.mdx deleted file mode 100644 index 4f0f856db111..000000000000 --- a/website/pages/ha/operating-graph-node.mdx +++ /dev/null @@ -1,345 +0,0 @@ ---- -title: Operating Graph Node ---- - -Graph Node is the component which indexes subgraphs, and makes the resulting data available to query via a GraphQL API. As such it is central to the indexer stack, and correct operation of Graph Node is crucial to running a successful indexer. - -This provides a contextual overview of Graph Node, and some of the more advanced options available to indexers. Detailed documentation and instructions can be found in the [Graph Node repository](https://github.com/graphprotocol/graph-node). - -## Graph Node - -[Graph Node](https://github.com/graphprotocol/graph-node) is the reference implementation for indexing Subgraphs on The Graph Network, connecting to blockchain clients, indexing subgraphs and making indexed data available to query. - -Graph Node (and the whole indexer stack) can be run on bare metal, or in a cloud environment. This flexibility of the central indexing component is crucial to the robustness of The Graph Protocol. Similarly, Graph Node can be [built from source](https://github.com/graphprotocol/graph-node), or indexers can use one of the [provided Docker Images](https://hub.docker.com/r/graphprotocol/graph-node). - -### PostgreSQL database - -The main store for the Graph Node, this is where subgraph data is stored, as well as metadata about subgraphs, and subgraph-agnostic network data such as the block cache, and eth_call cache. - -### Network clients - -In order to index a network, Graph Node needs access to a network client via an EVM-compatible JSON-RPC API. This RPC may connect to a single client or it could be a more complex setup that load balances across multiple. - -While some subgraphs may just require a full node, some may have indexing features which require additional RPC functionality. Specifically subgraphs which make `eth_calls` as part of indexing will require an archive node which supports [EIP-1898](https://eips.ethereum.org/EIPS/eip-1898), and subgraphs with `callHandlers`, or `blockHandlers` with a `call` filter, require `trace_filter` support ([see trace module documentation here](https://openethereum.github.io/JSONRPC-trace-module)). - -**Network Firehoses** - a Firehose is a gRPC service providing an ordered, yet fork-aware, stream of blocks, developed by The Graph's core developers to better support performant indexing at scale. This is not currently an Indexer requirement, but Indexers are encouraged to familiarise themselves with the technology, ahead of full network support. Learn more about the Firehose [here](https://firehose.streamingfast.io/). - -### IPFS Nodes - -Subgraph deployment metadata is stored on the IPFS network. The Graph Node primarily accesses the IPFS node during subgraph deployment to fetch the subgraph manifest and all linked files. Network indexers do not need to host their own IPFS node. An IPFS node for the network is hosted at https://ipfs.network.thegraph.com. - -### Prometheus metrics server - -To enable monitoring and reporting, Graph Node can optionally log metrics to a Prometheus metrics server. - -### Getting started from source - -#### Install prerequisites - -- **Rust** - -- **PostgreSQL** - -- **IPFS** - -- **Additional Requirements for Ubuntu users** - To run a Graph Node on Ubuntu a few additional packages may be needed. - -```sh -sudo apt-get install -y clang libpg-dev libssl-dev pkg-config -``` - -#### Setup - -1. Start a PostgreSQL database server - -```sh -initdb -D .postgres -pg_ctl -D .postgres -l logfile start -createdb graph-node -``` - -2. Clone [Graph Node](https://github.com/graphprotocol/graph-node) repo and build the source by running `cargo build` - -3. Now that all the dependencies are setup, start the Graph Node: - -```sh -cargo run -p graph-node --release -- \ - --postgres-url postgresql://[USERNAME]:[PASSWORD]@localhost:5432/graph-node \ - --ethereum-rpc [NETWORK_NAME]:[URL] \ - --ipfs https://ipfs.network.thegraph.com -``` - -### Getting started with Kubernetes - -A complete Kubernetes example configuration can be found in the [indexer repository](https://github.com/graphprotocol/indexer/tree/main/k8s). - -### Ports - -When it is running Graph Node exposes the following ports: - -| Port | Purpose | Routes | CLI Argument | Environment Variable | -| --- | --- | --- | --- | --- | -| 8000 | GraphQL HTTP server
(for subgraph queries) | /subgraphs/id/...
/subgraphs/name/.../... | --http-port | - | -| 8001 | GraphQL WS
(for subgraph subscriptions) | /subgraphs/id/...
/subgraphs/name/.../... | --ws-port | - | -| 8020 | JSON-RPC
(for managing deployments) | / | --admin-port | - | -| 8030 | Subgraph indexing status API | /graphql | --index-node-port | - | -| 8040 | Prometheus metrics | /metrics | --metrics-port | - | - -> **Important**: Be careful about exposing ports publicly - **administration ports** should be kept locked down. This includes the the Graph Node JSON-RPC endpoint. - -## Advanced Graph Node configuration - -At its simplest, Graph Node can be operated with a single instance of Graph Node, a single PostgreSQL database, an IPFS node, and the network clients as required by the subgraphs to be indexed. - -This setup can be scaled horizontally, by adding multiple Graph Nodes, and multiple databases to support those Graph Nodes. Advanced users may want to take advantage of some of the horizontal scaling capabilities of Graph Node, as well as some of the more advanced configuration options, via the `config.toml` file and Graph Node's environment variables. - -### `config.toml` - -A [TOML](https://toml.io/en/) configuration file can be used to set more complex configurations than those exposed in the CLI. The location of the file is passed with the --config command line switch. - -> When using a configuration file, it is not possible to use the options --postgres-url, --postgres-secondary-hosts, and --postgres-host-weights. - -A minimal `config.toml` file can be provided; the following file is equivalent to using the --postgres-url command line option: - -```toml -[store] -[store.primary] -connection="<.. postgres-url argument ..>" -[deployment] -[[deployment.rule]] -indexers = [ "<.. list of all indexing nodes ..>" ] -``` - -Full documentation of `config.toml` can be found in the [Graph Node docs](https://github.com/graphprotocol/graph-node/blob/master/docs/config.md). - -#### Multiple Graph Nodes - -Graph Node indexing can scale horizontally, running multiple instances of Graph Node to split indexing and querying across different nodes. This can be done simply by running Graph Nodes configured with a different `node_id` on startup (e.g. in the Docker Compose file), which can then be used in the `config.toml` file to specify [dedicated query nodes](#dedicated-query-nodes), [block ingestors](#dedicated-block-ingestor), and splitting subgraphs across nodes with [deployment rules](#deployment-rules). - -> Note that multiple Graph Nodes can all be configured to use the same database, which itself can be horizontally scaled via sharding. - -#### Deployment rules - -Given multiple Graph Nodes, it is necessary to manage deployment of new subgraphs so that the same subgraph isn't being indexed by two different nodes, which would lead to collisions. This can be done by using deployment rules, which can also specify which `shard` a subgraph's data should be stored in, if database sharding is being used. Deployment rules can match on the subgraph name and the network that the deployment is indexing in order to make a decision. - -Example deployment rule configuration: - -```toml -[deployment] -[[deployment.rule]] -match = { name = "(vip|important)/.*" } -shard = "vip" -indexers = [ "index_node_vip_0", "index_node_vip_1" ] -[[deployment.rule]] -match = { network = "kovan" } -# No shard, so we use the default shard called 'primary' -indexers = [ "index_node_kovan_0" ] -[[deployment.rule]] -match = { network = [ "xdai", "poa-core" ] } -indexers = [ "index_node_other_0" ] -[[deployment.rule]] -# There's no 'match', so any subgraph matches -shards = [ "sharda", "shardb" ] -indexers = [ - "index_node_community_0", - "index_node_community_1", - "index_node_community_2", - "index_node_community_3", - "index_node_community_4", - "index_node_community_5" - ] -``` - -Read more about deployment rules [here](https://github.com/graphprotocol/graph-node/blob/master/docs/config.md#controlling-deployment). - -#### Dedicated query nodes - -Nodes can be configured to explicitly be query nodes by including the following in the configuration file: - -```toml -[general] -query = "" -``` - -Any node whose --node-id matches the regular expression will be set up to only respond to queries. - -#### Database scaling via sharding - -For most use cases, a single Postgres database is sufficient to support a graph-node instance. When a graph-node instance outgrows a single Postgres database, it is possible to split the storage of graph-node's data across multiple Postgres databases. All databases together form the store of the graph-node instance. Each individual database is called a shard. - -Shards can be used to split subgraph deployments across multiple databases, and can also be used to use replicas to spread query load across databases. This includes configuring the number of available database connections each `graph-node` should keep in its connection pool for each database, which becomes increasingly important as more subgraphs are being indexed. - -Sharding becomes useful when your existing database can't keep up with the load that Graph Node puts on it, and when it's not possible to increase the database size anymore. - -> It is generally better make a single database as big as possible, before starting with shards. One exception is where query traffic is split very unevenly between subgraphs; in those situations it can help dramatically if the high-volume subgraphs are kept in one shard and everything else in another because that setup makes it more likely that the data for the high-volume subgraphs stays in the db-internal cache and doesn't get replaced by data that's not needed as much from low-volume subgraphs. - -In terms of configuring connections, start with max_connections in postgresql.conf set to 400 (or maybe even 200) and look at the store_connection_wait_time_ms and store_connection_checkout_count Prometheus metrics. Noticeable wait times (anything above 5ms) is an indication that there are too few connections available; high wait times there will also be caused by the database being very busy (like high CPU load). However if the database seems otherwise stable, high wait times indicate a need to increase the number of connections. In the configuration, how many connections each graph-node instance can use is an upper limit, and Graph Node will not keep connections open if it doesn't need them. - -Read more about store configuration [here](https://github.com/graphprotocol/graph-node/blob/master/docs/config.md#configuring-multiple-databases). - -#### Dedicated block ingestion - -If there are multiple nodes configured, it will be necessary to specify one node which is responsible for ingestion of new blocks, so that all configured index nodes aren't polling the chain head. This is done as part of the `chains` namespace, specifying the `node_id` to be used for block ingestion: - -```toml -[chains] -ingestor = "block_ingestor_node" -``` - -#### Supporting multiple networks - -The Graph Protocol is increasing the number of networks supported for indexing rewards, and there exist many subgraphs indexing unsupported networks which an indexer would like to process. The `config.toml` file allows for expressive and flexible configuration of: - -- Multiple networks -- Multiple providers per network (this can allow splitting of load across providers, and can also allow for configuration of full nodes as well as archive nodes, with Graph Node preferring cheaper providers if a given workload allows). -- Additional provider details, such as features, authentication and the type of provider (for experimental Firehose support) - -The `[chains]` section controls the ethereum providers that graph-node connects to, and where blocks and other metadata for each chain are stored. The following example configures two chains, mainnet and kovan, where blocks for mainnet are stored in the vip shard and blocks for kovan are stored in the primary shard. The mainnet chain can use two different providers, whereas kovan only has one provider. - -```toml -[chains] -ingestor = "block_ingestor_node" -[chains.mainnet] -shard = "vip" -provider = [ - { label = "mainnet1", url = "http://..", features = [], headers = { Authorization = "Bearer foo" } }, - { label = "mainnet2", url = "http://..", features = [ "archive", "traces" ] } -] -[chains.kovan] -shard = "primary" -provider = [ { label = "kovan", url = "http://..", features = [] } ] -``` - -Read more about provider configuration [here](https://github.com/graphprotocol/graph-node/blob/master/docs/config.md#configuring-ethereum-providers). - -### Environment variables - -Graph Node supports a range of environment variables which can enable features, or change Graph Node behaviour. These are documented [here](https://github.com/graphprotocol/graph-node/blob/master/docs/environment-variables.md). - -### Continuous deployment - -Users who are operating a scaled indexing setup with advanced configuration may benefit from managing their Graph Nodes with Kubernetes. - -- The indexer repository has an [example Kubernetes reference](https://github.com/graphprotocol/indexer/tree/main/k8s) -- [Launchpad](https://docs.graphops.xyz/launchpad/intro) is a toolkit for running a Graph Protocol Indexer on Kubernetes maintained by GraphOps. It provides a set of Helm charts and a CLI to manage a Graph Node deployment. - -### Managing Graph Node - -Given a running Graph Node (or Graph Nodes!), the challenge is then to manage deployed subgraphs across those nodes. Graph Node surfaces a range of tools to help with managing subgraphs. - -#### Logging - -Graph Node's logs can provide useful information for debugging and optimisation of Graph Node and specific subgraphs. Graph Node supports different log levels via the `GRAPH_LOG` environment variable, with the following levels: error, warn, info, debug or trace. - -In addition setting `GRAPH_LOG_QUERY_TIMING` to `gql` provides more details about how GraphQL queries are running (though this will generate a large volume of logs). - -#### Monitoring & alerting - -Graph Node provides the metrics via Prometheus endpoint on 8040 port by default. Grafana can then be used to visualise these metrics. - -The indexer repository provides an [example Grafana configuration](https://github.com/graphprotocol/indexer/blob/main/k8s/base/grafana.yaml). - -#### Graphman - -`graphman` is a maintenance tool for Graph Node, helping with diagnosis and resolution of different day-to-day and exceptional tasks. - -The graphman command is included in the official containers, and you can docker exec into your graph-node container to run it. It requires a `config.toml` file. - -Full documentation of `graphman` commands is available in the Graph Node repository. See \[/docs/graphman.md\] (https://github.com/graphprotocol/graph-node/blob/master/docs/graphman.md) in the Graph Node `/docs` - -### Working with subgraphs - -#### Indexing status API - -Available on port 8030/graphql by default, the indexing status API exposes a range of methods for checking indexing status for different subgraphs, checking proofs of indexing, inspecting subgraph features and more. - -The full schema is available [here](https://github.com/graphprotocol/graph-node/blob/master/server/index-node/src/schema.graphql). - -#### Indexing performance - -There are three separate parts of the indexing process: - -- Fetching events of interest from the provider -- Processing events in order with the appropriate handlers (this can involve calling the chain for state, and fetching data from the store) -- Writing the resulting data to the store - -These stages are pipelined (i.e. they can be executed in parallel), but they are dependent on one another. Where subgraphs are slow to index, the underlying cause will depend on the specific subgraph. - -Common causes of indexing slowness: - -- Time taken to find relevant events from the chain (call handlers in particular can be slow, given the reliance on `trace_filter`) -- Making large numbers of `eth_calls` as part of handlers -- A large amount of store interaction during execution -- A large amount of data to save to the store -- A large number of events to process -- Slow database connection time, for crowded nodes -- The provider itself falling behind the chain head -- Slowness in fetching new receipts at the chain head from the provider - -Subgraph indexing metrics can help diagnose the root cause of indexing slowness. In some cases, the problem lies with the subgraph itself, but in others, improved network providers, reduced database contention and other configuration improvements can markedly improve indexing performance. - -#### Failed subgraphs - -During indexing subgraphs might fail, if they encounter data that is unexpected, some component not working as expected, or if there is some bug in the event handlers or configuration. There are two general types of failure: - -- Deterministic failures: these are failures which will not be resolved with retries -- Non-deterministic failures: these might be down to issues with the provider, or some unexpected Graph Node error. When a non-deterministic failure occurs, Graph Node will retry the failing handlers, backing off over time. - -In some cases a failure might be resolvable by the indexer (for example if the error is a result of not having the right kind of provider, adding the required provider will allow indexing to continue). However in others, a change in the subgraph code is required. - -> Deterministic failures are considered "final", with a Proof of Indexing generated for the failing block, while non-determinstic failures are not, as the subgraph may manage to "unfail" and continue indexing. In some cases, the non-deterministic label is incorrect, and the subgraph will never overcome the error; such failures should be reported as issues on the Graph Node repository. - -#### Block and call cache - -Graph Node caches certain data in the store in order to save refetching from the provider. Blocks are cached, as are the results of `eth_calls` (the latter being cached as of a specific block). This caching can dramatically increase indexing speed during "resyncing" of a slightly altered subgraph. - -However, in some instances, if an Ethereum node has provided incorrect data for some period, that can make its way into the cache, leading to incorrect data or failed subgraphs. In this case indexers can use `graphman` to clear the poisoned cache, and then rewind the affected subgraphs, which will then fetch fresh data from the (hopefully) healthy provider. - -If a block cache inconsistency is suspected, such as a tx receipt missing event: - -1. `graphman chain list` to find the chain name. -2. `graphman chain check-blocks by-number ` will check if the cached block matches the provider, and deletes the block from the cache if it doesn’t. - 1. If there is a difference, it may be safer to truncate the whole cache with `graphman chain truncate `. - 2. If the block matches the provider, then the issue can be debugged directly against the provider. - -#### Querying issues and errors - -Once a subgraph has been indexed, indexers can expect to serve queries via the subgraph's dedicated query endpoint. If the indexer is hoping to serve significant query volume, a dedicated query node is recommended, and in case of very high query volumes, indexers may want to configure replica shards so that queries don't impact the indexing process. - -However, even with a dedicated query node and replicas, certain queries can take a long time to execute, and in some cases increase memory usage and negatively impact the query time for other users. - -There is not one "silver bullet", but a range of tools for preventing, diagnosing and dealing with slow queries. - -##### Query caching - -Graph Node caches GraphQL queries by default, which can significantly reduce database load. This can be further configured with the `GRAPH_QUERY_CACHE_BLOCKS` and `GRAPH_QUERY_CACHE_MAX_MEM` settings - read more [here](https://github.com/graphprotocol/graph-node/blob/master/docs/environment-variables.md#graphql-caching). - -##### Analysing queries - -Problematic queries most often surface in one of two ways. In some cases, users themselves report that a given query is slow. In that case the challenge is to diagnose the reason for the slowness - whether it is a general issue, or specific to that subgraph or query. And then of course to resolve it, if possible. - -In other cases, the trigger might be high memory usage on a query node, in which case the challenge is first to identify the query causing the issue. - -Indexers can use [qlog](https://github.com/graphprotocol/qlog/) to process and summarize Graph Node's query logs. `GRAPH_LOG_QUERY_TIMING` can also be enabled to help identify and debug slow queries. - -Given a slow query, indexers have a few options. Of course they can alter their cost model, to significantly increase the cost of sending the problematic query. This may result in a reduction in the frequency of that query. However this often doesn't resolve the root cause of the issue. - -##### Account-like optimisation - -Database tables that store entities seem to generally come in two varieties: 'transaction-like', where entities, once created, are never updated, i.e., they store something akin to a list of financial transactions, and 'account-like' where entities are updated very often, i.e., they store something like financial accounts that get modified every time a transaction is recorded. Account-like tables are characterized by the fact that they contain a large number of entity versions, but relatively few distinct entities. Often, in such tables the number of distinct entities is 1% of the total number of rows (entity versions) - -For account-like tables, `graph-node` can generate queries that take advantage of details of how Postgres ends up storing data with such a high rate of change, namely that all of the versions for recent blocks are in a small subsection of the overall storage for such a table. - -The command `graphman stats show shows, for each entity type/table in a deployment, how many distinct entities, and how many entity versions each table contains. That data is based on Postgres-internal estimates, and is therefore necessarily imprecise, and can be off by an order of magnitude. A `-1` in the `entities` column means that Postgres believes that all rows contain a distinct entity. - -In general, tables where the number of distinct entities are less than 1% of the total number of rows/entity versions are good candidates for the account-like optimization. When the output of `graphman stats show` indicates that a table might benefit from this optimization, running `graphman stats show ` will perform a full count of the table - that can be slow, but gives a precise measure of the ratio of distinct entities to overall entity versions. - -Once a table has been determined to be account-like, running `graphman stats account-like .
` will turn on the account-like optimization for queries against that table. The optimization can be turned off again with `graphman stats account-like --clear .
` It takes up to 5 minutes for query nodes to notice that the optimization has been turned on or off. After turning the optimization on, it is necessary to verify that the change does not in fact make queries slower for that table. If you have configured Grafana to monitor Postgres, slow queries would show up in `pg_stat_activity`in large numbers, taking several seconds. In that case, the optimization needs to be turned off again. - -For Uniswap-like subgraphs, the `pair` and `token` tables are prime candidates for this optimization, and can have a dramatic effect on database load. - -#### Removing subgraphs - -> This is new functionality, which will be available in Graph Node 0.29.x - -At some point an indexer might want to remove a given subgraph. This can be easily done via `graphman drop`, which deletes a deployment and all it's indexed data. The deployment can be specified as either a subgraph name, an IPFS hash `Qm..`, or the database namespace `sgdNNN`. Further documentation is available [here](https://github.com/graphprotocol/graph-node/blob/master/docs/graphman.md#-drop). diff --git a/website/pages/ha/publishing/_meta.js b/website/pages/ha/publishing/_meta.js deleted file mode 100644 index eb06f56f912a..000000000000 --- a/website/pages/ha/publishing/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/publishing/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/publishing/publishing-a-subgraph.mdx b/website/pages/ha/publishing/publishing-a-subgraph.mdx deleted file mode 100644 index 2fb016128239..000000000000 --- a/website/pages/ha/publishing/publishing-a-subgraph.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Publishing a Subgraph to the Decentralized Network ---- - -Once your subgraph has been [deployed to the Subgraph Studio](/deploying/deploying-a-subgraph-to-studio), you have tested it out, and are ready to put it into production, you can then publish it to the decentralized network. - -Publishing a Subgraph to the decentralized network makes it available for [Curators](/network/curating) to begin curating on it, and [Indexers](/network/indexing) to begin indexing it. - - - -You can find the list of the supported networks [Here](/developing/supported-networks). - -## Publishing a subgraph - -Subgraphs can be published to the decentralized network directly from the Subgraph Studio dashboard by clicking on the **Publish** button. Once a subgraph is published, it will be available to view in the [Graph Explorer](https://thegraph.com/explorer/). - -- Subgraphs can be published to Sepolia, Arbitrum sepolia, Arbitrum One, or Ethereum mainnet. - -- Regardless of the network the subgraph was published on, it can index data on any of the [supported networks](/developing/supported-networks). - -- When publishing a new version for an existing subgraph the same rules apply as above. - -## Curating your subgraph - -> It is recommended that you curate your own subgraph with 10,000 GRT to ensure that it is indexed and available for querying as soon as possible. - -Subgraph Studio enables you to be the first to curate your subgraph by adding GRT to your subgraph's curation pool in the same transaction. When publishing your subgraph, make sure to check the button that says, "Be the first to signal on this subgraph." - -![Curation Pool](/img/curate-own-subgraph-tx.png) - -## Updating metadata for a published subgraph - -Once your subgraph has been published to the decentralized network, you can modify the metadata at any time by making the update in the Subgraph Studio dashboard of the subgraph. After saving the changes and publishing your updates to the network, they will be reflected in The Graph Explorer. This won’t create a new version, as your deployment hasn’t changed. diff --git a/website/pages/ha/querying/_meta.js b/website/pages/ha/querying/_meta.js deleted file mode 100644 index e52da8f399fb..000000000000 --- a/website/pages/ha/querying/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../en/querying/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/querying/distributed-systems.mdx b/website/pages/ha/querying/distributed-systems.mdx deleted file mode 100644 index 85337206bfd3..000000000000 --- a/website/pages/ha/querying/distributed-systems.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: Distributed Systems ---- - -The Graph is a protocol implemented as a distributed system. - -Connections fail. Requests arrive out of order. Different computers with out-of-sync clocks and states process related requests. Servers restart. Re-orgs happen between requests. These problems are inherent to all distributed systems but are exacerbated in systems operating at a global scale. - -Consider this example of what may occur if a client polls an Indexer for the latest data during a re-org. - -1. Indexer ingests block 8 -2. Request served to the client for block 8 -3. Indexer ingests block 9 -4. Indexer ingests block 10A -5. Request served to the client for block 10A -6. Indexer detects reorg to 10B and rolls back 10A -7. Request served to the client for block 9 -8. Indexer ingests block 10B -9. Indexer ingests block 11 -10. Request served to the client for block 11 - -From the point of view of the Indexer, things are progressing forward logically. Time is moving forward, though we did have to roll back an uncle block and play the block under consensus forward on top of it. Along the way, the Indexer serves requests using the latest state it knows about at that time. - -From the point of view of the client, however, things appear chaotic. The client observes that the responses were for blocks 8, 10, 9, and 11 in that order. We call this the "block wobble" problem. When a client experiences block wobble, data may appear to contradict itself over time. The situation worsens when we consider that Indexers do not all ingest the latest blocks simultaneously, and your requests may be routed to multiple Indexers. - -It is the responsibility of the client and server to work together to provide consistent data to the user. Different approaches must be used depending on the desired consistency as there is no one right program for every problem. - -Reasoning through the implications of distributed systems is hard, but the fix may not be! We've established APIs and patterns to help you navigate some common use-cases. The following examples illustrate those patterns but still elide details required by production code (like error handling and cancellation) to not obfuscate the main ideas. - -## Polling for updated data - -The Graph provides the `block: { number_gte: $minBlock }` API, which ensures that the response is for a single block equal or higher to `$minBlock`. If the request is made to a `graph-node` instance and the min block is not yet synced, `graph-node` will return an error. If `graph-node` has synced min block, it will run the response for the latest block. If the request is made to an Edge & Node Gateway, the Gateway will filter out any Indexers that have not yet synced min block and make the request for the latest block the Indexer has synced. - -We can use `number_gte` to ensure that time never travels backward when polling for data in a loop. Here is an example: - -```javascript -/// Updates the protocol.paused variable to the latest -/// known value in a loop by fetching it using The Graph. -async function updateProtocolPaused() { - // It's ok to start with minBlock at 0. The query will be served - // using the latest block available. Setting minBlock to 0 is the - // same as leaving out that argument. - let minBlock = 0 - - for (;;) { - // Schedule a promise that will be ready once - // the next Ethereum block will likely be available. - const nextBlock = new Promise((f) => { - setTimeout(f, 14000) - }) - - const query = ` - query GetProtocol($minBlock: Int!) { - protocol(block: { number_gte: $minBlock } id: "0") { - paused - } - _meta { - block { - number - } - } - }` - - const variables = { minBlock } - const response = await graphql(query, variables) - minBlock = response._meta.block.number - - // TODO: Do something with the response data here instead of logging it. - console.log(response.protocol.paused) - - // Sleep to wait for the next block - await nextBlock - } -} -``` - -## Fetching a set of related items - -Another use-case is retrieving a large set or, more generally, retrieving related items across multiple requests. Unlike the polling case (where the desired consistency was to move forward in time), the desired consistency is for a single point in time. - -Here we will use the `block: { hash: $blockHash }` argument to pin all of our results to the same block. - -```javascript -/// Gets a list of domain names from a single block using pagination -async function getDomainNames() { - // Set a cap on the maximum number of items to pull. - let pages = 5 - const perPage = 1000 - - // The first query will get the first page of results and also get the block - // hash so that the remainder of the queries are consistent with the first. - const listDomainsQuery = ` - query ListDomains($perPage: Int!) { - domains(first: $perPage) { - name - id - } - _meta { - block { - hash - } - } - }` - - let data = await graphql(listDomainsQuery, { perPage }) - let result = data.domains.map((d) => d.name) - let blockHash = data._meta.block.hash - - let query - // Continue fetching additional pages until either we run into the limit of - // 5 pages total (specified above) or we know we have reached the last page - // because the page has fewer entities than a full page. - while (data.domains.length == perPage && --pages) { - let lastID = data.domains[data.domains.length - 1].id - query = ` - query ListDomains($perPage: Int!, $lastID: ID!, $blockHash: Bytes!) { - domains(first: $perPage, where: { id_gt: $lastID }, block: { hash: $blockHash }) { - name - id - } - }` - - data = await graphql(query, { perPage, lastID, blockHash }) - - // Accumulate domain names into the result - for (domain of data.domains) { - result.push(domain.name) - } - } - return result -} -``` - -Note that in case of a re-org, the client will need to retry from the first request to update the block hash to a non-uncle block. diff --git a/website/pages/ha/querying/graph-client/_meta.js b/website/pages/ha/querying/graph-client/_meta.js deleted file mode 100644 index f00c8556ac1b..000000000000 --- a/website/pages/ha/querying/graph-client/_meta.js +++ /dev/null @@ -1,5 +0,0 @@ -import meta from '../../../en/querying/graph-client/_meta.js' - -export default { - ...meta, -} diff --git a/website/pages/ha/querying/graphql-api.mdx b/website/pages/ha/querying/graphql-api.mdx deleted file mode 100644 index 89cda460d58f..000000000000 --- a/website/pages/ha/querying/graphql-api.mdx +++ /dev/null @@ -1,419 +0,0 @@ ---- -title: GraphQL API ---- - -This guide explains the GraphQL Query API that is used for the Graph Protocol. - -## Queries - -In your subgraph schema you define types called `Entities`. For each `Entity` type, an `entity` and `entities` field will be generated on the top-level `Query` type. Note that `query` does not need to be included at the top of the `graphql` query when using The Graph. - -### Examples - -Query for a single `Token` entity defined in your schema: - -```graphql -{ - token(id: "1") { - id - owner - } -} -``` - -> **Note:** When querying for a single entity, the `id` field is required, and it must be a string. - -Query all `Token` entities: - -```graphql -{ - tokens { - id - owner - } -} -``` - -### Sorting - -When querying a collection, the `orderBy` parameter may be used to sort by a specific attribute. Additionally, the `orderDirection` can be used to specify the sort direction, `asc` for ascending or `desc` for descending. - -#### Example - -```graphql -{ - tokens(orderBy: price, orderDirection: asc) { - id - owner - } -} -``` - -#### Example for nested entity sorting - -As of Graph Node [`v0.30.0`](https://github.com/graphprotocol/graph-node/releases/tag/v0.30.0) entities can be sorted on the basis of nested entities. - -In the following example, we sort the tokens by the name of their owner: - -```graphql -{ - tokens(orderBy: owner__name, orderDirection: asc) { - id - owner { - name - } - } -} -``` - -> Currently, you can sort by one-level deep `String` or `ID` types on `@entity` and `@derivedFrom` fields. Unfortunately, [sorting by interfaces on one level-deep entities](https://github.com/graphprotocol/graph-node/pull/4058), sorting by fields which are arrays and nested entities is not yet supported. - -### Pagination - -When querying a collection, the `first` parameter can be used to paginate from the beginning of the collection. It is worth noting that the default sort order is by ID in ascending alphanumeric order, not by creation time. - -Further, the `skip` parameter can be used to skip entities and paginate. e.g. `first:100` shows the first 100 entities and `first:100, skip:100` shows the next 100 entities. - -Queries should avoid using very large `skip` values since they generally perform poorly. For retrieving a large number of items, it is much better to page through entities based on an attribute as shown in the last example. - -#### Example using `first` - -Query the first 10 tokens: - -```graphql -{ - tokens(first: 10) { - id - owner - } -} -``` - -To query for groups of entities in the middle of a collection, the `skip` parameter may be used in conjunction with the `first` parameter to skip a specified number of entities starting at the beginning of the collection. - -#### Example using `first` and `skip` - -Query 10 `Token` entities, offset by 10 places from the beginning of the collection: - -```graphql -{ - tokens(first: 10, skip: 10) { - id - owner - } -} -``` - -#### Example using `first` and `id_ge` - -If a client needs to retrieve a large number of entities, it is much more performant to base queries on an attribute and filter by that attribute. For example, a client would retrieve a large number of tokens using this query: - -```graphql -query manyTokens($lastID: String) { - tokens(first: 1000, where: { id_gt: $lastID }) { - id - owner - } -} -``` - -The first time, it would send the query with `lastID = ""`, and for subsequent requests would set `lastID` to the `id` attribute of the last entity in the previous request. This approach will perform significantly better than using increasing `skip` values. - -### Filtering - -You can use the `where` parameter in your queries to filter for different properties. You can filter on mulltiple values within the `where` parameter. - -#### Example using `where` - -Query challenges with `failed` outcome: - -```graphql -{ - challenges(where: { outcome: "failed" }) { - challenger - outcome - application { - id - } - } -} -``` - -You can use suffixes like `_gt`, `_lte` for value comparison: - -#### Example for range filtering - -```graphql -{ - applications(where: { deposit_gt: "10000000000" }) { - id - whitelisted - deposit - } -} -``` - -#### Example for block filtering - -You can also filter entities by the `_change_block(number_gte: Int)` - this filters entities which were updated in or after the specified block. - -This can be useful if you are looking to fetch only entities which have changed, for example since the last time you polled. Or alternatively it can be useful to investigate or debug how entities are changing in your subgraph (if combined with a block filter, you can isolate only entities that changed in a specific block). - -```graphql -{ - applications(where: { _change_block: { number_gte: 100 } }) { - id - whitelisted - deposit - } -} -``` - -#### Example for nested entity filtering - -Filtering on the basis of nested entities is possible in the fields with the `_` suffix. - -This can be useful if you are looking to fetch only entities whose child-level entities meet the provided conditions. - -```graphql -{ - challenges(where: { application_: { id: 1 } }) { - challenger - outcome - application { - id - } - } -} -``` - -#### Logical operators - -As of Graph Node [`v0.30.0`](https://github.com/graphprotocol/graph-node/releases/tag/v0.30.0) you can group multiple parameters in the same `where` argument using the `and` or the `or` operators to filter results based on more than one criteria. - -##### `AND` Operator - -In the following example, we are filtering for challenges with `outcome` `succeeded` and `number` greater than or equal to `100`. - -```graphql -{ - challenges(where: { and: [{ number_gte: 100 }, { outcome: "succeeded" }] }) { - challenger - outcome - application { - id - } - } -} -``` - -> **Syntactic sugar:** You can simplify the above query by removing the `and` operator by passing a sub-expression separated by commas. -> -> ```graphql -> { -> challenges(where: { number_gte: 100, outcome: "succeeded" }) { -> challenger -> outcome -> application { -> id -> } -> } -> } -> ``` - -##### `OR` Operator - -In the following example, we are filtering for challenges with `outcome` `succeeded` or `number` greater than or equal to `100`. - -```graphql -{ - challenges(where: { or: [{ number_gte: 100 }, { outcome: "succeeded" }] }) { - challenger - outcome - application { - id - } - } -} -``` - -> **Note**: When constructing queries, it is important to consider the performance impact of using the `or` operator. While `or` can be a useful tool for broadening search results, it can also have significant costs. One of the main issues with `or` is that it can cause queries to slow down. This is because `or` requires the database to scan through multiple indexes, which can be a time-consuming process. To avoid these issues, it is recommended that developers use and operators instead of or whenever possible. This allows for more precise filtering and can lead to faster, more accurate queries. - -#### All Filters - -Full list of parameter suffixes: - -``` -_ -_not -_gt -_lt -_gte -_lte -_in -_not_in -_contains -_contains_nocase -_not_contains -_not_contains_nocase -_starts_with -_starts_with_nocase -_ends_with -_ends_with_nocase -_not_starts_with -_not_starts_with_nocase -_not_ends_with -_not_ends_with_nocase -``` - -> Please note that some suffixes are only supported for specific types. For example, `Boolean` only supports `_not`, `_in`, and `_not_in`, but `_` is available only for object and interface types. - -In addition, the following global filters are available as part of `where` argument: - -```gr -_change_block(number_gte: Int) -``` - -### Time-travel queries - -You can query the state of your entities not just for the latest block, which is the default, but also for an arbitrary block in the past. The block at which a query should happen can be specified either by its block number or its block hash by including a `block` argument in the toplevel fields of queries. - -The result of such a query will not change over time, i.e., querying at a certain past block will return the same result no matter when it is executed, with the exception that if you query at a block very close to the head of the chain, the result might change if that block turns out to not be on the main chain and the chain gets reorganized. Once a block can be considered final, the result of the query will not change. - -Note that the current implementation is still subject to certain limitations that might violate these gurantees. The implementation can not always tell that a given block hash is not on the main chain at all, or that the result of a query by block hash for a block that can not be considered final yet might be influenced by a block reorganization running concurrently with the query. They do not affect the results of queries by block hash when the block is final and known to be on the main chain. [This issue](https://github.com/graphprotocol/graph-node/issues/1405) explains what these limitations are in detail. - -#### Example - -```graphql -{ - challenges(block: { number: 8000000 }) { - challenger - outcome - application { - id - } - } -} -``` - -This query will return `Challenge` entities, and their associated `Application` entities, as they existed directly after processing block number 8,000,000. - -#### Example - -```graphql -{ - challenges(block: { hash: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c" }) { - challenger - outcome - application { - id - } - } -} -``` - -This query will return `Challenge` entities, and their associated `Application` entities, as they existed directly after processing the block with the given hash. - -### Fulltext Search Queries - -Fulltext search query fields provide an expressive text search API that can be added to the subgraph schema and customized. Refer to [Defining Fulltext Search Fields](/developing/creating-a-subgraph#defining-fulltext-search-fields) to add fulltext search to your subgraph. - -Fulltext search queries have one required field, `text`, for supplying search terms. Several special fulltext operators are available to be used in this `text` search field. - -Fulltext search operators: - -| Symbol | Operator | Description | -| --- | --- | --- | -| `&` | `And` | For combining multiple search terms into a filter for entities that include all of the provided terms | -| | | `Or` | Queries with multiple search terms separated by the or operator will return all entities with a match from any of the provided terms | -| `<->` | `Follow by` | Specify the distance between two words. | -| `:*` | `Prefix` | Use the prefix search term to find words whose prefix match (2 characters required.) | - -#### Examples - -Using the `or` operator, this query will filter to blog entities with variations of either "anarchism" or "crumpet" in their fulltext fields. - -```graphql -{ - blogSearch(text: "anarchism | crumpets") { - id - title - body - author - } -} -``` - -The `follow by` operator specifies a words a specific distance apart in the fulltext documents. The following query will return all blogs with variations of "decentralize" followed by "philosophy" - -```graphql -{ - blogSearch(text: "decentralized <-> philosophy") { - id - title - body - author - } -} -``` - -Combine fulltext operators to make more complex filters. With a pretext search operator combined with a follow by this example query will match all blog entities with words that start with "lou" followed by "music". - -```graphql -{ - blogSearch(text: "lou:* <-> music") { - id - title - body - author - } -} -``` - -### Validation - -Graph Node implements [specification-based](https://spec.graphql.org/October2021/#sec-Validation) validation of the GraphQL queries it receives using [graphql-tools-rs](https://github.com/dotansimha/graphql-tools-rs#validation-rules), which is based on the [graphql-js reference implementation](https://github.com/graphql/graphql-js/tree/main/src/validation). Queries which fail a validation rule do so with a standard error - visit the [GraphQL spec](https://spec.graphql.org/October2021/#sec-Validation) to learn more. - -## Schema - -The schema of your data source--that is, the entity types, values, and relationships that are available to query--are defined through the [GraphQL Interface Definition Langauge (IDL)](https://facebook.github.io/graphql/draft/#sec-Type-System). - -GraphQL schemas generally define root types for `queries`, `subscriptions` and `mutations`. The Graph only supports `queries`. The root `Query` type for your subgraph is automatically generated from the GraphQL schema that's included in your subgraph manifest. - -> **Note:** Our API does not expose mutations because developers are expected to issue transactions directly against the underlying blockchain from their applications. - -### Entities - -All GraphQL types with `@entity` directives in your schema will be treated as entities and must have an `ID` field. - -> **Note:** Currently, all types in your schema must have an `@entity` directive. In the future, we will treat types without an `@entity` directive as value objects, but this is not yet supported. - -### Subgraph Metadata - -All subgraphs have an auto-generated `_Meta_` object, which provides access to subgraph metadata. This can be queried as follows: - -```graphQL -{ - _meta(block: { number: 123987 }) { - block { - number - hash - timestamp - } - deployment - hasIndexingErrors - } -} -``` - -If a block is provided, the metadata is as of that block, if not the latest indexed block is used. If provided, the block must be after the subgraph's start block, and less than or equal to the most recently indexed block. - -`deployment` is a unique ID, corresponding to the IPFS CID of the `subgraph.yaml` file. - -`block` provides information about the latest block (taking into account any block constraints passed to `_meta`): - -- hash: the hash of the block -- number: the block number -- timestamp: the timestamp of the block, if available (this is currently only available for subgraphs indexing EVM networks) - -`hasIndexingErrors` is a boolean identifying whether the subgraph encountered indexing errors at some past block diff --git a/website/pages/ha/querying/managing-api-keys.mdx b/website/pages/ha/querying/managing-api-keys.mdx deleted file mode 100644 index ee7c274bca10..000000000000 --- a/website/pages/ha/querying/managing-api-keys.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Managing your API keys ---- - -Regardless of whether you’re a dapp developer or a subgraph developer, you’ll need to manage your API keys. This is important for you to be able to query subgraphs because API keys make sure the connections between application services are valid and authorized. This includes authenticating the end user and the device using the application. - -The Studio will list out existing API keys, which will give you the ability to manage or delete them. - -1. The **Overview** section will allow you to: - - Edit your key name - - Regenerate API keys - - View the current usage of the API key with stats: - - Number of queries - - Amount of GRT spent -2. Under **Security**, you’ll be able to opt into security settings depending on the level of control you’d like to have over your API keys. In this section, you can: - - View and manage the domain names authorized to use your API key - - Assign subgraphs that can be queried with your API key -3. Under **Indexer Preference**, you’ll be able to set different preferences for Indexers who are indexing subgraphs that your API key is used for. You can assign up to 5 points for each of these: - - **Fastest Speed**: Time between the query and the response from an indexer. If you mark this as important we will optimize for fast indexers. - - **Lowest Price**: The amount paid per query. If you mark this as important we will optimize for the less expensive indexers. - - **Data Freshness**: How recent the latest block an indexer has processed for the subgraph you are querying. If you mark this as important we will optimize to find the indexers with the freshest data. - - **Economic Security**: The amount of GRT an indexer can lose if they respond incorrectly to your query. If you mark this as important we will optimize for indexers with a large stake. -4. Under **Budget**, you’ll be able to update the maximum price per query. Note that we have a dynamic setting for that that's based on a volume discounting algorithm. **We strongly recommend using the default settings unless you are experiencing a specific problem.** Otherwise, you can update it under "Set a custom maximum budget". On this page you can also view different KPIs (in GRT and USD): - - Average cost per query - - Failed queries over max price - - Most expensive query diff --git a/website/pages/ha/querying/querying-best-practices.mdx b/website/pages/ha/querying/querying-best-practices.mdx deleted file mode 100644 index 98c0ffb72c61..000000000000 --- a/website/pages/ha/querying/querying-best-practices.mdx +++ /dev/null @@ -1,463 +0,0 @@ ---- -title: Querying Best Practices ---- - -The Graph provides a decentralized way to query data from blockchains. - -The Graph network's data is exposed through a GraphQL API, making it easier to query data with the GraphQL language. - -This page will guide you through the essential GraphQL language rules and GraphQL queries best practices. - ---- - -## Querying a GraphQL API - -### The anatomy of a GraphQL query - -Unlike REST API, a GraphQL API is built upon a Schema that defines which queries can be performed. - -For example, a query to get a token using the `token` query will look as follows: - -```graphql -query GetToken($id: ID!) { - token(id: $id) { - id - owner - } -} -``` - -which will return the following predictable JSON response (_when passing the proper `$id` variable value_): - -```json -{ - "token": { - "id": "...", - "owner": "..." - } -} -``` - -GraphQL queries use the GraphQL language, which is defined upon [a specification](https://spec.graphql.org/). - -The above `GetToken` query is composed of multiple language parts (replaced below with `[...]` placeholders): - -```graphql -query [operationName]([variableName]: [variableType]) { - [queryName]([argumentName]: [variableName]) { - # "{ ... }" express a Selection-Set, we are querying fields from `queryName`. - [field] - [field] - } -} -``` - -While the list of syntactic do's and don'ts is long, here are the essential rules to keep in mind when it comes to writing GraphQL queries: - -- Each `queryName` must only be used once per operation. -- Each `field` must be used only once in a selection (we cannot query `id` twice under `token`) -- Some `field`s or queries (like `tokens`) return complex types that require a selection of sub-field. Not providing a selection when expected (or providing one when not expected - for example, on `id`) will raise an error. To know a field type, please refer to [The Graph Explorer](/network/explorer). -- Any variable assigned to an argument must match its type. -- In a given list of variables, each of them must be unique. -- All defined variables must be used. - -Failing to follow the above rules will end with an error from the Graph API. - -For a complete list of rules with code examples, please look at our GraphQL Validations guide. - -### Sending a query to a GraphQL API - -GraphQL is a language and set of conventions that transport over HTTP. - -It means that you can query a GraphQL API using standard `fetch` (natively or via `@whatwg-node/fetch` or `isomorphic-fetch`). - -However, as stated in ["Querying from an Application"](/querying/querying-from-an-application), we recommend you to use our `graph-client` that supports unique features such as: - -- Cross-chain Subgraph Handling: Querying from multiple subgraphs in a single query -- [Automatic Block Tracking](https://github.com/graphprotocol/graph-client/blob/main/packages/block-tracking/README.md) -- [Automatic Pagination](https://github.com/graphprotocol/graph-client/blob/main/packages/auto-pagination/README.md) -- Fully typed result - -Here's how to query The Graph with `graph-client`: - -```tsx -import { execute } from '../.graphclient' - -const query = ` -query GetToken($id: ID!) { - token(id: $id) { - id - owner - } -} -` -const variables = { id: '1' } - -async function main() { - const result = await execute(query, variables) - // `result` is fully typed! - console.log(result) -} - -main() -``` - -More GraphQL client alternatives are covered in ["Querying from an Application"](/querying/querying-from-an-application). - -Now that we covered the basic rules of GraphQL queries syntax, let's now look at the best practices of GraphQL query writing. - ---- - -## Writing GraphQL queries - -### Always write static queries - -A common (bad) practice is to dynamically build query strings as follows: - -```tsx -const id = params.id -const fields = ['id', 'owner'] -const query = ` -query GetToken { - token(id: ${id}) { - ${fields.join('\n')} - } -} -` - -// Execute query... -``` - -While the above snippet produces a valid GraphQL query, **it has many drawbacks**: - -- it makes it **harder to understand** the query as a whole -- developers are **responsible for safely sanitizing the string interpolation** -- not sending the values of the variables as part of the request parameters **prevent possible caching on server-side** -- it **prevents tools from statically analyzing the query** (ex: Linter, or type generations tools) - -For this reason, it is recommended to always write queries as static strings: - -```tsx -import { execute } from 'your-favorite-graphql-client' - -const id = params.id -const query = ` -query GetToken($id: ID!) { - token(id: $id) { - id - owner - } -} -` - -const result = await execute(query, { - variables: { - id, - }, -}) -``` - -Doing so brings **many advantages**: - -- **Easy to read and maintain** queries -- The GraphQL **server handles variables sanitization** -- **Variables can be cached** at server-level -- **Queries can be statically analyzed by tools** (more on this in the following sections) - -**Note: How to include fields conditionally in static queries** - -We might want to include the `owner` field only on a particular condition. - -For this, we can leverage the `@include(if:...)` directive as follows: - -```tsx -import { execute } from 'your-favorite-graphql-client' - -const id = params.id -const query = ` -query GetToken($id: ID!, $includeOwner: Boolean) { - token(id: $id) { - id - owner @include(if: $includeOwner) - } -} -` - -const result = await execute(query, { - variables: { - id, - includeOwner: true, - }, -}) -``` - -Note: The opposite directive is `@skip(if: ...)`. - -### Performance tips - -**"Ask for what you want"** - -GraphQL became famous for its "Ask for what you want" tagline. - -For this reason, there is no way, in GraphQL, to get all available fields without having to list them individually. - -When querying GraphQL APIs, always think of querying only the fields that will be actually used. - -A common cause of over-fetching is collections of entities. By default, queries will fetch 100 entities in a collection, which is usually much more than what will actually be used, e.g., for display to the user. Queries should therefore almost always set first explicitly, and make sure they only fetch as many entities as they actually need. This applies not just to top-level collections in a query, but even more so to nested collections of entities. - -For example, in the following query: - -```graphql -query listTokens { - tokens { - # will fetch up to 100 tokens - id - transactions { - # will fetch up to 100 transactions - id - } - } -} -``` - -The response could contain 100 transactions for each of the 100 tokens. - -If the application only needs 10 transactions, the query should explicitly set `first: 10` on the transactions field. - -**Combining multiple queries** - -Your application might require querying multiple types of data as follows: - -```graphql -import { execute } from "your-favorite-graphql-client" - -const tokensQuery = ` -query GetTokens { - tokens(first: 50) { - id - owner - } -} -` -const countersQuery = ` -query GetCounters { - counters { - id - value - } -} -` - -const [tokens, counters] = Promise.all( - [ - tokensQuery, - countersQuery, - ].map(execute) -) -``` - -While this implementation is totally valid, it will require two round trips with the GraphQL API. - -Fortunately, it is also valid to send multiple queries in the same GraphQL request as follows: - -```graphql -import { execute } from "your-favorite-graphql-client" - -const query = ` -query GetTokensandCounters { - tokens(first: 50) { - id - owner - } - counters { - id - value - } -} -` - -const { result: { tokens, counters } } = execute(query) -``` - -This approach will **improve the overall performance** by reducing the time spent on the network (saves you a round trip to the API) and will provide a **more concise implementation**. - -### Leverage GraphQL Fragments - -A helpful feature to write GraphQL queries is GraphQL Fragment. - -Looking at the following query, you will notice that some fields are repeated across multiple Selection-Sets (`{ ... }`): - -```graphql -query { - bondEvents { - id - newDelegate { - id - active - status - } - oldDelegate { - id - active - status - } - } -} -``` - -Such repeated fields (`id`, `active`, `status`) bring many issues: - -- harder to read for more extensive queries -- when using tools that generate TypeScript types based on queries (_more on that in the last section_), `newDelegate` and `oldDelegate` will result in two distinct inline interfaces. - -A refactored version of the query would be the following: - -```graphql -query { - bondEvents { - id - newDelegate { - ...DelegateItem - } - oldDelegate { - ...DelegateItem - } - } -} - -# we define a fragment (subtype) on Transcoder -# to factorize repeated fields in the query -fragment DelegateItem on Transcoder { - id - active - status -} -``` - -Using GraphQL `fragment` will improve readability (especially at scale) but also will result in better TypeScript types generation. - -When using the types generation tool, the above query will generate a proper `DelegateItemFragment` type (_see last "Tools" section_). - -### GraphQL Fragment do's and don'ts - -**Fragment base must be a type** - -A Fragment cannot be based on a non-applicable type, in short, **on type not having fields**: - -```graphql -fragment MyFragment on BigInt { - # ... -} -``` - -`BigInt` is a **scalar** (native "plain" type) that cannot be used as a fragment's base. - -**How to spread a Fragment** - -Fragments are defined on specific types and should be used accordingly in queries. - -Example: - -```graphql -query { - bondEvents { - id - newDelegate { - ...VoteItem # Error! `VoteItem` cannot be spread on `Transcoder` type - } - oldDelegate { - ...VoteItem - } - } -} - -fragment VoteItem on Vote { - id - voter -} -``` - -`newDelegate` and `oldDelegate` are of type `Transcoder`. - -It is not possible to spread a fragment of type `Vote` here. - -**Define Fragment as an atomic business unit of data** - -GraphQL Fragment must be defined based on their usage. - -For most use-case, defining one fragment per type (in the case of repeated fields usage or type generation) is sufficient. - -Here is a rule of thumb for using Fragment: - -- when fields of the same type are repeated in a query, group them in a Fragment -- when similar but not the same fields are repeated, create multiple fragments, ex: - -```graphql -# base fragment (mostly used in listing) -fragment Voter on Vote { - id - voter -} - -# extended fragment (when querying a detailed view of a vote) -fragment VoteWithPoll on Vote { - id - voter - choiceID - poll { - id - proposal - } -} -``` - ---- - -## The essential tools - -### GraphQL web-based explorers - -Iterating over queries by running them in your application can be cumbersome. For this reason, don't hesitate to use [The Graph Explorer](https://thegraph.com/explorer) to test your queries before adding them to your application. The Graph Explorer will provide you a preconfigured GraphQL playground to test your queries. - -If you are looking for a more flexible way to debug/test your queries, other similar web-based tools are available such as [Altair](https://altair.sirmuel.design/) and [GraphiQL](https://graphiql-online.com/graphiql). - -### GraphQL Linting - -In order to keep up with the mentioned above best practices and syntactic rules, it is highly recommended to use the following workflow and IDE tools. - -**GraphQL ESLint** - -[GraphQL ESLint](https://github.com/dotansimha/graphql-eslint) will help you stay on top of GraphQL best practices with zero effort. - -[Setup the "operations-recommended"](https://github.com/dotansimha/graphql-eslint#available-configs) config will enforce essential rules such as: - -- `@graphql-eslint/fields-on-correct-type`: is a field used on a proper type? -- `@graphql-eslint/no-unused variables`: should a given variable stay unused? -- and more! - -This will allow you to **catch errors without even testing queries** on the playground or running them in production! - -### IDE plugins - -**VSCode and GraphQL** - -The [GraphQL VSCode extension](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) is an excellent addition to your development workflow to get: - -- syntax highlighting -- autocomplete suggestions -- validation against schema -- snippets -- go to definition for fragments and input types - -If you are using `graphql-eslint`, the [ESLint VSCode extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) is a must-have to visualize errors and warnings inlined in your code correctly. - -**WebStorm/Intellij and GraphQL** - -The [JS GraphQL plugin](https://plugins.jetbrains.com/plugin/8097-graphql/) will significantly improve your experience while working with GraphQL by providing: - -- syntax highlighting -- autocomplete suggestions -- validation against schema -- snippets - -More information on this [WebStorm article](https://blog.jetbrains.com/webstorm/2019/04/featured-plugin-js-graphql/) that showcases all the plugin's main features. diff --git a/website/pages/ha/querying/querying-by-subgraph-id-vs-deployment-id.mdx b/website/pages/ha/querying/querying-by-subgraph-id-vs-deployment-id.mdx deleted file mode 100644 index 25a955931e7a..000000000000 --- a/website/pages/ha/querying/querying-by-subgraph-id-vs-deployment-id.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Subgraph ID vs Deployment ID ---- - -A subgraph is identified by a Subgraph ID, and each version of the subgraph is identified by a Deployment ID. - -When querying a subgraph, either ID can be used, though it is generally suggested that the Deployment ID is used due to its ability to specify a specific version of a subgraph. - -Here are some key differences between the two IDs: ![](/img/subgraph-id-vs-deployment-id.png) - -## Deployment ID - -The Deployment ID is the IPFS hash of the compiled manifest file, which refers to other files on IPFS instead of relative URLs on the computer. For example, the compiled manifest can be accessed via: `https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQKXcNQQRdUvNRMGJiE2idoTu9fo5F5MRtKztH4WyKxED`. To change the Deployment ID, one can simply update the manifest file, such as modifying the description field as described in the [subgraph manifest documentation](https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md#13-top-level-api). - -When queries are made using a subgraph's Deployment ID, we are specifying a version of that subgraph to query. Using the Deployment ID to query a specific subgraph version results in a more sophisticated and robust setup as there is full control over the subgraph version being queried. However, this results in the need of updating the query code manually every time a new version of the subgraph is published. - -Example endpoint that uses Deployment ID: - -`https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/QmfYaVdSSekUeK6expfm47tP8adg3NNdEGnVExqswsSwaB` - -## Subgraph ID - -The Subgraph ID is a unique identifier for a subgraph. It remains constant across all versions of a subgraph. It is recommended to use the Subgraph ID to query the latest version of a subgraph, although there are some caveats. - -Be aware that querying using Subgraph ID may result in queries being responded to by an older version of the subgraph due to the new version needing time to sync. Also, new versions could introduce breaking schema changes. - -Example endpoint that uses Subgraph ID: `https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/FL3ePDCBbShPvfRJTaSCNnehiqxsPHzpLud6CpbHoeKW` diff --git a/website/pages/ha/querying/querying-from-an-application.mdx b/website/pages/ha/querying/querying-from-an-application.mdx deleted file mode 100644 index 30b6c2264d64..000000000000 --- a/website/pages/ha/querying/querying-from-an-application.mdx +++ /dev/null @@ -1,267 +0,0 @@ ---- -title: Querying from an Application ---- - -Once a subgraph is deployed to the Subgraph Studio or to The Graph Explorer, you will be given the endpoint for your GraphQL API that should look something like this: - -**Subgraph Studio (testing endpoint)** - -```sh -Queries (HTTP) -https://api.studio.thegraph.com/query/// -``` - -**Graph Explorer** - -```sh -Queries (HTTP) -https://gateway.thegraph.com/api//subgraphs/id/ -``` - -Using the GraphQL endpoint, you can use various GraphQL Client libraries to query the subgraph and populate your app with the data indexed by the subgraph. - -Here are a couple of the more popular GraphQL clients in the ecosystem and how to use them: - -## GraphQL clients - -### Graph client - -The Graph is providing it own GraphQL client, `graph-client` that supports unique features such as: - -- Cross-chain Subgraph Handling: Querying from multiple subgraphs in a single query -- [Automatic Block Tracking](https://github.com/graphprotocol/graph-client/blob/main/packages/block-tracking/README.md) -- [Automatic Pagination](https://github.com/graphprotocol/graph-client/blob/main/packages/auto-pagination/README.md) -- Fully typed result - -Also integrated with popular GraphQL clients such as Apollo and URQL and compatible with all environments (React, Angular, Node.js, React Native), using `graph-client` will give you the best experience for interacting with The Graph. - -Let's look at how to fetch data from a subgraph with `graphql-client`. - -To get started, make sure to install The Graph Client CLI in your project: - -```sh -yarn add -D @graphprotocol/client-cli -# or, with NPM: -npm install --save-dev @graphprotocol/client-cli -``` - -Define your query in a `.graphql` file (or inlined in your `.js` or `.ts` file): - -```graphql -query ExampleQuery { - # this one is coming from compound-v2 - markets(first: 7) { - borrowRate - cash - collateralFactor - } - # this one is coming from uniswap-v2 - pair(id: "0x00004ee988665cdda9a1080d5792cecd16dc1220") { - id - token0 { - id - symbol - name - } - token1 { - id - symbol - name - } - } -} -``` - -Then, create a configuration file (called `.graphclientrc.yml`) and point to your GraphQL endpoints provided by The Graph, for example: - -```yaml -# .graphclientrc.yml -sources: - - name: uniswapv2 - handler: - graphql: - endpoint: https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2 - - name: compoundv2 - handler: - graphql: - endpoint: https://api.thegraph.com/subgraphs/name/graphprotocol/compound-v2 - -documents: - - ./src/example-query.graphql -``` - -Running the following The Graph Client CLI command will generate typed and ready to use JavaScript code: - -```sh -graphclient build -``` - -Finally, update your `.ts` file to use the generated typed GraphQL documents: - -```tsx -import React, { useEffect } from 'react' -// ... -// we import types and typed-graphql document from the generated code (`..graphclient/`) -import { ExampleQueryDocument, ExampleQueryQuery, execute } from '../.graphclient' - -function App() { - const [data, setData] = React.useState() - - useEffect(() => { - execute(ExampleQueryDocument, {}).then((result) => { - setData(result?.data) - }) - }, [setData]) - return ( -
-
- logo -

Graph Client Example

-
- {data && ( -
- -
-