In this tutorial, you'll use Shopify Functions to apply the discount specified in the `GateConfiguration`. The server-side validation that's implemented in this tutorial prevents users from receiving applicable gated discounts without passing the gate.
This is the last part of a tutorial series to build a tokengating app. Complete the previous tutorials before starting this tutorial:
* [Create gates in the admin UI using the Gates API](/docs/apps/build/blockchain/tokengating/build-a-tokengating-app/create-gates-admin)
* [Show gates on the storefront](/docs/apps/build/blockchain/tokengating/build-a-tokengating-app/show-gates-storefront)
## What you'll learn
* How to build a Shopify Function to apply the discount specified in the `GateConfiguration`
* Read and validate the HMAC signature stored as a cart attribute to verify your app's evaluation has not been tampered with. This will ensure your exclusive discount only goes to those who have met your gate requirements, as deemed by your app's evaluation.
## Requirements
- You've installed [Rust](https://www.rust-lang.org/tools/install).
On Windows, Rust requires the [Microsoft C++ Build Tools](https://docs.microsoft.com/en-us/windows/dev-environment/rust/setup). Make sure to select the **Desktop development with C++** workload when installing the tools.
- You've installed the [`wasm32-wasip1`](https://doc.rust-lang.org/rustc/platform-support/wasm32-wasip1.html) build target.
## Step 1: Initialize a product discount extension
To automatically apply exclusive discounts for buyers at checkout, add a [product discount function](/docs/api/functions/reference/product-discounts) as an extension to your app.
1. Navigate to your app directory.
2. Run the following command to create a new product discount extension:
Choose the `Rust` language option.
> Tip:
> Shopify Functions support any language that compiles to WebAssembly (Wasm), such as Rust, AssemblyScript, or TinyGo. You specify the Wasm template option when you're using a language other than Rust and can conform to the Wasm API. [Learn more about the Wasm API](/docs/apps/build/functions/programming-languages/webassembly-for-functions).
3. Navigate to `extensions/tokengating-function`
4. Replace your `Cargo.toml` file with the following:
5. Build the function's Wasm module.
If you encounter any errors, ensure that you've installed Rust and the `wasm32-wasip1` target.
## Step 2: Write the function logic
The function logic uses the input from the metafield that was defined when you [created the `GateConfiguration`](/docs/apps/build/blockchain/tokengating/build-a-tokengating-app/create-gates-admin). The following `_shopify_gate_context` cart attribute key is the gate context that was created in the [previous tutorial](/docs/apps/build/blockchain/tokengating/build-a-tokengating-app/show-gates-storefront#step-9-write-the-hmac-to-the-gate-context-for-later-consumption). This gate context is added here so that the function can determine whether the tokengated discount should be applied.
### Input Query
Copy the following code into `extensions/tokengating-function/src/run.graphql`.
This file defines the input for the function. Replace `tokengating-example-app` with the namespace that you used [when creating your `GateConfiguration`](/docs/apps/build/blockchain/tokengating/build-a-tokengating-app/create-gates-admin).
>Tip:
>For a complete list of available fields, refer to the [product discount input API](/docs/api/functions/reference/product-discounts/graphql/input).
### Function Logic
Your main discounting logic is located in `extensions/tokengating-function/src/main.rs` directory and written in Rust. By the time the code in this file executes, the input query above will have resolved and we have everything we need to accomplish our tasks within the function which are:
* Check that the automatic discount is relevant by reading its metafield for the `GateConfiguration` and only evaluating further if it matches the line item's `GateConfiguration`
* Verify the attached HMAC value, which is your app's attestation that this buyer has met the requirements to unlock the gate.
* If the above HMAC is verified, apply the discount by adding the corresponding [discount object](/docs/api/functions/reference/product-discounts/graphql/common-objects/discount) and returning it as the [function's output](/docs/apps/build/functions/input-output#output). Otherwise, the function will not apply the discount.
The following code will set up the function logic to determine if the gate is unlocked. Replace the code in `src/main.rs` with the following:
The code checks that your automatic discount is relevant to the cart's line items, and that your app has attested that the buyer has unlocked the gate. You can review the culmination of this logic by looking at the definition of `gate_unlocked`.
## Step 3: Deploy your function
1. Before deploying, ensure that the `api_version` in your `extensions/tokengating-function/shopify.extension.toml` is set to `unstable`. In the end, it should look like the following:
2. Because the `api_version` is `unstable`, you need to update the `schema.graphql` file. Navigate to the `extensions/tokengating-function/` directory and run the following code:
```bash
shopify app function schema > schema.graphql
```
3. Deploy your app along with the function.
## Step 4: Preview the function on a development store
To test your function, you need to make it available to your development store.
1. If you're developing a function in a language other than JavaScript or TypeScript, ensure you have configured `build.watch` in your [function extension configuration](/docs/api/functions/configuration#properties).
1. Navigate back to your app root:
1. Use the Shopify CLI [`dev` command](/docs/api/shopify-cli/app/app-dev) to start app preview:
You can keep the preview running as you work on your function. When you make changes to a watched file, Shopify CLI rebuilds your function and updates the function extension's drafts, so you can immediately test your changes.
1. Follow the CLI prompts to preview your app, and install it on your development store.
## Step 5: Test the function
1. Install the [Shopify GraphiQL app](https://shopify-graphiql-app.shopifycloud.com/) on your store.
1. In the GraphiQL app, in the **API Version** field, select the **unstable** version.
1. Find the ID of your function by executing the following query:
The result contains a node with your function's ID:
1. Copy the ID and navigate to `/web/api/create-discount.js` to replace the `YOUR_FUNCTION_ID`.
You've now:
* built an admin app for merchants to configure gates and the corresponding discount
* deployed a theme app extension to display those gate requirements to buyers along with a wallet connection experience
* used Shopify Functions to apply the discount when gated products are added to the cart
To see the function in action:
1. Navigate to your gated product's detail page and unlock the product.
2. Add the product to your cart.
3. View your cart and check that the exclusive discount is applied. Note that the discount should be visibile in the cart, even before initiating the checkout process.
## Developer tools and resources
To view all of the code used for the tokengating example app, you can download the source code.