From 440ccd22938a53a75471dda3d58585c18eb1a2ca Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Mon, 16 Sep 2024 20:56:51 +0400 Subject: [PATCH] building dapps (#173) * docs: building dapps * remove allow lists from docs * docs: move tech concepts to the build section * fix: titles --- docs/.vuepress/configs/sidebar.ts | 18 +- docs/about/network-features/sponsoring.md | 5 +- docs/about/tech-concepts/glossary.md | 67 ---- docs/build/sdk/collections.md | 122 +------ docs/build/sdk/v2/collections.md | 1 - docs/build/sdk/v2/dapps.md | 265 ++++++++++++++ docs/build/sdk/v2/migration.md | 4 +- docs/reference/sdk-methods.md | 405 ---------------------- 8 files changed, 279 insertions(+), 608 deletions(-) delete mode 100644 docs/about/tech-concepts/glossary.md create mode 100644 docs/build/sdk/v2/dapps.md diff --git a/docs/.vuepress/configs/sidebar.ts b/docs/.vuepress/configs/sidebar.ts index 28b6a29..ba29ce3 100644 --- a/docs/.vuepress/configs/sidebar.ts +++ b/docs/.vuepress/configs/sidebar.ts @@ -46,14 +46,6 @@ export const sidebar: Record = { '/about/network-features/sdk-indexer', '/about/network-features/marketplace.md', ] - }, - { - text: 'Tech Concepts', - children: [ - '/about/tech-concepts/addresses', - '/about/tech-concepts/balances/index.md', - //'/about/tech-concepts/glossary.md', - ] } ], '/build': [ @@ -77,7 +69,7 @@ export const sidebar: Record = { ] }, { - text: 'SDK V2 [Alpha]', + text: 'SDK-2.0 [Alpha]', children: [ '/build/sdk/v2/quick-start.md', '/build/sdk/v2/balances.md', @@ -85,6 +77,7 @@ export const sidebar: Record = { '/build/sdk/v2/tokens.md', '/build/sdk/v2/sponsoring.md', '/build/sdk/v2/indexer.md', + '/build/sdk/v2/dapps.md', ] }, { @@ -106,6 +99,13 @@ export const sidebar: Record = { }, '/build/evm/UniqueNFT.md', ], + }, + { + text: 'Tech Concepts', + children: [ + '/about/tech-concepts/addresses', + '/about/tech-concepts/balances/index.md', + ] } ], '/tutorials': [ diff --git a/docs/about/network-features/sponsoring.md b/docs/about/network-features/sponsoring.md index 6ff431d..3b7f533 100644 --- a/docs/about/network-features/sponsoring.md +++ b/docs/about/network-features/sponsoring.md @@ -17,10 +17,9 @@ Unique Network supports sponsoring various types of transactions to enhance user ## Preventing Attacks -One potential risk with sponsoring transactions is the possibility of DOS attacks, where malicious actors deplete sponsor funds by sending numerous "free" transactions. Unique Network addresses this issue by implementing rate limits. Rate Limiting Strategies: +One potential risk with sponsoring transactions is the possibility of DOS attacks, where malicious actors deplete sponsor funds by sending numerous "free" transactions. Unique Network addresses this issue by implementing rate limits: -1. **Time limits**: Set a rate limit where an NFT transferred will be sponsored only once every X block. This prevents excessive transactions in a short period. -2. **Allow Lists**: Implement a rate limit based on an allow list, ensuring only trusted transactions are processed frequently. +**Time limits**: Set a rate limit where an NFT transferred will be sponsored only once every X block. This prevents excessive transactions in a short period. ## Learn More diff --git a/docs/about/tech-concepts/glossary.md b/docs/about/tech-concepts/glossary.md deleted file mode 100644 index b48e3ab..0000000 --- a/docs/about/tech-concepts/glossary.md +++ /dev/null @@ -1,67 +0,0 @@ -# Glossary - -**Distributed Database** is a database type where the information is stored in several copies on devices located in different locations. - -**Consistency** is a distributed database property that means that all copies of the data are synchronized and identical to each other. - -**State** is a state of a blockchain. It describes some current system state. A state, for example, can include user balances owned by users' tokens, etc. - -**Consensus** is an agreement of the network participants on consistency. - -**Transaction** a state change. An operation that changes the state of the blockchain, for example, the transfer of cryptocurrency from one user to another. - -**Transaction fee** is a transaction commission. Any change in the blockchain state is paid by a commission. This is required to control the flow of such changes because the changes require network computing resources to reach and verify consensus. - -**Substrate** is a kind of constructor that allows you to collect, configure, and customize your blockchain. - -**Polkadot** is a stable blockchain made from Substrate by Parity to use it as a Relay - collecting node for a large number of parallel blockchains (parachains, parathreads). Each parachain has its own business logic, for example, the Unique Network parachain implements advanced NFT logic. - -**Kusama** is an unstable relay, an experimental kind of Polkadot. All innovations first go to Kusama, and only then to Polkadot. - -**Token** is a valuable unit in the blockchain. - -**KSM** is the Kusama token, the cryptocurrency of the Kusama network. Used to pay commissions on the Kusama network. - -**DOT** is the Polkadot token, the cryptocurrency of the Polkadot network. Used to pay commissions on the Polkadot network. - -**UNQ** is the Unique token, the cryptocurrency of the Unique network. Used to pay commissions on the Unique network. - -**QTZ** is the Quartz token, the cryptocurrency of the Quartz network. Used to pay commissions on the Quartz network. - -**NFT** (or Non-Fungible Token) is a unique indivisible token. It reflects some unique, indivisible essence of the real or virtual world. For example, a car, an apartment, a diamond, a cryptocurrency, a cryptobank, or any game item. The Ethereum blockchain has an NFT token standard known as ERC-721. - -**Fractional NFT** (or Re-Fungible Token, RFT) is a unique divisible token for proportional ownership of NFT. Also reflects some unique essence of the real or virtual world, but can be divided into several parts distributed separately. The Ethereum blockchain has a Fungible token standard known as EIP-1633. - -**Native Coin**. The blockchain usually has some kind of Fungible token for paying network fees, which is "stitched" in its code and cannot be changed (or it will be very difficult and expensive to change). It regulates the entire economy of the network. For example, KSM tokens for the Kusama network, DOT for the Polkadot network, and UNQ for the Unique Network. - -**Coin** (or Fungible Token) is a divisible value. These tokens reflect the values of the real or virtual world that can be divided or added. For example, rubles, dollars, gold, wood, money in the game Monopoly, etc. The Ethereum blockchain has a Fungible token standard known as ERC-20. - -**Application Token** is a token created and managed by some specific application, for example, a game. The economy of the entire network does not depend on it, but only the economy of a particular application if the application author wants this. - -**Sponsoring** is a feature that allows freeing the user from working with native fungible tokens. - -**Royalties** are payments that compensate original NFT creators for the use of their non-fungible tokens (NFTs). - -**Minting** is the operation of creating a divisible or an indivisible token. - -**Transfer** is an operation that transfers a divisible or an indivisible token. - -**Burn**. The operation of destroying a divisible or an indivisible token. - -**Total supply** is the total amount of some indivisible token in the world. The mint operation increases this amount, the burn operation decreases it, and the transfer operation does not change this value. - -**Send** is the operation that sends a token, sometimes used instead of the transfer operation. - -**Sell (list)** means to put an NFT token for sale (in the terms of a marketplace). - -**SDK** is ready-to-use application programming interfaces (APIs) in the form of on-device libraries of reusable functions. - -**SS58** is the extensible address format for the Substrate chains. A key characteristic when considering cross-chain interoperability and address derivation. Read more [here](https://docs.substrate.io/v3/advanced/ss58/). - -**Buy (delist)** means to buy an NFT token (in the terms of a marketplace). - -**Cancel** - in the context of a marketplace, it means canceling the sale of a token and removing it from the sale. - -**DID** is a new type of identifier that enables verifiable, decentralized digital identity. - -**Rate limits** are a strategy for limiting network traffic. Rate limiting can help stop certain kinds of malicious bot activity. It can also reduce strain on web servers. \ No newline at end of file diff --git a/docs/build/sdk/collections.md b/docs/build/sdk/collections.md index d661a41..b7cd323 100644 --- a/docs/build/sdk/collections.md +++ b/docs/build/sdk/collections.md @@ -17,7 +17,7 @@ In Unique Network, the collection has the following entities: - **limits** - a set that defines the rules for a collection, e.g. whether it can be transferred, or how much tokens you can mint in it; - **owner** - an address that created a collection (or if the collection was transferred, the address that owns the collection at the moment); - **admins** - a collection can be controlled by multiple admin addresses. Admins can issue and burn NFTs, as well as add and remove other admins, but they cannot change NFT or collection ownership; -- **allow list** - a list of addresses collected that allow certain community members a guaranteed spot for minting a new NFT. + ## Prerequisites @@ -668,126 +668,6 @@ curl -X 'POST' \ - -## Allow list - -### Add to allow list - -Adds an address to the allow list of a collection. - -Please check the samples below to learn how to add an address to the allow list. - - - - -```typescript:no-line-numbers -import Sdk from '@unique-nft/sdk' - -const sdk = new Sdk({ baseUrl: 'https://rest.unique.network/opal' }); - -const { parsed } = await sdk.collection.addToAllowList.submitWaitResult({ - address: '5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y', - collectionId: 1, - newAdmin: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', -}); - -const { address, collectionId } = parsed; - -console.log(`Address ${address} is allowed in collection # ${collectionId}.`); -``` - - - - - -```bash:no-line-numbers -curl -X 'POST' \ - 'https://rest.unique.network/opal/collection/add-to-allow-list' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "address": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", - "collectionId": 1, - "newAdminId": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - }' -``` - - - - -### Get the allow list - -You can get the allow list of the specified collection. - -Please check the samples below to learn how to get the allow list. - - - - -```typescript:no-line-numbers -import Sdk from '@unique-nft/sdk' - -const sdk = new Sdk({ baseUrl: 'https://rest.unique.network/opal' }); - -const { addresses } = await sdk.collection.allowList({ collectionId: 1 }); - -console.log(`The addresses in the collection allow list: ${addresses}`); -``` - - - - -```bash:no-line-numbers -curl -X 'GET' \ - 'https://rest.unique.network/opal/collection/allow-list?collectionId=1' -``` - - - - -### Remove from the allow list - -You can get the allow list of the specified collection. - -Please check the samples below to learn how to get the allow list. - - - - -```typescript:no-line-numbers -import Sdk from '@unique-nft/sdk' - -const sdk = new Sdk({ baseUrl: 'https://rest.unique.network/opal' }); - -const { parsed } = await sdk.collection.removeFromAllowList.submitWaitResult({ - address: '5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y', - collectionId: 1, - addressToDelete: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', -}); - -const { collectionId, address } = parsed; - -console.log(`Address ${address} removed from allow list in collection ${collectionId}.`); -``` - - - - - -```bash:no-line-numbers -curl -X 'POST' \ - 'https://rest.unique.network/opal/collection/remove-from-allow-list' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{ - "address": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", - "collectionId": 1, - "addressToDelete": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" - }' -``` - - - ## Destroy a collection #### Limitations diff --git a/docs/build/sdk/v2/collections.md b/docs/build/sdk/v2/collections.md index b3861f9..e11e38c 100644 --- a/docs/build/sdk/v2/collections.md +++ b/docs/build/sdk/v2/collections.md @@ -21,7 +21,6 @@ In Unique Network, the collection has the following entities: - **limits** - a set that defines the rules for a collection, e.g., whether it can be transferred or how many tokens you can mint in it; - **owner** - an address that created a collection (or if the collection was transferred, the address that owns the collection at the moment); - **admins** - a collection can be controlled by multiple admin addresses. Admins can issue and burn NFTs, as well as add and remove other admins, but they cannot change NFT or collection ownership; -- **allow list** - a list of addresses collected that allow certain community members a guaranteed spot for minting a new NFT. ## Prerequisite diff --git a/docs/build/sdk/v2/dapps.md b/docs/build/sdk/v2/dapps.md new file mode 100644 index 0000000..6e2c8f3 --- /dev/null +++ b/docs/build/sdk/v2/dapps.md @@ -0,0 +1,265 @@ +# Building DApps + +This guide provides a walkthrough of how to get started building decentralized applications (dApps) using the [Unique Network React Template](https://github.com/UniqueNetwork/unique-react-template). This boilerplate is designed to simplify development for projects on the Unique Network, leveraging modern tools such as React, TypeScript, and the Unique SDK. + +Check out the live [demo](https://plate.uniquenetwork.dev). + +[[toc]] + +## Quick Start +To get started with the boilerplate, follow these steps: + +1. Create your repository with a GitHub template: + +- On [GitHub](https://github.com/UniqueNetwork/unique-react-template), navigate to the repository's main page. +- Above the file list, click Use this template. +- Select Create a new repository. + +... or just clone the repo with the following command: + +```sh:no-line-numbers +git clone [](https://github.com/UniqueNetwork/unique-react-template) +``` + +2. Install dependencies: + +```sh:no-line-numbers +yarn +``` + +3. Run the development server: + +```sh:no-line-numbers +yarn start +``` + +## Working with the Unique SDK + +The Unique SDK enables you to interact with Substrate-based networks, particularly focusing on NFT operations and tokenized assets. This section will cover the basic setup, configuration, and common operations using the SDK within the context of the provided boilerplate. + +### SDK Overview +The Unique SDK (@unique-nft/sdk) is designed to abstract complexities when working with the blockchain and provides high-level functionality to create, manage, and query NFTs on the Unique Network. + +The boilerplate already integrates the SDK through a global context provider. Let's break down how to configure and interact with the SDK. + +#### Step 1: Initialization of the SDK + +The SDK is initialized within the boilerplate in the `src/sdk/SdkContext.tsx` file. This context is used to provide access to the SDK throughout the application. + +Example of SDK Initialization: + +```ts +import { Sdk } from '@unique-nft/sdk'; +import { createContext, ReactNode, useContext, useState, useEffect } from 'react'; + +interface ISdkContext { + sdk: Sdk | null; +} + +const SdkContext = createContext({ sdk: null }); + +export const SdkProvider = ({ children }: { children: ReactNode }) => { + const [sdk, setSdk] = useState(null); + + useEffect(() => { + const initializeSdk = async () => { + const sdkInstance = await Sdk.create({ + baseUrl: 'https://rest.unique.network/v2/opal', // Example URL for testnet + }); + setSdk(sdkInstance); + }; + + initializeSdk(); + }, []); + + return ( + + {children} + + ); +}; + +export const useSdk = () => useContext(SdkContext); +``` + +- Base URL: This is the endpoint to which the SDK will connect. In this example, it connects to the Opal testnet, but you can change this URL to point to the mainnet or other environments. You can find the list of endpoints in the [reference section](../../../reference/sdk-endpoints.md). +- Provider Component: The SdkProvider component initializes the SDK and stores it in the global state using React.Context. This allows other components to easily access the SDK through the `useSdk` hook. + + +#### Step 2: Accessing the SDK in Components + +Once the SDK is initialized, you can access it in any component using the useSdk hook. This enables you to perform operations like querying NFTs, creating collections, or transferring tokens. + +Example Usage of SDK in a Component: + +```ts +import { useSdk } from '../sdk/SdkContext'; + +const MyComponent = () => { + const { sdk } = useSdk(); + + const fetchNFT = async (tokenId: number) => { + if (!sdk) return; + + try { + const nft = await sdk.token.get({ collectionId: 123, tokenId }); + console.log('NFT Data:', nft); + } catch (error) { + console.error('Error fetching NFT:', error); + } + }; + + return ( +
+ +
+ ); +}; + +export default MyComponent; +``` + +## Connecting Accounts + +The boilerplate comes preconfigured to support multiple wallet providers, including Polkadot-based wallets and WalletConnect (for EVM-based wallets). This section explains how to connect these wallets and manage user accounts in your dApp. + +### Connecting Polkadot wallets + +This section explains how to integrate Polkadot-based wallets into your dApp using the boilerplate provided. It supports a variety of wallets, such as Polkadot.js, SubWallet, Talisman, Enkrypt, and NovaWallet. By using the Polkadot Wallet class, users can easily connect their wallets, manage accounts, and sign transactions on the Unique Network. + +#### Step-1. Polkadot Wallet Setup + +The boilerplate provides a PolkadotWallet class that handles interaction with various Polkadot-based wallets. This class can be instantiated with the name of the wallet the user wants to connect to, and it provides methods for managing accounts and signing transactions. + +Example of Polkadot Wallet Setup + +```ts +import { PolkadotWallet } from './PolkadotWallet'; + +const polkadotWallet = new PolkadotWallet('polkadot-js'); // Instantiate with the wallet of choice +``` + +- PolkadotWallet: This class supports all Polkadot-compatible wallets like Polkadot.js, Subwallet, Talisman, etc. +- Wallet name: Pass the wallet name when instantiating the PolkadotWallet class. The following options are available: `polkadot-js` `subwallet-js` `talisman` `enkrypt` `novawallet` + +#### Step-2. Connecting to a Polkadot Wallet + +Once the wallet instance is created, you can request the user to connect their wallet and retrieve their accounts. The _accounts property within the class stores the accounts associated with the connected wallet. + +Example: Connecting to Wallet and Retrieving Accounts + +```ts +const connectAndFetchAccounts = async () => { + try { + await polkadotWallet.connect(); // Initiates connection + const accounts = await polkadotWallet.getAccounts(); // Retrieves wallet accounts + console.log('Connected accounts:', accounts); + } catch (error) { + console.error('Error connecting to wallet:', error); + } +}; +``` + +- `polkadotWallet.connect()`: Initiates the connection to the wallet. If the user approves, this method connects the wallet and prepares it for account management. +- `polkadotWallet.getAccounts()`: After the connection is established, this method retrieves the user's accounts from the wallet extension. + +#### Step-3. Connecting to EVM wallets + +The provided code integrates WalletConnect with the Unique Network boilerplate, allowing users to connect Ethereum-compatible wallets like MetaMask, to the dApp. Here's a breakdown of the key elements involved in this process, followed by a guide on how to use WalletConnect in your dApp. + +The createWeb3Modal function creates a modal that enables users to connect their Ethereum wallets. Here's the basic setup: + +```ts +import { createWeb3Modal } from "@web3modal/wagmi/react"; +import { defaultWagmiConfig } from "@web3modal/wagmi/react/config"; + +const projectId = process.env.REACT_APP_PROJECT_ID; +const chains = [ + { + id: parseInt(process.env.REACT_APP_CHAIN_ID ?? "8880", 10), + name: process.env.REACT_APP_CHAIN_NAME ?? "Unique Mainnet", + rpcUrls: { default: { http: [process.env.REACT_APP_CHAIN_RPC_URL] } }, + nativeCurrency: { name: "UNQ", symbol: "UNQ", decimals: 18 }, + }, +]; + +const config = defaultWagmiConfig({ chains, projectId }); + +createWeb3Modal({ wagmiConfig: config, projectId }); +``` + +To display the modal, you can trigger it with a button: + +```ts +import { useWeb3Modal } from "@web3modal/wagmi/react"; + +const WalletConnectButton = () => { + const web3Modal = useWeb3Modal(); + + const connectWallet = () => { + web3Modal.openModal(); + }; + + return ; +}; + +export default WalletConnectButton; +``` + +Once a wallet is connected, use wagmi to access the account information: + +```ts +import { useAccount } from "wagmi"; + +const AccountDetails = () => { + const { address, isConnected } = useAccount(); + + return isConnected ?

