Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose API url variables for ghostnet & mainnet #5

Merged
merged 25 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3663417
:wrench: update NFT example contracts for staging
Dec 15, 2023
d345f1c
:recycle: add apiURL variables && update constructor of GasStation class
Dec 18, 2023
ee914fd
:arrow_up: bump gas-station deps
Dec 18, 2023
f8be644
:bug: replace env var to Gas station API
Dec 19, 2023
07360bb
:recycle: review PR
Jan 8, 2024
bf392cc
:arrow_up: bump version of GS lib
Jan 8, 2024
3327be9
New permit contract with multiple admins
aguillon Jan 8, 2024
2a23b79
Minor change in the interface of examples/nft.
aguillon Dec 27, 2023
960af77
Merge pull request #7 from marigold-dev/contract-update
aguillon Jan 9, 2024
d454a08
New contract for stash too
aguillon Jan 9, 2024
5e19c75
Maintain a set of minted token ids and randomize minting and stashing
aguillon Jan 9, 2024
587112d
CSS shenanigans (thank you Jules)
aguillon Jan 9, 2024
b31ff1a
Pardon my French
aguillon Jan 9, 2024
9150161
Merge pull request #6 from marigold-dev/example-nft-qol
aguillon Jan 9, 2024
3dff258
index/comment: add comments
lykimq Jan 18, 2024
e8b4c10
Minting: add progress bar and formating code
lykimq Jan 18, 2024
0a7ed1f
Doc: add Readme for the example
lykimq Jan 18, 2024
997e0f5
Git: add ignore .d.ts and .js
lykimq Jan 18, 2024
53d47f8
HomePage: rework the introduction display on the webpage, formatting
lykimq Jan 18, 2024
e42b6e3
Doc: refine the README of the project
lykimq Jan 18, 2024
cdde4c7
Console_log: remove console_log, and formatting
lykimq Jan 22, 2024
36a91b2
StakingComponent: add progress bar for stashing button, add comments
lykimq Jan 22, 2024
e960a99
Merge pull request #8 from marigold-dev/quyen@staging
aguillon Jan 22, 2024
f3a7b00
:bug: fix progress bar display
Jan 22, 2024
6129ada
Version bump 0.0.8
aguillon Jan 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/docker-nft-ghostnet-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ jobs:
set -x
ls -last .
sed -i 's|http://localhost:8000|https://staging.gas-station-api.marigold.dev|g' ./examples/nft/.env
sed -i 's|KT1Re88VMEJ7TLHTkXSHQYZQTD3MP3k7j6Ar|KT199yuNkHQKpy331A6fvWJtQ1uan9uya2jx|g' ./examples/nft/.env
sed -i 's|KT1Rp1rgfwS25XrWU6fUnR8cw6KMZBhDvXdq|KT1MLMXwFEMcfByGbGcQ9ow3nsrQCkLbcRAu|g' ./examples/nft/.env
cat ./examples/nft/.env

- name: Set up Docker Buildx
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/examples/nft/node_modules/
/examples/nft/.svelte-kit/
node_modules
dist
dist
**/*d.ts
**/*.js
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Tezos Gas Station library

