123# Unique Parachain45## Project Description67The Unique Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the8basement for creating collections of unique non-divisible things, also called Non Fungible Tokens (NFTs), minting NFT of9a given Collection, and managing their ownership.1011The pallet also enables storing NFT properties. Though (according to ERC-721) NFT properties belong to logic of a12concrete application that operates a Collection, so purposefully the NFT Tracking Module does not have any knowledge13about properties except their byte size leaving application logic out to be controlled by Smart Contracts.1415The Unique Chain also provides:1617- Smart Contracts Pallet and example smart contract that interacts with Unique Runtime18- ERC-1155 Functionality (currently PoC as Re-Fungible tokens, i.e. items that are still unique, but that can be split19 between multiple users)20- Variety of economic options for dapp producers to choose from to create freemium games and other ways to attract21 users. As a step one, we implemented an economic model when a collection sponsor can be set to pay for collection22 Transfer transactions.2324Wider Unique Ecosystem (most of it was developed during Hackusama):2526- [SubstraPunks Game hosted on IPFS](https://github.com/usetech-llc/substrapunks)27- [Unique Wallet and UI](https://uniqueapps.usetech.com/#/nft)28- [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)2930Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!3132## Application Development3334If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).353637## Building3839Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything40so that we can keep the builds stable.41421. Install Rust:4344```bash45sudo apt-get install git curl libssl-dev llvm pkg-config libclang-dev clang46curl https://sh.rustup.rs -sSf | sh47```48492. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.50513. Install install nightly 2021-11-11 and make it default:5253```bash54rustup toolchain install nightly-2021-11-1155rustup default nightly-2021-11-1156```57584. Add wasm target for nightly toolchain:5960```bash61rustup target add wasm32-unknown-unknown --toolchain nightly-2021-11-1162```63645. Build:65```bash66cargo build67```6869optionally, build in release:70```bash71cargo build --release72```7374## Building as Parachain locally7576Note: checkout this project and all related projects (see below) in the sibling folders (both under the same folder)7778### Polkadot launch utility7980```81git clone https://github.com/paritytech/polkadot-launch82```8384### Build relay8586```87git clone https://github.com/paritytech/polkadot.git88cd polkadot89git checkout release-v0.9.1790cargo build --release91```9293### Build Unique parachain9495Run in the root of this project:96```97cargo build --release98```99100### Build Acala parachain (optional, full config only)101102```103git clone https://github.com/AcalaNetwork/Acala104cd Acala105git checkout 54db3acd409a0b787f116f20e163a3b24101ce38106make build-release107```108109## Running as Parachain locally110111```112./launch-testnet.sh113```114115Optional, full setup with Acala and Statemint116```117./launch-testnet-full.sh118```119120## Run Integration Tests1211221. Install all needed dependecies123```124cd tests125yarn install126```1271282. Run tests129```130yarn test131```132133134## Code Formatting135136### Apply formatting and clippy fixes137```bash138cargo clippy139cargo fmt140```141142### Format tests143```bash144pushd tests && yarn fix ; popd145```146147### Check code style in tests148```bash149cd tests && yarn eslint --ext .ts,.js src/150```151152153## Karura token transfer154155To get started, you need to open inbound and outbound hrmp channels.156157### Next, we need to register our asset at Karura.158```159assetRegistry -> registerForeignAsset(location, metadata)160location:161 V0(X2(Parent, Parachain(PARA_ID)))162metadata:163 name OPL164 symbol OPL165 decimals 18166minimalBalance 1167```168169### Next, we can send tokens from Opal to Karura:170```171polkadotXcm -> reserveTransferAssets172dest:173 V0(X2(Parent, Parachain(<KARURA_PARA_ID>)))174beneficiary:175 X1(AccountId(Any, <ACCOUNT>))176assets:177 V1(Concrete(0,Here), Fungible(<AMOUNT>))178feeAssetItem:179 0180weightLimit:181 <LIMIT>182```183184The result will be displayed in ChainState185tokens -> accounts186187### To send tokens from Karura to Opal:188```189xtokens -> transfer190191currencyId:192 ForeingAsset193 <TOKEN_ID>194195amount:196 <AMOUNT>197dest:198 V1199 (200 Parents:1,201 X2(Parachain(<KARURA_PARA_ID>), AccountId(Any, <ACCOUNT>)202 )203destWeight:204 <WEIGHT>205```