Skip to content

Commit

Permalink
more progress
Browse files Browse the repository at this point in the history
  • Loading branch information
PiVortex committed Oct 10, 2024
1 parent 19fed61 commit b3b8274
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 56 deletions.
14 changes: 7 additions & 7 deletions docs/3.tutorials/auction/2.1-frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ For starters, let's take a look at how the code in the frontend is structured by
| File | Description |
|----------------------------------|---------------------------------------------------------------------------------|
| **_app.js** | Responsible for rending the page, initiates the wallet object and adds it to global context |
| **index.js** | The main page where the projects components are loaded into and contains most of the logic for the application like viewing the state of the contract and logic for placing a bid |
| **index.js** | The main page where the project's components are loaded into and contains most of the logic for the application like viewing the state of the contract and logic for placing a bid |
| **near.js** | Contains the wallet class that has methods to interact with the wallet and blockchain |
| **context.js** | Holds the global context - the wallet object and the signed in account ID - that can be accessed anywhere |
| **context.js** | Holds the global context - the wallet object and the signed-in account ID - that can be accessed anywhere |
| **config.js** | Specifies the account ID of the auction contract |
| **Navigation.jsx** | A component that contains a button to sign users in and out of wallets |
| **Bid.jsx** | A component allowing a user to make a bid |
Expand All @@ -39,7 +39,7 @@ For starters, let's take a look at how the code in the frontend is structured by

## Specifying the contract

We have a config file that specifies the contract name of the auction that the frontend will interact with. There has been an example auction contract deployed and sepcfiied already but feel free to change the contract to your own auction contract you deployed.
We have a config file that specifies the contract name of the auction that the frontend will interact with. There has been an example auction contract deployed and specified already but feel free to change the contract to your own auction contract you deployed.

<Language value="javascript" language="javascript" showSingleFName={true}>
<Github fname="config.js"
Expand Down Expand Up @@ -68,7 +68,7 @@ The wallet object is initiated in the `app.js` file and its added to the global

:::tip Access keys

On NEAR, in additional to normal full access keys, we have `function-call access keys` that are given to applications to allow them to sign `non-payable` transactions on behalf of the user. This is so the wallet doesn't have to pop up for each non critical transaction, improving the user experience. When creating the wallet object you can decide to create an access key for the application to use. However, in this example we opt out since the main function - `bid` - we'll be calling is `payable`.
On NEAR, in additional to normal full access keys, we have `function-call access keys` that are given to applications to allow them to sign `non-payable` transactions on behalf of the user. This is so the wallet doesn't have to pop up for each non-critical transaction, improving the user experience. When creating the wallet object you can decide to create an access key for the application to use. However, in this example we opt out since the main function - `bid` - we'll be calling is `payable`.

You can read further about NEAR's key model [here](../../1.concepts/protocol/access-keys.md).

Expand All @@ -89,7 +89,7 @@ We add a sign-in and sign-out button in the `navigation` component to call the r

## Displaying the highest bid

To get the highest bid from the auction and who made it we call `get_highest_bid`. Since this method returns the highest bid in `yoctoNEAR` we divide by `10^24` to get the amount in NEAR.
To get the highest bid from the auction and who made it we call `get_highest_bid`. Since this function returns the highest bid in `yoctoNEAR` we divide by `10^24` to get the amount in NEAR.

<Language value="javascript" language="javascript">
<Github fname="index.js"
Expand Down Expand Up @@ -141,7 +141,7 @@ The contract stores the end time of the auction in the number of nanoseconds sin

## Making a bid

To make a bid we make a call to the contract using the `bid` method. We specify the deposit amount in `yoctoNEAR` which will be the bid amount. The input box will take the bid amount in NEAR so we multiply by `10^24` to get the correct amount to send. We also specify the amount of gas to attatch to the transaction, here we are attaching 30Tgas which is more than enough for the transaction to go through, we are refuned any unused gas anwyway.
To make a bid we make a call to the contract using the `bid` function. We specify the deposit amount in `yoctoNEAR` which will be the bid amount. The input box will take the bid amount in NEAR so we multiply by `10^24` to get the correct amount to send. We also specify the amount of gas to attach to the transaction, here we are attaching 30Tgas which is more than enough for the transaction to go through, we are refunded any unused gas anyway.

Here, since the user is changing the state of the contract, not just viewing it, the user needs to sign the transaction. Thus the wallet will pop up displaying the transaction details.

Expand All @@ -158,7 +158,7 @@ Here, since the user is changing the state of the contract, not just viewing it,

## Claiming the auction