This library helps you
- use [Marigold's Gas Station API](https://github.com/marigold-dev/gas-station) in TypeScript
- create [TZIP-17 permit contracts](https://tzip.tezosagora.org/proposal/tzip-17/), which are FA2
contracts that can be manipulated by a 3rd party (such as the gas station API). Permits are signed
This library facilitates the following:
- Utilizing [Marigold's Gas Station API](https://github.com/marigold-dev/gas-station) in TypeScript.
- Creating [TZIP-17 permit contracts](https://tzip.tezosagora.org/proposal/tzip-17/), which are FA2
contracts capable of being manipulated by a 3rd party, such as the gas station API. Permits are signed
off-chain and can be posted and executed by anyone.

A toy webapp example is available in the `examples/` directory.
An example of a toy web app is provided in the `examples/nft` directory.

Contributions welcome at https://github.com/marigold-dev/gas-station-lib.
Feel free to contribute and provide feedback on https://github.com/marigold-dev/gas-station-lib.
6 changes: 3 additions & 3 deletions examples/nft/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PUBLIC_TZKT_API=https://api.ghostnet.tzkt.io
PUBLIC_TEZOS_RPC=https://ghostnet.smartpy.io
PUBLIC_GAS_STATION_API=http://localhost:8000/operation
PUBLIC_PERMIT=KT1Re88VMEJ7TLHTkXSHQYZQTD3MP3k7j6Ar # GHOSTNET : KT199yuNkHQKpy331A6fvWJtQ1uan9uya2jx
PUBLIC_STAKING_CONTRACT=KT1Rp1rgfwS25XrWU6fUnR8cw6KMZBhDvXdq # GHOSTNET : KT1MLMXwFEMcfByGbGcQ9ow3nsrQCkLbcRAu
PUBLIC_GAS_STATION_API=http://localhost:8000
PUBLIC_PERMIT=KT1HUdxmgZUw21ED9gqELVvCty5d1ff41p7J
PUBLIC_STAKING_CONTRACT=KT1VVotciVbvz1SopVfoXsxXcpyBBSryQgEn
PUBLIC_APP_BASE_URL=http://localhost:5173
85 changes: 81 additions & 4 deletions examples/nft/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,82 @@
Toy example of a webapp using a gas station API and a permit contract. The webapp lets you mint a
NFT and transfer it to a “staking” contract even if you have no tez in your wallet.
# Gas Station Demo

The contracts are already deployed on Ghostnet. Their addresses, together with the API URL, can be
changed in the `.env` file.
This project is a toy web application demonstrating the use of a Gas Station API and a Permit Contract on the Tezos blockchain.

The web app allows you to mint a non-fungible token (NFT) and transfer it to a "staking" contract, even if you have no Tez in your wallet.


## Prerequisites

Before you start, ensure you have the following installed on your machine:

- Node.js [Download and Install Node.js](https://nodejs.org/)
- npm (Node Package Manager): Comes with Node.js installation
- NVM (Node Version Manager): This is the key component for managing Node.js versions.
To install NVM for managing Node.js versions, refer to the official installation guide
at [install](https://github.com/nvm-sh/nvm#installing-and-updating)

## Gas Station API and Permit Contract

This project interacts with a Gas Station API and a Permit Contract on the Tezos blockchain. The contracts are already deloyed on Ghostnet. Configure the follwing in the `.env` file:

- **Gas Station API URL**: the URL of the Gas Station API that handles the reply of operations to the blockchain.
- **Permit Contract Address**: the address of the Permit Contract on the Tezos blockchain. This contract is used for authorizing and signing operations.
- **Staking Contract Address (Optional)**: If applicable, the address of the Staking Contract where NFTs can be transferred.

**Note:** The contract addresses and API URL can be changed in the `.env` file.


## Configuration

Copy the `.env.example` file to `.env` and update the following variables based on your deployment:

```dotenv
PUBLIC_TZKT_API=https://api.ghostnet.tzkt.io
PUBLIC_TEZOS_RPC=https://ghostnet.smartpy.io

# Gas Station API URL
PUBLIC_GAS_STATION_API=http://localhost:8000

# Permit Contract Address
PUBLIC_PERMIT=KT1HUdxmgZUw21ED9gqELVvCty5d1ff41p7J

# Staking Contract Address (if applicable)
PUBLIC_STAKING_CONTRACT=KT1VVotciVbvz1SopVfoXsxXcpyBBSryQgEn

PUBLIC_APP_BASE_URL=http://localhost:5173
```

## Running locally

Navigate to the project folder:

```
cd examples/nft
```

To install dependencies, run:

```
npm install
```
or

```
npm i
```

To launch the project on your localhost using a development server, run:

```
npm run dev
```

Your project will be accessible at http://localhost:5173/

To clean up generated files, run:

```
rm -rf node_modules
```

Make sure to configure the `.env` file with the appropriate values before running the project locally.
8 changes: 4 additions & 4 deletions examples/nft/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/nft/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"type": "module",
"dependencies": {
"@marigold-dev/gas-station-lib": "^0.0.4",
"@marigold-dev/gas-station-lib": "^0.0.7",
"@airgap/beacon-sdk": "^4.0.4",
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@picocss/pico": "^1.5.10",
Expand Down
150 changes: 113 additions & 37 deletions examples/nft/src/lib/MintingComponent.svelte
Original file line number Diff line number Diff line change
@@ -1,78 +1,154 @@
<script lang="ts">
import { Tezos, subTezos } from "$lib/tezos";
import { GasStation } from "@marigold-dev/gas-station-lib";
import { PUBLIC_PERMIT, PUBLIC_GAS_STATION_API, PUBLIC_TZKT_API } from '$env/static/public';
import {
GasStation,
GAS_STATION_PUBLIC_API_GHOSTNET,
} from "@marigold-dev/gas-station-lib";
import {
PUBLIC_GAS_STATION_API,
PUBLIC_PERMIT,
PUBLIC_TZKT_API,
} from "$env/static/public";

export let user_address = '';
export let user_address = "";
export let available_token_ids = new Set<string>(); // to be shared with StakingComponent


const token_id = 0;
let user_tokens: any[] = [];

/*** Generate a random integer up to a given maximum value.
* It uses to generate a random token ID when minting. */
function randomInt(max: number) {
return Math.floor(Math.random() * max);
}

// Converts an IPFS link to its HTTPs counterpart
function IPFSLinkToHTTPS(url: string) {
return url.replace("ipfs://", "https://ipfs.io/ipfs/");
}

function get_tokens(user_address: string) {
return fetch(`${PUBLIC_TZKT_API}/v1/tokens/balances?account=${user_address}&token.contract=${PUBLIC_PERMIT}&balance.gt=0`)
return fetch(
`${PUBLIC_TZKT_API}/v1/tokens/balances?account=${user_address}&token.contract=${PUBLIC_PERMIT}&balance.gt=0`,
)
.then((response) => {
return response.json();
})
.then((fa2_tokens) => {
user_tokens = fa2_tokens;
});
};
}

// Add minting progress
let mintingProgress = 0;
let isMinting = false;

/** This function is triggered when the "Mint" button is clicked.
* It initiates the minting process, interacting with the permit contract
* and gas station API. */
function mint(user_address: string) {
(async () => {
const gas_api = new GasStation({
apiURL: PUBLIC_GAS_STATION_API
});
const contract = await Tezos.wallet.at(PUBLIC_PERMIT);
const mint_op = await contract.methodsObject.mint_token([{
const token_id = randomInt(6);
(async () => {
isMinting = true;

try {
const gas_api = new GasStation({
apiURL: PUBLIC_GAS_STATION_API,
});

const contract = await Tezos.wallet.at(PUBLIC_PERMIT);
const mint_op = await contract.methodsObject
.mint_token([
{
owner: user_address,
token_id: token_id,
amount_: 1
}]).toTransferParams()
console.log(mint_op);
const response = await gas_api.postOperation(user_address, {
destination: mint_op.to,
parameters: mint_op.parameter
});
console.log(response);
// √ construct mint operation from Taquito
// √ jsonize
// √ const reponse = await fetch("http://127.0.0.1/operation")
// √ display balance
// next: randomize (on the server side) the NFT we get
// display an error message if we didn't wait for long enough
})();
amount_: 1,
},
])
.toTransferParams();

mintingProgress = 50; // Set progress to 50% after Taquito operation

const response = await gas_api.postOperation(user_address, {
destination: mint_op.to,
parameters: mint_op.parameter,
});

mintingProgress = 100; // Set progress to 100% after gas station operation
} catch (error) {
console.error("Minting failed:", error);
mintingProgress = 0; // Reset progress on failure
} finally {
isMinting = false;
}
// √ construct mint operation from Taquito
// √ jsonize
// √ const reponse = await fetch("http://127.0.0.1/operation")
// √ display balance
// next: randomize (on the server side) the NFT we get
// display an error message if we didn't wait for long enough
})();
}

subTezos(() => {
get_tokens(user_address)
get_tokens(user_address);
});

// Maintain the set of available token IDs to pick one in the stash operation
$: available_token_ids = new Set(
user_tokens.map((token) => token.token.tokenId),
);
</script>

<div style="display: flex">
<div>
<button on:click={() => mint(user_address)}>
mint
<button on:click={() => mint(user_address)} disabled={isMinting}
>{isMinting ? "Minting..." : "Mint"}
</button>
{#if isMinting}
<div class="progress-bar">
<div
class="progress-bar-fill"
style={`width: ${mintingProgress}%`}
></div>
</div>
{/if}
</div>

<div>
{#if user_tokens.length == 0}
<p>You don't have any tokens. Try minting one!</p>
{:else}
{#each user_tokens as token, i}
<div>
<img src="{IPFSLinkToHTTPS(token.token.metadata.thumbnailUri)}" alt="Token thumnail"/>
<div style="text-align: center; font-size:14px">{token.balance}</div>
</div>
{/each}
<div style="display:flex;align-items:center;justify-content:center;">
{#each user_tokens as token, i}
<div
style="display:flex;flex-direction:column;justify-content:center;align-items:center;"
>
{#if Object.hasOwn(token.token, "metadata")}
<img
src={IPFSLinkToHTTPS(token.token.metadata.thumbnailUri)}
alt="Token thumnail"
/>
<div style="text-align: center; font-size:14px">
{token.balance}
</div>
{/if}
</div>
{/each}
</div>
{/if}
</div>
</div>

<style>
.progress-bar {
background-color: #eee; /* Light gray background for the progress bar */
border: 1px solid #ccc; /* Border for the progress bar */
border-radius: 15px; /* Rounded corners */
height: 10px;
}

.progress-bar-fill {
background-color: #0074cc; /* Color for the filled part of the progress bar */
height: 100%; /* Fill the entire height of the progress bar */
}
</style>
2 changes: 1 addition & 1 deletion examples/nft/src/lib/Nav.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { myAccount, connectWallet, getPKH } from '$lib/tezos';

function truncate_address(str) {
function truncate_address(str: string) {
if (str.length > 25) {
return str.substr(0, 10) + '...' + str.substr(str.length-5, str.length);
}
Expand Down
Loading
Loading