diff --git a/docs/.vuepress/config.ts b/docs/.vuepress/config.ts index 76937d92c39..3bc894e4f96 100644 --- a/docs/.vuepress/config.ts +++ b/docs/.vuepress/config.ts @@ -297,6 +297,10 @@ export default defineUserConfig({ "/build/quickstart/quickstart_chains/terra.html": "/build/quickstart/quickstart_chains/cosmos.html", "/run_publish/ipfs.html": "/miscellaneous/ipfs.html", + "/run_publish/query.html": "/run_publish/query/graphql.html", + "/run_publish/aggregate.html": "/run_publish/query/aggregate.html", + "/run_publish/subscription.html": + "/run_publish/query/subscription.html", }; return { ...redirects, @@ -304,10 +308,10 @@ export default defineUserConfig({ app.pages.map(({ path }) => [ path.replace( "/subquery_network/node_operators/indexers/", - "/subquery_network/indexers/", + "/subquery_network/indexers/" ), path, - ]), + ]) ), }; }, diff --git a/docs/.vuepress/public/assets/img/run_publish/integration_ecosystem.png b/docs/.vuepress/public/assets/img/run_publish/integration_ecosystem.png new file mode 100644 index 00000000000..24a39e32611 Binary files /dev/null and b/docs/.vuepress/public/assets/img/run_publish/integration_ecosystem.png differ diff --git a/docs/.vuepress/sidebar.ts b/docs/.vuepress/sidebar.ts index 165bb5694e2..3a064d6a06a 100644 --- a/docs/.vuepress/sidebar.ts +++ b/docs/.vuepress/sidebar.ts @@ -442,19 +442,22 @@ export const getSidebar = (locale: string) => }, `${locale}/run_publish/cli.md`, { - text: "Querying", + text: "Query and Access Data", + link: `${locale}/run_publish/query/query.md`, + collapsible: true, children: [ + `${locale}/run_publish/query/query.md`, { text: "GraphQL", children: [ - `${locale}/run_publish/query.md`, - `${locale}/run_publish/aggregate.md`, - `${locale}/run_publish/subscription.md`, + `${locale}/run_publish/query/graphql.md`, + `${locale}/run_publish/query/aggregate.md`, + `${locale}/run_publish/query/subscription.md`, ], }, { text: "Other Tools", - children: [`${locale}/run_publish/other_tools/metabase.md`], + children: [`${locale}/run_publish/query/other_tools/metabase.md`], }, ], }, diff --git a/docs/academy/herocourse/module5.md b/docs/academy/herocourse/module5.md index 2002d77c118..ecd1f53515b 100644 --- a/docs/academy/herocourse/module5.md +++ b/docs/academy/herocourse/module5.md @@ -92,7 +92,7 @@ Slots are a feature in SubQuery's Managed Service that are the equivalent of a d Once your project is deployed, access your project and run your desired query in the playground. For more information, visit: -- [Query your Project using GraphQL in SubQuery Explorer](/run_publish/query.md) +- [Query your Project using GraphQL in SubQuery Explorer](/run_publish/query/graphql.md) #### Step 6: Query via the API diff --git a/docs/build/graph-migration.md b/docs/build/graph-migration.md index 1acf0f987a5..4a2851ae978 100644 --- a/docs/build/graph-migration.md +++ b/docs/build/graph-migration.md @@ -517,7 +517,7 @@ SubQuery does not support historical metadata querying. However `deployments` wi - SubQuery has a larger support for query pagination. You have the options of using `first` and `offset`, or `cursors` on `edges`. - Note that [cursor-based pagination](https://graphql.org/learn/pagination/#pagination-and-edges) is far more efficient compared to `first`/`offset`/`after` pagination -- SubQuery supports [advanced aggregate functions](../run_publish/aggregate.md) to allow you to perform a calculation on a set of values during your query. +- SubQuery supports [advanced aggregate functions](../run_publish/query/aggregate.md) to allow you to perform a calculation on a set of values during your query. ## What's Next? diff --git a/docs/build/project-upgrades.md b/docs/build/project-upgrades.md index f186cbecfb4..7db2f12ef96 100644 --- a/docs/build/project-upgrades.md +++ b/docs/build/project-upgrades.md @@ -79,5 +79,5 @@ Other notes: - Only supports PostgreSQL stores - Migrations will not succeed `--unfinalizedBlocks` is enabled - Does not support Enum modification -- [GraphQL subscriptions](../run_publish/subscription.md) are not supported +- [GraphQL subscriptions](../run_publish/query/subscription.md) are not supported - [Rewind](../run_publish/historical.md) will only be supported if the new schema does not drop any `fields` or `entity`. Note that [automated historical state tracking](../run_publish/historical.md) must be enabled to support rewind. diff --git a/docs/quickstart/quickstart_chains/polkadot-astar.md b/docs/quickstart/quickstart_chains/polkadot-astar.md index 813d4f23001..92bb2384bd9 100644 --- a/docs/quickstart/quickstart_chains/polkadot-astar.md +++ b/docs/quickstart/quickstart_chains/polkadot-astar.md @@ -191,7 +191,7 @@ Navigate to the default mapping function in the `src/mappings` directory. There type ApproveCallArgs = [AccountId, Balance]; export async function handleWasmCall( - call: WasmCall, + call: WasmCall ): Promise { logger.info(`Processing WASM Call at ${call.blockNumber}`); const approval = new Approval(`${call.blockNumber}-${call.idx}`); @@ -214,7 +214,7 @@ The `handleWasmCall` function receives event data from the WASM execution enviro ```ts export async function handleBondAndStake(event: SubstrateEvent): Promise { logger.info( - `Processing new Dapp Staking Bond and Stake event at ${event.block.block.header.number}`, + `Processing new Dapp Staking Bond and Stake event at ${event.block.block.header.number}` ); const { event: { @@ -265,7 +265,7 @@ query { ``` ::: tip -There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query.md). +There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query/graphql.md). ::: You should see results similar to below: diff --git a/docs/quickstart/quickstart_chains/polkadot-kilt.md b/docs/quickstart/quickstart_chains/polkadot-kilt.md index 6fa6dfdd648..3544ca3f8a4 100644 --- a/docs/quickstart/quickstart_chains/polkadot-kilt.md +++ b/docs/quickstart/quickstart_chains/polkadot-kilt.md @@ -83,10 +83,10 @@ Navigate to the default mapping function in the `src/mappings` directory. There ```ts export async function handleAttestationCreated( - event: SubstrateEvent, + event: SubstrateEvent ): Promise { logger.info( - `New attestation created at block ${event.block.block.header.number}`, + `New attestation created at block ${event.block.block.header.number}` ); // A new attestation has been created.\[attester ID, claim hash, CType hash, (optional) delegation ID\] const { @@ -112,10 +112,10 @@ export async function handleAttestationCreated( } export async function handleAttestationRevoked( - event: SubstrateEvent, + event: SubstrateEvent ): Promise { logger.info( - `New attestation revoked at block ${event.block.block.header.number}`, + `New attestation revoked at block ${event.block.block.header.number}` ); // An attestation has been revoked.\[account id, claim hash\] const { @@ -138,7 +138,7 @@ export async function handleAttestationRevoked( export async function handleDailyUpdate( date: Date, - type: "CREATED" | "REVOKED", + type: "CREATED" | "REVOKED" ): Promise { const id = date.toISOString().slice(0, 10); let aggregation = await Aggregation.get(id); @@ -194,7 +194,7 @@ query { ``` ::: tip -There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query.md). +There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query/graphql.md). ::: You should see results similar to below: diff --git a/docs/quickstart/quickstart_chains/polkadot-moonbeam.md b/docs/quickstart/quickstart_chains/polkadot-moonbeam.md index e9fd7ec5a45..3c3186117d7 100644 --- a/docs/quickstart/quickstart_chains/polkadot-moonbeam.md +++ b/docs/quickstart/quickstart_chains/polkadot-moonbeam.md @@ -136,7 +136,7 @@ Navigate to the default mapping function in the `src/mappings` directory. There ```ts export async function handleCollatorJoined( - call: SubstrateExtrinsic, + call: SubstrateExtrinsic ): Promise { //We added a logger to the top of this function, in order to see the block number of the event we are processing. logger.info(`Processing SubstrateEvent at ${call.block.block.header.number}`); @@ -152,7 +152,7 @@ export async function handleCollatorJoined( } export async function handleCollatorLeft( - call: SubstrateExtrinsic, + call: SubstrateExtrinsic ): Promise { //We added a logger to the top of this function, in order to see the block number of the event we are processing. logger.info(`Processing SubstrateCall at ${call.block.block.header.number}`); @@ -168,7 +168,7 @@ The `handleCollatorJoined` and `handleCollatorLeft` functions receives Substrate export async function erc20Transfer( event: MoonbeamEvent< [string, string, BigNumber] & { from: string; to: string; value: BigNumber } - >, + > ): Promise { //We added a logger to the top of this function, in order to see the block number of the event we are processing. logger.info(`Processing MoonbeamEvent at ${event.blockNumber.toString()}`); @@ -209,7 +209,7 @@ query { ``` ::: tip -There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query.md). +There is a _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and helps you find what entities and methods you can query. To learn more about the GraphQL Query language [here](../../run_publish/query/graphql.md). ::: You should see results similar to below: diff --git a/docs/quickstart/snippets/query-intro.md b/docs/quickstart/snippets/query-intro.md index d1595b469d0..03ea9df71de 100644 --- a/docs/quickstart/snippets/query-intro.md +++ b/docs/quickstart/snippets/query-intro.md @@ -8,4 +8,4 @@ Next, let's query our project. Follow these three simple steps to query your Sub 3. Find the _Docs_ tab on the right side of the playground which should open a documentation drawer. This documentation is automatically generated and it helps you find what entities and methods you can query. -Try the following queries to understand how it works for your new SubQuery starter project. Don’t forget to learn more about the [GraphQL Query language](../../run_publish/query.md). +Try the following queries to understand how it works for your new SubQuery starter project. Don’t forget to learn more about the [GraphQL Query language](../../run_publish/query/graphql.md). diff --git a/docs/quickstart/whats-next.md b/docs/quickstart/whats-next.md index 0f1b43610e2..de74b202d04 100644 --- a/docs/quickstart/whats-next.md +++ b/docs/quickstart/whats-next.md @@ -12,7 +12,7 @@ Now that you have a clear understanding of how to build a basic SubQuery project - [Multi-chain indexing support](../build/multi-chain.md) - SubQuery allows you to index data from across different layer-1 networks into the same database, this allows you to query a single endpoint to get data for all supported networks. - [Dynamic Data Sources](../build/dynamicdatasources.md) - When you want to index factory contracts, for example on a DEX or generative NFT project. - - [GraphQL Subscriptions](../run_publish/subscription.md) - Build more reactive front end applications that subscribe to changes in your SubQuery project. + - [GraphQL Subscriptions](../run_publish/query/subscription.md) - Build more reactive front end applications that subscribe to changes in your SubQuery project. - Find out **how to build a performant SubQuery project and avoid common mistakes** in [Project Optimisation](../build/optimisation.md). diff --git a/docs/run_publish/optimisation.md b/docs/run_publish/optimisation.md index 65c7a4edd7f..3849c603773 100644 --- a/docs/run_publish/optimisation.md +++ b/docs/run_publish/optimisation.md @@ -14,7 +14,7 @@ SubQuery runs well behind an API gateway or a DDOS mitigation service. For any p ## Request Caching -Although @subql/node does not natively provide any default request level caching, one of the easiest ways to increase performance when the number of users hitting your SubQuery project increases is by adding a cache in front of the GraphQL endpoint with a basic TTL of a few seconds (depending on how stale you want to allow your data). Most cloud providers offer simple to setup and manage caching solutions (e.g. Redis) that will work well with the GraphQL api endpoints that we provide. If you're worried about stale data affecting your user's experience, by leveraging [GraphQl subscriptions](./subscription.md) you can ensure that the most recent data is never affected by the cache while older, slower data is mostly from the cache. Additionally, consider different TTLs for each different entity. +Although @subql/node does not natively provide any default request level caching, one of the easiest ways to increase performance when the number of users hitting your SubQuery project increases is by adding a cache in front of the GraphQL endpoint with a basic TTL of a few seconds (depending on how stale you want to allow your data). Most cloud providers offer simple to setup and manage caching solutions (e.g. Redis) that will work well with the GraphQL api endpoints that we provide. If you're worried about stale data affecting your user's experience, by leveraging [GraphQl subscriptions](./query/subscription.md) you can ensure that the most recent data is never affected by the cache while older, slower data is mostly from the cache. Additionally, consider different TTLs for each different entity. ## Database Configuration @@ -34,6 +34,6 @@ GraphQL is extremely powerful, but one of the downsides is that it allows users - `--query-timeout` is a flag that will restrict the time each query will be allowed to run for, [read more here](./references.md#query-timeout). - `--max-connection` is a flag that will restrict the number of simultaneous DB connections created by the query endpoint, [read more here](./references.md#max-connection). - `--query-limit` is a flag that allows you to limit the number of results returned by any query and enforce pagination, [read more here](./references.md#query-limit). -- `--unsafe` is a flag that enables some advanced features like [GraphQL aggregations](./aggregate.md), these may have performance impacts, [read more here](./references.md#unsafe-query-service) +- `--unsafe` is a flag that enables some advanced features like [GraphQL aggregations](./query/aggregate.md), these may have performance impacts, [read more here](./references.md#unsafe-query-service) You should also consider reading this excellent guide from Apollo on how they recommend you secure your [GraphQL API from malicious queries](https://www.apollographql.com/blog/graphql/security/securing-your-graphql-api-from-malicious-queries/). diff --git a/docs/run_publish/publish.md b/docs/run_publish/publish.md index 783fd724810..693cca74e3f 100644 --- a/docs/run_publish/publish.md +++ b/docs/run_publish/publish.md @@ -247,7 +247,7 @@ Once your deployment has succesfully completed and our nodes have indexed your d ![Project being deployed and synced](/assets/img/run_publish/projects_deploy_sync.png) -Alternatively, you can click on the three dots next to the title of your project, and view it on SubQuery Explorer. There you can use the in browser playground to get started - [read more about how to use our Explorer's GraphQL playground here](../run_publish/query.md). +Alternatively, you can click on the three dots next to the title of your project, and view it on SubQuery Explorer. There you can use the in browser playground to get started - [read more about how to use our Explorer's GraphQL playground here](../run_publish/query/graphql.md). ![Projects in SubQuery Explorer](/assets/img/run_publish/projects_explorer.png) diff --git a/docs/run_publish/aggregate.md b/docs/run_publish/query/aggregate.md similarity index 94% rename from docs/run_publish/aggregate.md rename to docs/run_publish/query/aggregate.md index 70dea973d85..433a9ba7786 100644 --- a/docs/run_publish/aggregate.md +++ b/docs/run_publish/query/aggregate.md @@ -27,7 +27,7 @@ SubQuery provides the following aggregate functions when in unsafe mode: SubQuery's implementation of aggregate functions is based on [pg-aggregates](https://github.com/graphile/pg-aggregates), you can find more information there. ::: warning Important -Please note that you must enable the `--unsafe` flag on the query service in order to use these functions. [Read more](./references.md#unsafe-query-service). +Please note that you must enable the `--unsafe` flag on the query service in order to use these functions. [Read more](../references.md#unsafe-query-service). Also, note that the `--unsafe` command will prevent your project from being run in the SubQuery Network, and you must contact support if you want this command to be run with your project in [SubQuery's managed service](https://managedservice.subquery.network). ::: diff --git a/docs/run_publish/query.md b/docs/run_publish/query/graphql.md similarity index 76% rename from docs/run_publish/query.md rename to docs/run_publish/query/graphql.md index bbeeda60ee5..5492ce9b453 100644 --- a/docs/run_publish/query.md +++ b/docs/run_publish/query/graphql.md @@ -2,14 +2,14 @@ ::: info Coming from the Graph? -You may want to take a look at the information we have [on the differences](../build/graph-migration.md#graphql-query-differences) between SubQuery's GraphQL library, and The Graph. +You may want to take a look at the information we have [on the differences](../../build/graph-migration.md#graphql-query-differences) between SubQuery's GraphQL library, and The Graph. ::: You can follow the [official GraphQL guide here](https://graphql.org/learn/) to learn more about GraphQL, how it works, and how to use it: -- There are libraries to help you implement GraphQL in [many different languages](https://graphql.org/code/) - we recommend [Apollo Client](https://www.apollographql.com/docs/react/) as it will allow a [seamless migration to our decentralised network](../subquery_network/publish.md#changes-to-your-dapp) when you publish your project in the future. -- You will want to review advice on how to [structure your GraphQL queries to maximise performance](../build/optimisation.md#query-performance-advice). +- There are libraries to help you implement GraphQL in [many different languages](https://graphql.org/code/) - we recommend [Apollo Client](https://www.apollographql.com/docs/react/) as it will allow a [seamless migration to our decentralised network](../../subquery_network/publish.md#changes-to-your-dapp) when you publish your project in the future. +- You will want to review advice on how to [structure your GraphQL queries to maximise performance](../../build/optimisation.md#query-performance-advice). - For an in-depth learning experience with practical tutorials, see [How to GraphQL](https://www.howtographql.com/). - Check out the free online course, [Exploring GraphQL: A Query Language for APIs](https://www.edx.org/course/exploring-graphql-a-query-language-for-apis). diff --git a/docs/run_publish/other_tools/metabase.md b/docs/run_publish/query/other_tools/metabase.md similarity index 89% rename from docs/run_publish/other_tools/metabase.md rename to docs/run_publish/query/other_tools/metabase.md index e14cc846be7..8145b33a552 100644 --- a/docs/run_publish/other_tools/metabase.md +++ b/docs/run_publish/query/other_tools/metabase.md @@ -6,9 +6,9 @@ The objective of this guide is to show you how to analyse data from any SubQuery :::warning Automated Historical State Tracking -When running your project for the sole purpose of visualising in Metabase, we strongly recommending running your project with [Automated Historical State Tracking](../historical.md) disabled. +When running your project for the sole purpose of visualising in Metabase, we strongly recommending running your project with [Automated Historical State Tracking](../../historical.md) disabled. -Automated Historical State Tracking alters the underlying DB tables to manage state tracking for you automatically. However this may make things complicated for Metabase visualisations. You can read more about these alterations [here](../historical.md#db-schema). +Automated Historical State Tracking alters the underlying DB tables to manage state tracking for you automatically. However this may make things complicated for Metabase visualisations. You can read more about these alterations [here](../../historical.md#db-schema). ::: @@ -16,7 +16,7 @@ At a high level, there is no specific configuration required to ensure compatibi For that reason, visualising data in Metabase is not supported in SubQuery decentralised network or Managed Service, you must self host and run your SubQuery Indexing project. -You will want to follow the guide on how to run your [SubQuery indexing project locally](../run.md#running-subquery-locally). Please pay attention to what you set as your Postgres database host, port, username, and password. +You will want to follow the guide on how to run your [SubQuery indexing project locally](../../run.md#running-subquery-locally). Please pay attention to what you set as your Postgres database host, port, username, and password. ## Configuring Metabase @@ -28,7 +28,7 @@ The installation steps are thoroughly documented, ensuring a seamless configurat ![](/assets/img/run_publish/metabase/metabase-database-connection.png) -If you are running your indexer project [locally](../run.md) through Docker, all the requisite information can be found in the `docker-compose.yml` file. When you provide the correct credentials, Metabase will attempt to establish a connection. It will only proceed if the connection is successful. This connection allows Metabase to access the indexed blockchain data, enabling robust analysis and visualisation capabilities. +If you are running your indexer project [locally](../../run.md) through Docker, all the requisite information can be found in the `docker-compose.yml` file. When you provide the correct credentials, Metabase will attempt to establish a connection. It will only proceed if the connection is successful. This connection allows Metabase to access the indexed blockchain data, enabling robust analysis and visualisation capabilities. ## Browse Data diff --git a/docs/run_publish/query/query.md b/docs/run_publish/query/query.md new file mode 100644 index 00000000000..fcb30c2f010 --- /dev/null +++ b/docs/run_publish/query/query.md @@ -0,0 +1,23 @@ +# Query and Access Data from SubQuery SDK + +The default way that most query SubQuery Indexing SDK projects is by the excellent [GraphQL Query service](./graphql.md). + +Native builds of SubQuery running in [Docker](../run.md#using-docker) will automatically include query service (`subql/query`). If you run it locally, you will also [likely run a query service](../run.md#running-the-query-service) instance. + +Both the decentralised SubQuery Network and the SubQuery Managed Service only provide access to SubQuery SDK indexing projects via the GraphQL endpoints exposed by the query service. + +**Please see the docs for how to query your SubQuery project [here](./graphql.md)**. + +## Integrations with other Developer Tools + +SubQuery is open-source, and we are busy creating a rich ecosytem of developer tools that it works well with. + +We now have guides to expose SubQuery data to the following locations. + +- [GraphQL](./graphql.md) - the default query pattern. +- [GraphQL Subscriptions](./subscription.md) - subscribe to updated data as soon as it is indexed. +- [Direct Postgres Access](../run.md#connect-to-database) - you can directly connect to the Postgres data from any other tool or service. +- [Metabase](./other_tools/metabase.md) - an industry leading open-source and free data visualisation and business intelligence tool. +- [CSV Export](../references.md#csv-out-dir) - export indexed datasets to CSV files easily. + +![Integration Ecosystem](/assets/img/run_publish/integration_ecosystem.png) diff --git a/docs/run_publish/subscription.md b/docs/run_publish/query/subscription.md similarity index 100% rename from docs/run_publish/subscription.md rename to docs/run_publish/query/subscription.md diff --git a/docs/run_publish/references.md b/docs/run_publish/references.md index f7868e698e2..5d7d4d83a6a 100644 --- a/docs/run_publish/references.md +++ b/docs/run_publish/references.md @@ -394,7 +394,7 @@ In the case where Worker C completes its fetch prior to Worker A and B, it will ### --aggregate -**Boolean (default: `true`)** - Enables or disables the GraphQL aggregation feature, [read more about this here](../run_publish/aggregate.md). +**Boolean (default: `true`)** - Enables or disables the GraphQL aggregation feature, [read more about this here](../run_publish/query/aggregate.md). ### --disable-hot-schema @@ -480,11 +480,11 @@ We use the [graphql-query-complexity](https://www.npmjs.com/package/graphql-quer ### --subscription -**Boolean** - This flag enables [GraphQL Subscriptions](./subscription.md), to enable this feature requires `subql-node` also enable `--subscription`. +**Boolean** - This flag enables [GraphQL Subscriptions](./query/subscription.md), to enable this feature requires `subql-node` also enable `--subscription`. ### --unsafe (Query Service) -**Boolean** - This flag enables certain aggregation functions including sum, max, avg and others. Read more about this feature [here](../run_publish/aggregate.md). These are disabled by default for database performance reasons. +**Boolean** - This flag enables certain aggregation functions including sum, max, avg and others. Read more about this feature [here](../run_publish/query/aggregate.md). These are disabled by default for database performance reasons. ### --version diff --git a/docs/subquery_network/publish.md b/docs/subquery_network/publish.md index 1b9186cd90d..3cd641809bd 100644 --- a/docs/subquery_network/publish.md +++ b/docs/subquery_network/publish.md @@ -25,7 +25,7 @@ The SubQuery Network is the future of web3 infrastructure, it allows you to comp ## Prerequisites for your project running on Kepler -1. Kepler does not support GraphQL subscriptions, so you can't enable the `--subscription` [command line argument](../run_publish/subscription.md) +1. Kepler does not support GraphQL subscriptions, so you can't enable the `--subscription` [command line argument](../run_publish/query/subscription.md) 2. Your client application (the one that will query data from Kepler) must be able to run a JS library 3. Your project can generate stable proof of indexing results. This means you should avoid: 1. Random ordered DB operations, e.g. avoid using `Promise.all()` in your mapping functions.