Once the auction is over (the current time is greater than the end time) the auction can be claimed. At this point, the timer will be hidden and a button to claim the auction will be displayed. Once clicked the `claim` method will be called on the auction contract to send the highest bidder the NFT and the auctioneer the FTs.
Once the auction is over (the current time is greater than the end time) the auction can be claimed. At this point, the timer will be hidden and a button to claim the auction will be displayed. Once clicked the `claim` function will be called on the auction contract to send the highest bidder the NFT and the auctioneer the FTs.

<Language value="javascript" language="javascript" showSingleFName={true}>
<Github fname="index.js"
Expand Down
105 changes: 104 additions & 1 deletion docs/3.tutorials/auction/2.2-indexing.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,107 @@
---
id: indexing-historical-data
title: Indexing Historical Data
---
---

import {Github, Language} from "@site/src/components/codetabs"

In our frontend, we can easily display the previous bid since it's stored in the contract's state. However, we're unable to see previous bids to the auction. An indexer is used to fetch historical data from the blockchain and store it in a database. Since indexers can take a while to set up and can be expensive to run, we will use a pre-defined API endpoint provided by NEAR Blocks to query an indexer they run that will fetch us the data we need.

---

## NEAR Blocks API key

NEAR Blocks provides a free tier that allows you to make 6 calls per minute, which will be plenty for our use case. To get an API key, head over to https://dash.nearblocks.io/user/overview and sign up. Once signed go to `API Keys` then click `Add key` and give it whatever name you like.

We'll create a new file named `.env.local` to store our API key.

```env
API_KEY=YOUR_API_KEY_GOES_HERE
```

We put the API key in a `.env.local` file so the user cannot access it in the browser and use our key elsewhere. We should also add `.env.local` to our `.gitignore` file so it is not pushed to GitHub.

---

## Calling the API endpoint

NextJS allows us to easily create server-side functions with API routes. We need to make this API call on the server-side rather than the client side so as to not expose our API key. We'll create a new file in src/pages/api named `getBidHistory.js`. Here we'll define our function to get the bid history.

<Language value="javascript" language="javascript" showSingleFName={true}>
<Github fname="getBidHistory.js"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/frontends/01-frontend/src/pages/api/getBidHistory.js#L1-L13"
start="1" end="13" />
</Language>

Here we are retrieving the auction contract ID from the API route call and then calling the NEAR Blocks API. This specific API endpoint allows us to retrieve transactions made to a specific contract calling a specific function. Some details are worth discussing here:

- We pass the account ID of the auction contract, which is `basic-auction-example.testnet` in the example repo.
- We specify the function name on the auction contract that we want the transactions for, in our case it will be `bid`
- We'll receive a JSON object of up to 25 transactions, ordered by the most recent first.
- We pass our API key to authenticate the request.

---

## Retrieving the bids from the API result

From our API call, we receive a JSON object containing up to 25 transactions made to the bid function on the auction contract.

<Language value="javascript" language="javascript" showSingleFName={true}>
<Github fname="getBidHistory.js"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/frontends/01-frontend/src/pages/api/getBidHistory.js#L15-L43"
start="15" end="43" />
</Language>

We want to display the 5 most recent valid bids. To do this we loop through each transaction and check whether the transaction was successful by checking `receipt_outcome.status` is `true`. If so we check the first action (since there should only be one function call action in this case) and store the `deposit`, which is equal to the bid amount, and store the `predecessor account ID`, which is the account ID of the bidder.

Once we have 5 valid bids we can stop looping through the transactions.

Note that in our example if the previous 25 bids were invalid the API will return an empty array. The function could be set up such that it calls the API again to get the new page of transactions if this is the case.


:::tip Learn More