Connected: {address}

:

No wallet connected

; +}; + +export default AccountDetails; +``` + +### Using Connected Account with SDK + +To use the connected Polkadot account, you need to access it from the `AccountsContext`. This gives you the currently selected account, which you can then use in the SDK. + +You can use `connectSdk` function to create an SDK instance connected to the account. + +```ts +import { UniqueChain } from "@unique-nft/sdk"; +import { Account, WalletsType } from "../accounts/types"; + +export const connectSdk = async ( + sdkEndpoint: string, + account?: Account +) => { + const uniqueChain = UniqueChain({ + baseUrl: sdkEndpoint, + //@ts-ignore + account, + }); + + return uniqueChain; +}; +``` + +Putting it all together: + +```ts +import { useContext } from 'react'; +import { AccountsContext } from '../accounts/AccountsContext'; + +const MyComponent = () => { + const { selectedAccount } = useContext(AccountsContext); + + const createNftCollection = async () => { + const sdk = await connectSdk(baseUrl, selectedAccount); + + // ... + } + + // ... +}; +``` + diff --git a/docs/build/sdk/v2/migration.md b/docs/build/sdk/v2/migration.md index 718ec97..e6f218f 100644 --- a/docs/build/sdk/v2/migration.md +++ b/docs/build/sdk/v2/migration.md @@ -1,4 +1,4 @@ -# Migration from SDK V1 to SDK V2 +# Migration to SDK-2.0 This guide provides instructions on migrating from SDK V1 to SDK V2, highlighting key changes and improvements. @@ -116,7 +116,7 @@ Attributes in SDK V2: The extrinsic methods for transferring, burning, and nesting tokens remain unchanged. -## What If the Application Create Tokens in SDK-V1 Collections +## Application Creates Tokens in the V1 Collection If your application creates tokens in collections originally created with SDK-V1, you should continue using SDK-V1 for this purpose. diff --git a/docs/reference/sdk-methods.md b/docs/reference/sdk-methods.md index bd7b209..e57cc85 100644 --- a/docs/reference/sdk-methods.md +++ b/docs/reference/sdk-methods.md @@ -2165,411 +2165,6 @@ This method returns `RemoveCollectionAdminResult` -## Collections allow list - -
- -
- -
- -
- -
- ## Nesting