This document walks through all Hackusama deliverables made in relation to NFT Blockchain submission.
The TestNet public node is avaiable at wss://unique.usetech.com. It is easy to verify that it functions with the standard AppsUI:
- Open the Apps UI
- Click on the network icon in the top left corner
- Scroll down the list and input
wss://unique.usetech.com
under "custom endpoint" - After connection is established, copy these UI Custom Types and paste them in Developer Settings. Hit "Save" button.
- Now the NFT node is connected with AppsUI.
- Go to Chain State and verify that NFT pallet is visible and you can read information from it.
- For example, select nft -> collection, and enter collection ID 4 (for SubstraPunks) and click "+" button. You will see the collection properties such as UTF-16 encoded collection name and description, UTF-8 encoded token prefix, the size of custom data, etc.
- Install Polkadot{.js} extension if you don't have it already installed. Here are the links for Chrome and Firefox extensions.
- Create an address
- Contact us at Unique Network Telegram channel in order to get some Unique token and some Re-Fungible tokens. Faucet is comming soon, we will update this instructions when it goes live.
- Open Contracts tab. It only appears in the UI when Smart Contracts pallet is included in the runtime.
- Additionally, we can find an existing smart contract. Click on "Add an existing contract" link.
- Input this contract address:
5GdNqKMv4Sszq3SRd3TkXNa6a9ct4D3nXvtTWTFR7rTyccVJ
- Input any contract name, for example
Claim Substrapunks
- Download and drag-and-drop this metadata.json file into contract ABI field.
- Click Save. The contract appears in the page. If the contract did not exist at that address, the UI would display an error message: "Unable to find deployed contract code at the specified address".
This was one of the most challenging parts of the Hackusama for us. The pre-RC4 versions of Substrate did not function
properly when we tried to use ext_dispatch_call
to dispatch a runtime call to NFT pallet from Contracts pallet, and
RC4 had the ext_dispatch_call
already removed to "free space" for some friendlier way of interaction between pallets,
that was not yet implemented. Thanks to Alexander Theißen who reverted the removal of ext_dispatch_call
and created a
special branch based on RC4 for us!
The smart contract source code exists in this repository folder, but the best way to test how the interaction between smart contracts and NFT pallet works is to see it in action using the SubstraPunks Game Example that uses smart contract to claim free characters. The complete demo of this game will come later, so please bare with us and let's put this item demonstration for a bit later.
This feature is best demonstrated in action using our NFT wallet. First, you need to have some Unique and Re-Fungible tokens. This section tells how to get them.
- Open the NFT Wallet
- Search for collection called "Artwork". Search can be done either by collection name or collection ID (which is 2).
- Click on "+ Add collection" in search results. The collection will appear under "My collections"
- Expand the "Artwork" collection and see that you own a token with a partial balance
- Transfer the token to some other address: Click "Transfer token" and enter address and the amount. Amount should be entered as decimal fraction. For example "0.01" to transfer 1/100th part of the token.
- Observe that your balance decreased by the amount you entered.
Also, the Re-Fungible support can be demonstrated using the standard UI features without NFT wallet.
- Open Chain State.
- Select "nft" - "reFungbleItemList"
- Enter parameters: 2 and 1, click "+" button
- Observe the following data structure returned:
{
Collection: 2,
Owner: [
{
owner: 5FNujvbtMyKoJC2zTrfGVaQek7jhfR1L558BMhogfFfD7veH,
fraction: 3,000
},
{
owner: 5D73wtH5pqN99auP4b6KQRQAbketaSj4StkBJxACPBUAUdiq,
fraction: 3,000
},
{
owner: 5FZeTmbZQZsJcyEevjGVK1HHkcKfWBYxWpbgEffQ2M1SqAnP,
fraction: 2,000
},
{
owner: 5EnzEXBuxFHdymceAAtstym8FETQqH4inx29XJSP6uHaCUiP,
fraction: 1,000
},
{
owner: 5GU6iHnc3qTMaufmKYzHUpDmVN2CgzA2JMcGFQLcKNDbE7c6,
fraction: 1,000
}
],
Data:
}
The Owner field contains a list of owners with the fractions they own. The fractions are represented as fixed point
decimals. The number of decimal points in this fraction is determined by collection properties. For example, in the
Artwork collection this property is equal to 4. The owned fraction is then determined as fraction
divided by
10^DecimalPoints, i.e. 10,000 in this case.
- Staying in Chain State, select "nft" - "colection"
- Input "2" and click "+"
- Observe the following structure returned. It tells that collection is ReFungible and DecimalPoints field is equal to 4.
{
Owner: 5FNujvbtMyKoJC2zTrfGVaQek7jhfR1L558BMhogfFfD7veH,
Mode: {
ReFungible: [
0,
4
]
},
Access: 0,
DecimalPoints: 4,
Name: [
...
This feature is best demonstrated in action using our NFT wallet. First, you need to have some Unique and Re-Fungible tokens. This section tells how to get them.
- Open the NFT Wallet
- Search for collection called "Artwork". Search can be done either by collection name or collection ID (which is 2).
- Expand "Artwork" collection
- Click on the image to zoom in.
- Right-click on the image and select "Open Image in New Tab"
- Note the image URL:
https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image1.jpg
- Open Chain State.
- Select "nft" - "colection"
- Input "2" and click "+"
- Scroll down:
],
TokenPrefix: ARTu0000,
CustomDataSize: 0,
OffchainSchema: https://ipfs-gateway.usetech.com/ipfs/QmUSv64cUmL2m44QYkUFWmH89qykC8VLPFwjhpeAScjejS/image{id}.jpg,
Sponsor: 5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM,
UnconfirmedSponsor: 5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM
}
- Observe the field called
OffchainSchema
. This field defines the URL schema that is used to contruct token URLs based on the token ID. In this particular example, the {id} template variable is replaced with token id 1, which results in the proper image URL.
This feature is best demonstrated when you own a SubstraPunk character. Please proceed with the demonstration, and then come back after you claim one.
- Create a new address in Polkadot{.js} extension. We need an address that has zero balance in Unique tokens. Let's call it "ZERO BALANCE" address.
- Open the NFT Wallet
- Search for collection called "SubstraPunks" (partial search also works, so you can just type "punk" and hit Enter)
- Add collection
- Expand substrapunks collection and transfer your PNK token to your "ZERO BALANCE" address.
- Now select your "ZERO BALANCE" address in the drop-down list and repeat searching and adding the collection for this address.
- Transfer token back to your main address. Observe that despite the zero balance, the transfer is successful.
We did not complete these features in time by Hackusama deadline, but because they are important for security of the network, we completed them after the deadline anyway. They can be seen in branch feature/allow_list. Here are the permalinks to essential functions:
All features of the NFT Wallet were already demonstrated previously:
- Enables adding favorite collections
- Shows tokens owned
- Allows NFT and Re-Fungible transfers
- Shows Re-Fungible Balances
- Shows Token Images
The UI was also mainly demonstrated. We only need to show some configuration that happens behind the scenes:
- Open the NFT Wallet Developer Settings
- Observe that Custom UI types are already in place
- Open the NFT Wallet
- Observe that Unique Network icon appears in the left top corner without a need to specify the network
- Click on Unique Network icon and see that
NFT Testnet
is in the network list
In order to see Unity Asset in action, please follow the instructions in this README file:
First, you will need some Unique balance. This section tells how to get the TestNet currency.
- Open this SubstraPunks Game IPFS link
- Find a character you like that still has red background. Red indicates that the character was not yet claimed by anyone.
- Allow access for Polkadot{.js} to this site
- Click "Claim" button
- Select the account that has some Unique balance
- Click "Claim" again, sign transaction, and wait until it mines.
Let's make a pause here: You were just demonstrated how the integration between smart contracts and NFT Pallet works. This is what we've been previously talking about here
The source code of the generic smart contract is located in smart_contract folder. But to demonstrate smart contracts in practice we created additional Claim Contract to implement claiming functionality in this game.
Here is how Claiming works: Claim Contract owns all characters in the game initially. Player sends a transaction calling the method claim:
fn claim(&mut self, collection_id: u64, item_id: u64, new_owner: AccountId)
Inside the method claim
there is a call made to NFT pallet to transfer the token that is being claimed to the player:
runtime_calls::transfer(collection_id, item_id, new_owner);
- Follow the link to NFT Wallet
- Search for "SubstraPunks" collection, add it
- Expand the collection and find your character in there!
- Now you can try transfers and test the economic model, the last thing we put off until a SubstraPunks character is claimed.