You can read more about transaction actions in this section of the documentation: [Actions](../../1.concepts/protocol/transaction-anatomy.md#Actions)

:::

---

## Using the API Route

In our main page, we'll define a function to call the API route we just created. This function will be called each time the page timer reaches zero.

<Language value="javascript" language="javascript" showSingleFName={true}>
<Github fname="getBidHistory.js"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/frontends/01-frontend/src/pages/index.js#L84-L92"
start="84" end="92" />
</Language>

The `pastBids` will then be passed into the `Bid` component to be displayed.

---

You may like to explore NEAR Blocks APIs further to see what other data you can retrieve from the blockchain. You can find the documentation at https://api.nearblocks.io/api-docs/

---

## Using the frontend

Now we have implemented the frontend and indexer you can go ahead and actually use the frontend. From the root of the frontend directory run the following commands:

```bash
# install dependencies
npm install

# run the frontend locally
npm run dev
```

---

## Conclusion

In this short part of the tutorial, we've added the ability to display the previous 5 valid bids made to the auction contract. In doing this we learned how to interact with the NEAR Blocks APIs to retrieve historical data from the blockchain and how to make server-side calls in NextJS to not expose our API key. Now we have a pretty good frontend that displays all the information we need about the auction contract.

In the [next section of the tutorial](./3.1-nft.md) we're going to improve our contract by adding primitives to the auction contract starting with adding NFTs as a prize.

26 changes: 13 additions & 13 deletions docs/3.tutorials/auction/3.1-nft.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ When we create an auction we need to list the NFT. To specify which NFT is being
<TabItem value="js" label="🌐 JavaScript">

<Github fname="main.ava.js" language="javascript"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/03-owner-claims-winner-gets-nft/src/contract.ts#L22-L28"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/02-winner-gets-nft/src/contract.ts#L22-L28"
start="22" end="28" />

</TabItem>

<TabItem value="rust" label="πŸ¦€ Rust">

<Github fname="lib.rs" language="rust"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/src/lib.rs#L32-L49"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/src/lib.rs#L32-L49"
start="32" end="49" />

Note that `token_id` is of type `TokenId` which is a String type alias that the NFT standards use for future-proofing.
Expand All @@ -49,8 +49,8 @@ When the method `claim` is called the NFT needs to be transferred to the highest
<TabItem value="js" label="🌐 JavaScript">

<Github fname="contract.ts" language="javascript"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/03-owner-claims-winner-gets-nft/src/contract.ts#L68-L70"
start="68" end="70" />
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/02-winner-gets-nft/src/contract.ts#L58-L60"
start="58" end="60" />

In near-sdk-js we cannot transfer the NFT and send the $NEAR independently so we will chain the promises.

Expand All @@ -64,10 +64,10 @@ When the method `claim` is called the NFT needs to be transferred to the highest

<Language value="rust" language="rust">
<Github fname="lib.rs"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/src/lib.rs#L93-L96"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/src/lib.rs#L93-L96"
start="93" end="96" />
<Github fname="ext.rs"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/src/ext.rs"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/src/ext.rs"
start="2" end="10" />
</Language>

Expand Down Expand Up @@ -98,15 +98,15 @@ To deploy the NFT contract, this time we're going to use `dev deploy` which crea
<TabItem value="js" label="🌐 JavaScript">

<Github fname="main.ava.js" language="javascript"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/03-owner-claims-winner-gets-nft/sandbox-test/main.ava.js#L24-L25"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L24-L25"
start="24" end="25" />

</TabItem>

<TabItem value="rust" label="πŸ¦€ Rust">

<Github fname="test_basics.rs" language="rust"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/tests/test_basics.rs#L30-L39"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L30-L39"
start="30" end="39" />

</TabItem>
Expand All @@ -124,15 +124,15 @@ To start a proper auction the auction contract should own an NFT. To do this the
<TabItem value="js" label="🌐 JavaScript">

<Github fname="main.ava.js" language="javascript"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/03-owner-claims-winner-gets-nft/sandbox-test/main.ava.js#L28-L39"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L28-L39"
start="28" end="39" />

</TabItem>

<TabItem value="rust" label="πŸ¦€ Rust">

<Github fname="test_basics.rs" language="rust"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/tests/test_basics.rs#L42-L60"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L42-L60"
start="42" end="60" />

</TabItem>
Expand All @@ -150,15 +150,15 @@ After `claim` is called, the test should verify that the auction winner now owns
<TabItem value="js" label="🌐 JavaScript">

<Github fname="main.ava.js" language="javascript"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/03-owner-claims-winner-gets-nft/sandbox-test/main.ava.js#L105-L106"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L105-L106"
start="105" end="106" />

</TabItem>

<TabItem value="rust" label="πŸ¦€ Rust">

<Github fname="test_basics.rs" language="rust"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/03-owner-claims-winner-gets-nft/tests/test_basics.rs#L151-L164"
url="https://github.com/near-examples/auctions-tutorial/blob/reorg-auction/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L151-L164"
start="151" end="164" />

</TabItem>
Expand All @@ -181,4 +181,4 @@ You can also just buy an NFT with testnet $NEAR on a testnet marketplace like [M

## Conclusion

In this part of the tutorial we have added NFTs as a reward which has taught us how to interact with NFT standards, make cross-contract calls and test multiple contracts that interact with each other in workspaces. In the [next part](./4-ft.md) we'll learn how to interact with fungible token standards by adapting the auction to receive bids in FTs. This will allow users to launch auctions in different tokens, including stablecoins.
In this part of the tutorial we have added NFTs as a reward which has taught us how to interact with NFT standards, make cross-contract calls and test multiple contracts that interact with each other in workspaces. In the [next part](./3.2-ft.md) we'll learn how to interact with fungible token standards by adapting the auction to receive bids in FTs. This will allow users to launch auctions in different tokens, including stablecoins.
Loading

0 comments on commit b3b8274

Please sign in to comment.