In-game NFT Marketplace
web3.unity provides prefabs for integrating an in-game marketplace. A web UI via the ChainSafe Gaming Marketplace is also available. To access and interact with the marketplace, various endpoints are available to games implementing this feature.
Create Approval Transaction
In order to interact with the marketplace, an account must be given approval by the minting interface. This is achieved by using the web3.unity SDK's EVM.CreateApproveTransaction
class method. A sample code snippet is provided below. Please refer to the CreateApproval.cs
and CreateApproval
prefabs provided in the SDK.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Web3Unity.Scripts.Library.ETHEREUEM.Connect;
using Web3Unity.Scripts.Library.Web3Wallet;
public class CreateApprovalWebWallet : MonoBehaviour
{
// Start is called before the first frame update
public string chain = "ethereum";
public string network = "goerli";
public string account;
public string tokenType = "1155";
string chainID = "5";
private void Awake()
{
account = PlayerPrefs.GetString("Account");
}
public async void ApproveTransaction()
{
var response = await EVM.CreateApproveTransaction(chain, network, account, tokenType);
Debug.Log("Response: " + response.connection.chain);
try
{
string responseNft = await Web3Wallet.SendTransaction(chainID, response.tx.to, "0",
response.tx.data, response.tx.gasLimit, response.tx.gasPrice);
if (responseNft == null)
{
Debug.Log("Empty Response Object:");
}
print(responseNft);
Debug.Log(responseNft);
}
catch (Exception e)
{
Debug.LogException(e, this);
}
}
}
Get Listed NFT's
To get a list of marketplace NFT's that have been minted through the marketplace, the SDK provides an EVM.GetNftMarket
function. This method returns all NFT's that have been minted and listed for sale. We have provided a sample code snippet below, but please also refer to the GetListNFTWebGL.cs
and GetListedNFTWebWallet.cs
prefabs in the SDK for full implementation details. The source files provided also allow the user to purchase the listed NFT in game.
- chain = ethereum / goerli / avalanche
- network = testnet / mainnet
using System.Collections;
using System.Collections.Generic;
using Models;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Web3Unity.Scripts.Library.ETHEREUEM.Connect;
public class GetListedNFTWebWallet : MonoBehaviour
{
private string chain = "ethereum";
public Renderer textureObject;
private string network = "goerli";
private string chainID = "5";
public Text price;
public Text seller;
public Text description;
public Text listPercentage;
public Text contractAddr;
public Text tokenId;
public Text itemId;
private string _itemPrice = "";
private string _tokenType = "";
private string _itemID = "";
public void Awake()
{
price.text = "";
seller.text = "";
description.text = "";
listPercentage.text = "";
tokenId.text = "";
itemId.text = "";
contractAddr.text = "";
}
// Start is called before the first frame update
async void Start()
{
List<GetNftListModel.Response> response = await EVM.GetNftMarket(chain, network);
price.text = response[0].price;
seller.text = response[0].seller;
Debug.Log("Seller: " + response[0].seller);
if (response[0].uri.StartsWith("ipfs://"))
{
response[0].uri = response[0].uri.Replace("ipfs://", "https://ipfs.io/ipfs/");
Debug.Log("Response URI" + response[0].uri);
}
UnityWebRequest webRequest = UnityWebRequest.Get(response[0].uri);
await webRequest.SendWebRequest();
RootGetNFT data =
JsonConvert.DeserializeObject<RootGetNFT>(
System.Text.Encoding.UTF8.GetString(webRequest.downloadHandler.data));
if (data.description == null)
{
description.text = "";
}
else
{
description.text = data.description;
}
// parse json to get image uri
string imageUri = data.image;
if (imageUri.StartsWith("ipfs://"))
{
imageUri = imageUri.Replace("ipfs://", "https://ipfs.io/ipfs/");
StartCoroutine(DownloadImage(imageUri));
}
else
{
StartCoroutine(DownloadImage(imageUri));
}
if (data.properties != null)
{
foreach (var prop in data.properties.additionalFiles)
{
if (prop.StartsWith("ipfs://"))
{
var additionalURi = prop.Replace("ipfs://", "https://ipfs.io/ipfs/");
}
}
}
listPercentage.text = response[0].listedPercentage;
Debug.Log(response[0].listedPercentage);
contractAddr.text = response[0].nftContract;
itemId.text = response[0].itemId;
_itemID = response[0].itemId;
_itemPrice = response[0].price;
_tokenType = response[0].tokenType;
tokenId.text = response[0].tokenId;
}
IEnumerator DownloadImage(string MediaUrl)
{
UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ProtocolError)
Debug.Log(request.error);
else
{
Texture2D webTexture = ((DownloadHandlerTexture)request.downloadHandler).texture as Texture2D;
Sprite webSprite = SpriteFromTexture2D(webTexture);
textureObject.GetComponent<Image>().sprite = webSprite;
}
}
Sprite SpriteFromTexture2D(Texture2D texture)
{
return Sprite.Create(texture, new Rect(0.0f, 0.0f, texture.width, texture.height), new Vector2(0.5f, 0.5f),
100.0f);
}
}
Functionality For Purchasing A Marketplace NFT
Once an NFT has been minted and listed for sale, you can allow the purchase of these items in-game by using the EVM.CreatePurchaseNftTransaction
function provided in EVM.cs
. There are also prefabs created for the different builds (BuyItemWebGL
and BuyItemWebWallet
) that is implemented in the GetListedNFTWebGL.cs
and GetListedNFTWebWallet.cs
files. See below for a code snippet of the implementation:
- chain = ethereum / goerli / avalanche
- network = testnet / mainnet
- account = connected account
- item id = the token id of the minted item
- item price = the price set by the issuer
- token type = either erc721 or erc1155
using System;
using Models;
using UnityEngine;
using UnityEngine.UI;
using Web3Unity.Scripts.Library.ETHEREUEM.Connect;
using Web3Unity.Scripts.Library.Web3Wallet;
public class GetListedNFTWebWallet : MonoBehaviour
{
private string chain = "ethereum";
private string network = "goerli";
private string chainID = "5";
public Text price;
public Text seller;
public Text description;
public Text listPercentage;
public Text contractAddr;
public Text tokenId;
public Text itemId;
private string _itemPrice = "";
private string _tokenType = "";
private string _itemID = "";
public void Awake()
{
price.text = "";
seller.text = "";
description.text = "";
listPercentage.text = "";
tokenId.text = "";
itemId.text = "";
contractAddr.text = "";
}
public async void PurchaseItem()
{
BuyNFT.Response response = await EVM.CreatePurchaseNftTransaction(chain, network,
PlayerPrefs.GetString("Account"), _itemID, _itemPrice, _tokenType);
Debug.Log("Account: " + response.tx.account);
Debug.Log("To : " + response.tx.to);
Debug.Log("Value : " + response.tx.value);
Debug.Log("Data : " + response.tx.data);
Debug.Log("Gas Price : " + response.tx.gasPrice);
Debug.Log("Gas Limit : " + response.tx.gasLimit);
try
{
string responseNft = await Web3Wallet.SendTransaction(chainID, response.tx.to, response.tx.value,
response.tx.data, response.tx.gasLimit, response.tx.gasPrice);
if (responseNft == null)
{
Debug.Log("Empty Response Object:");
}
print(responseNft);
Debug.Log(responseNft);
}
catch (Exception e)
{
Debug.LogException(e, this);
}
}
}
Listing Minted Asset
To list minted NFT's for sale, the SDK provides an EVM.CreateListNftTransaction
function. You can find the prefabs and its implementation by searching for the file names ListItemWebGL
and ListItemWebWallet
. See below for the code snippet:
- chain = ethereum / goerli / avalanche
- network = testnet / mainnet
- account = connected account
- item id = the token id of the minted item
- item price = the price set by the seller
- token type = either erc721 or erc1155
using System;
using System.Collections;
using System.Collections.Generic;
using Models;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Web3Unity.Scripts.Library.ETHEREUEM.Connect;
using Web3Unity.Scripts.Library.Web3Wallet;
namespace Web3Unity.Scripts.Prefabs.Minter
{
public class ListNftWebWallet : MonoBehaviour
{
private string chain = "ethereum";
private string network = "goerli";
private string chainID = "5";
private string _itemPrice = "0.001";
private string _tokenType = "";
private string _itemID = "";
private string account;
public Renderer textureObject;
public Text description;
public Text tokenURI;
public Text contractAddr;
public Text isApproved;
public InputField itemPrice;
public Text noListedItems;
public Text playerAccount;
public void Awake()
{
account = PlayerPrefs.GetString("Account");
description.text = "";
tokenURI.text = "";
isApproved.text = "";
contractAddr.text = "";
}
// Start is called before the first frame update
async void Start()
{
playerAccount.text = account;
try
{
List<MintedNFT.Response> response = await EVM.GetMintedNFT(chain, network, account);
if (response[1].uri == null)
{
Debug.Log("Not Listed Items");
return;
}
if (response[1].uri.StartsWith("ipfs://"))
{
response[1].uri = response[1].uri.Replace("ipfs://", "https://ipfs.io/ipfs/");
}
UnityWebRequest webRequest = UnityWebRequest.Get(response[1].uri);
await webRequest.SendWebRequest();
RootGetNFT data =
JsonConvert.DeserializeObject<RootGetNFT>(
System.Text.Encoding.UTF8.GetString(webRequest.downloadHandler.data));
description.text = data.description;
// parse json to get image uri
string imageUri = data.image;
if (imageUri.StartsWith("ipfs://"))
{
imageUri = imageUri.Replace("ipfs://", "https://ipfs.io/ipfs/");
StartCoroutine(DownloadImage(imageUri));
}
else
{
StartCoroutine(DownloadImage(imageUri));
}
tokenURI.text = response[1].uri;
Debug.Log(response[1].uri);
contractAddr.text = response[1].nftContract;
Debug.Log("NFT Contract: " + response[1].nftContract);
isApproved.text = response[1].isApproved.ToString();
_itemID = response[1].id;
_itemPrice = itemPrice.text;
Debug.Log("Token Type: " + response[1].tokenType);
_tokenType = response[1].tokenType;
}
catch (Exception e)
{
noListedItems.text = "NO LISTED ITEM for " + account;
Debug.Log("No Listed Items" + e);
}
}
// ReSharper disable Unity.PerformanceAnalysis
IEnumerator DownloadImage(string MediaUrl)
{
UnityWebRequest request = UnityWebRequestTexture.GetTexture(MediaUrl);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ProtocolError)
Debug.Log(request.error);
else
{
Texture2D webTexture = ((DownloadHandlerTexture)request.downloadHandler).texture as Texture2D;
Sprite webSprite = SpriteFromTexture2D(webTexture);
textureObject.GetComponent<Image>().sprite = webSprite;
}
}
Sprite SpriteFromTexture2D(Texture2D texture)
{
return Sprite.Create(texture, new Rect(0.0f, 0.0f, texture.width, texture.height), new Vector2(0.5f, 0.5f),
100.0f);
}
public async void ListItem()
{
float eth = float.Parse(_itemPrice);
float decimals = 1000000000000000000; // 18 decimals
float wei = eth * decimals;
Debug.Log("ItemID: " + _itemID);
ListNFT.Response response =
await EVM.CreateListNftTransaction(chain, network, account, _itemID, Convert.ToDecimal(wei).ToString(), _tokenType);
int value = Convert.ToInt32(response.tx.value.hex, 16);
Debug.Log("Response: " + response);
try
{
string responseNft = await Web3Wallet.SendTransaction(chainID, response.tx.to, value.ToString(),
response.tx.data, response.tx.gasLimit, response.tx.gasPrice);
if (responseNft == null)
{
Debug.Log("Empty Response Object:");
}
}
catch (Exception e)
{
Debug.Log("Error: " + e);
}
}
}
}