List the ERC721 Assets with Scripts (Supported Myria token)
Learn how to list ERC721 assets for sale on the Myria NFT Marketplace.
Prerequisites
- Mint at least one ERC721 asset as described here
Implementation
- Myria SDK (React)
You can find full React implementation for ERC721 listing in the Myria React Samples repository.
1. Set up a new React project
Listing ERC721 tokens requires client-side interaction with the MetaMask wallet. It's recommended to use React to implement such a behavior.
You can create a React app via Create React App. Note, the below project relies on Web3.js library and needs custom configuration.
2. Create a myria-client.ts
helper
It's recommended to have a separate .ts
file for quick access to the MyriaClient
.
For more details, use the Myria Core SDK overview.
3. Retrieve the assets
First, get a list of available assets in your wallet. There are two ways that you can get the list of available assets:
1 - Get all of assets by your stark key - the response data will contains the all Assets/Nfts in cross collection and NFTs that you've purchased in Myria marketplace.
You can use the getAssetByStarkKey()
function of the OnchainAssetManager
.
Details request and response for getAssetByStarkKey()
, you can reference at SDK Docs.
2 - Get all of assets by your specific collection id - the response data will only contains the minted Assets/Nfts under this collection.
You can use the getAssetByCollectionId()
function of the CollectionManager
.
Details request and response for getAssetByCollectionId()
, you can reference at SDK Docs.
- get-all-assets-by-stark-key.ts
- get-assets-by-collection-id.ts
- MyriaAssets.tsx
The getAllAssetByStarkKey()
function has the following parameters:
client
:MyriaClient
instancestarkKey
: Stark Key of your walletpage
: The current page contains list of assetslimit
: Total items per page
import { MyriaClient, OnchainAssetManager } from "myria-core-sdk";
export async function getAllAssetByStarkKey(client: MyriaClient, starkKey: string, page?:number, limit?: number) {
const assetManager: OnchainAssetManager = new OnchainAssetManager(client);
let assets: any = [];
try {
console.log(
`Retrieving a list of assets with ${starkKey} stark key...`
);
const assetData = await assetManager.getAssetByStarkKey(starkKey, page, limit);
if(assetData.data) {
assets = assetData.data.items
} else {
assets = []
}
return assets;
} catch (error) {
if (error instanceof Error) {
console.log(error);
}
return;
}
}
The getAllAssetByStarkKey()
function has the following parameters:
client
:MyriaClient
instancecollectionId
: ID of collection to query the list of assetsassetType
: Type of the asset (ALL/ NON_SALE / FOR_SALE) - Note that the assets is only able to listing if it is NON_SALE so you can specify the NON_SALE for assets type on this casepage
: The current page contains list of assetslimit
: Total items per page
import { MyriaClient,
CollectionManager,
GetAssetByCollectionParams,
CommonPaginateDataTypes,
AssetListResponse,
} from "myria-core-sdk";
export async function getAllAssetsByCollectionId(client: MyriaClient, collectionId: number, assetType: string, limit: number, page: number) {
const collectionManager: CollectionManager = new CollectionManager(client.env);
const payload: GetAssetByCollectionParams = {
collectionId: 1,
assetType, // or pass the params assetType (NON_SALE / FOR_SALE)
limit: 100,
page: 1
};
console.log("Get asset list by collection ID");
let assets: any = [];
try {
console.log(
`Retrieving a list of assets by specific ${payload.collectionId}...`
);
const assetData: CommonPaginateDataTypes<AssetListResponse[]> = await collectionManager.getAssetByCollectionId(starkKey, page, limit);
if(assetData.data) {
assets = assetData
} else {
assets = []
}
return assets;
} catch (error) {
if (error instanceof Error) {
console.log(error);
}
return;
}
}
import { MyriaClient } from "myria-core-sdk";
import { useEffect, useState } from "react";
import { getAllAssetByStarkKey } from "./get-all-assets-by-stark-key.ts";
type Props = {
isConnected: boolean,
account: string,
starkKey: string,
client: MyriaClient
}
const Assets = ({ isConnected, account, starkKey, client }: Props) => {
const [assets, setAssets] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
const [err, setErr] = useState("");
useEffect(() => {
if(isConnected) {
const getErc721 = async () => {
setIsLoading(true);
try {
const result = await getAllAssetByStarkKey(client, starkKey);
setAssets(result);
} catch (err: any) {
setErr(err.message);
} finally {
setIsLoading(false);
setIsLoaded(true);
}
}
getErc721();
}
}, []);
return (
<div>
{err && <code className="mt-3">{err}</code>}
{!isConnected && <p>Please connect your wallet first!</p>}
{isLoading && <p>Loading assets...</p>}
<div className="row align-items-start text-center mt-3">
{(assets && assets.length && isLoaded)
? assets.map((asset: any) => (
<div className="col mb-3" key={asset.id}>
<div className="card mry-card" key={asset.id} style={{ width: "14rem" }}>
<img src={asset.imageUrl ? asset.imageUrl : "/null.png"} alt={asset.name} className="card-img-top img-thumbnail" />
<div className="card-body">
<h5 className="card-title">{asset.name}</h5>
<p className="card-text">{asset.description}</p>
</div>
<div className="card-footer">
<small className="text-muted">#{asset.id} | {asset.publicId}</small>
</div>
</div>
</div>
))
: (isLoaded && !assets.length && <p>No assets available</p>)
}
</div>
</div>
);
}
export default Assets;
4. Single List an asset
Listing an ERC721 asset represents a SELL
order of the MINTABLE_ERC721
token. You can list your asset using the OrderManager
.
You can refer method createOrderV2 at SDK Docs for details request and response.
- list-erc721-with-eth.ts
- list-erc721-with-myria.ts
- MyriaAssets.tsx
The listErc721()
function has the following parameters:
client
:MyriaClient
instanceaccount
: public key of your walletstarkKey
: Stark Key of your walletasset
: an asset object returned fromgetAllAssetByStarkKey()
You can specify the listing price in ETH by changing the price
variable.
import {
CreateOrderV2Params,
EnvTypes,
FeeDto,
ModuleFactory,
MyriaClient,
OrderType,
TokenType,
} from "myria-core-sdk";
export async function listErc721(
client: MyriaClient,
account: string,
starkKey: string,
assetId: string,
price: string,
currentTokenType: TokenType
) {
const orderManager = new OrderManager(client);
const assetManager = new OnchainAssetManager(client);
const asset = ((await assetManager.getAssetById(assetId)) as any).data;
const feeData: FeeDto[] = [
{
feeType: asset?.fee?.[0].feeType, // Type of fee for the asset (Myria only support ROYALTY currently)
percentage: asset?.fee?.[0]?.percentage, // Integer percentage of fee for creator to cost every transaction
address: asset?.fee?.[0]?.address, // Destination wallet address that the fee will send to
},
];
const paramCreateOrder: CreateOrderV2Params = {
orderType: OrderType.SELL,
ownerWalletAddress: account, // Wallet address of the current owner
ownerStarkKey: starkKey, // Stark key of the current owner
assetRefId: parseInt(asset.id, 10),
tokenSell: {
tokenType: TokenType.MINTABLE_ERC721,
data: {
tokenId: asset?.tokenId, // Token ID of Nft
tokenAddress: asset?.tokenAddress, // Token address (collection address) of Nft
},
},
tokenReceived: {
tokenType: TokenType.ETH,
},
price: price + "", // Normal price of NFT (eg price = 0.3 mean 0.3 ETH)
fees: feeData,
};
let listingResponse;
try {
listingResponse = await orderManager?.createOrderV2(paramCreateOrder);
console.log('Listing success!')
} catch (ex) {
console.log('Listing error: ', ex);
throw ex
}
}
The listErc721()
function has the following parameters:
client
:MyriaClient
instanceaccount
: public key of your walletstarkKey
: Stark Key of your walletasset
: an asset object returned fromgetAllAssetByStarkKey()
You can specify the listing price in MYRIA by changing the price
variable.
import {
CreateOrderV2Params,
EnvTypes,
FeeDto,
ModuleFactory,
MyriaClient,
OrderType,
TokenType,
} from "myria-core-sdk";
export async function listErc721(
client: MyriaClient,
account: string,
starkKey: string,
assetId: string,
price: string,
currentTokenType: TokenType
) {
const orderManager = new OrderManager(client);
const assetManager = new OnchainAssetManager(client);
const asset = ((await assetManager.getAssetById(assetId)) as any).data;
const MYRIA_TOKEN_ADDRESS_TESTNET = '0xA06116D9E28AF403d6989c45EF8C0b9B971e5E12';
const MYRIA_TOKEN_ADDRESS_MAINNET = '0xa0ef786bf476fe0810408caba05e536ac800ff86';
const feeData: FeeDto[] = [
{
feeType: asset?.fee?.[0].feeType, // Type of fee for the asset (Myria only support ROYALTY currently)
percentage: asset?.fee?.[0]?.percentage, // Integer percentage of fee for creator to cost every transaction
address: asset?.fee?.[0]?.address, // Destination wallet address that the fee will send to
},
];
const paramCreateOrder: CreateOrderV2Params = {
orderType: OrderType.SELL,
ownerWalletAddress: account, // Wallet address of the current owner
ownerStarkKey: starkKey, // Stark key of the current owner
assetRefId: parseInt(asset.id, 10),
tokenSell: {
tokenType: TokenType.MINTABLE_ERC721,
data: {
tokenId: asset?.tokenId, // Token ID of Nft
tokenAddress: asset?.tokenAddress, // Token address (collection address) of Nft
},
},
tokenReceived: {
tokenType: TokenType.ERC20,
data: {
tokenAddress: MYRIA_TOKEN_ADDRESS_TESTNET // Specify the token address that you want to receive once sell NFTs
},
},
price: price + "", // Normal price of NFT (eg price = 0.3 mean 0.3 MYRIA)
fees: feeData,
};
let listingResponse;
try {
listingResponse = await orderManager?.createOrderV2(paramCreateOrder);
console.log('Listing success!')
} catch (ex) {
console.log('Listing error: ', ex);
throw ex
}
}
import { MyriaClient } from "myria-core-sdk";
import { useEffect, useState } from "react";
import { getAllAssetByStarkKey } from "./get-all-assets-by-stark-key";
import { listErc721 } from "./list-erc721-with-eth"; // Use this file if asset is listed with ETH
// import { listErc721 } from "./list-erc721-with-myria"; // Use this file if asset is listed with Myria
type Props = {
isConnected: boolean,
account: string,
starkKey: string,
client: MyriaClient
}
const Assets = ({ isConnected, account, starkKey, client }: Props) => {
const [assets, setAssets] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
const [err, setErr] = useState("");
useEffect(() => {
if(isConnected) {
const getErc721 = async () => {
setIsLoading(true);
try {
const result = await getAllAssetsByStarkKey(client, starkKey);
setAssets(result);
} catch (err: any) {
setErr(err.message);
} finally {
setIsLoading(false);
setIsLoaded(true);
}
}
getErc721();
}
}, []);
const onList = async (asset: any) => {
return await listErc721(client, account, starkKey, asset);
}
return (
<div>
{err && <code className="mt-3">{err}</code>}
{!isConnected && <p>Please connect your wallet first!</p>}
{isLoading && <p>Loading assets...</p>}
<div className="row align-items-start text-center mt-3">
{(assets && assets.length && isLoaded)
? assets.map((asset: any) => (
<div className="col mb-3" key={asset.id}>
<div className="card mry-card" key={asset.id} style={{ width: "14rem" }}>
<img src={asset.imageUrl ? asset.imageUrl : "/null.png"} alt={asset.name} className="card-img-top img-thumbnail" />
<div className="card-body">
<h5 className="card-title">{asset.name}</h5>
<p className="card-text">{asset.description}</p>
<a className="card-link" onClick={() => onList(asset.id)}>List NFT</a>
</div>
<div className="card-footer">
<small className="text-muted">#{asset.id} | {asset.publicId}</small>
</div>
</div>
</div>
))
: (isLoaded && !assets.length && <p>No assets available</p>)
}
</div>
</div>
);
}
export default Assets;
5. Bulk List assets
Listing multiple ERC721 asset represents creating multiple SELL
order of the MINTABLE_ERC721
token. You can list your asset using the OrderManager
.
You can refer method createOrderV2 at SDK Docs for details request and response.
- bulk-list-erc721-with-eth.ts
- bulk-list-erc721-with-myria.ts
The bulkListErc721()
function has the following parameters:
client
:MyriaClient
instanceaccount
: public key of your walletstarkKey
: Stark Key of your walletassets
: an array of assets returned fromgetAllAssetByStarkKey()
orgetAllAssetByCollectionId()
can be reference at Step #3price
: The price to set for multiple assets
You can specify the listing price in ETH by changing the price
variable.
import {
CreateOrderV2Params,
EnvTypes,
FeeDto,
ModuleFactory,
MyriaClient,
OrderEntity,
OrderType,
TokenType,
} from "myria-core-sdk";
import { MYRIA_TOKEN_PROD, MYRIA_TOKEN_STAGING } from "../../utils/utils";
import { getAllAssetsByCollectionId } from '../get-assets-by-collection-id.ts';
const timer = (ms: any) => new Promise((res) => setTimeout(res, ms));
export async function bulkListErc721(
client: MyriaClient,
account: string,
starkKey: string,
assets: any,
price: string,
listTokenType: TokenType
) {
const moduleFactory = new ModuleFactory(client);
const orderManager = moduleFactory.getOrderManager();
const payload: GetAssetByCollectionParams = {
collectionId: 1, // Collection ID game studio/Partner
assetType: 'NON_SALE',
limit: 100,
page: 1
};
console.log("Get asset list by collection ID");
let bulkListResult: OrderEntity[] = [];
console.log("Initiating a bulk listing...", data);
for (let i = 0; i < assets.length; i++) {
const data = assets[i];
const feeData: FeeDto[] = [
{
feeType: data.fee?.[0].feeType,
percentage: data.fee?.[0]?.percentage,
address: account,
},
];
const paramCreateOrder: CreateOrderV2Params = {
orderType: OrderType.SELL,
ownerWalletAddress: account,
ownerStarkKey: starkKey,
assetRefId: parseInt(data.id, 10),
tokenSell: {
tokenType: TokenType.MINTABLE_ERC721,
data: {
tokenId: data.tokenId,
tokenAddress: data.tokenAddress,
},
},
tokenReceived: {
tokenType: TokenType.ETH, // Must be ETH if NFTs intend list under ETH
},
price: price + "",
fees: feeData,
};
const listingResponse = await orderManager?.createOrderV2(paramCreateOrder);
if (listingResponse) {
console.log(`Listed asset #${data.id}`);
bulkListResult.push(listingResponse);
}
await timer(3000);
}
if (bulkListResult && bulkListResult.length) {
console.log(
`Bulk listing is completed. Listed ${bulkListResult.length} assets...`
);
}
}
The listErc721()
function has the following parameters:
client
:MyriaClient
instanceaccount
: public key of your walletstarkKey
: Stark Key of your walletassets
: an array of assets returned fromgetAllAssetByStarkKey()
orgetAllAssetByCollectionId()
can be reference at Step #3price
: The price to set for multiple assets
You can specify the listing price in MYRIA by changing the price
variable.
import {
CreateOrderV2Params,
EnvTypes,
FeeDto,
ModuleFactory,
MyriaClient,
OrderEntity,
OrderType,
TokenType,
} from "myria-core-sdk";
import { MYRIA_TOKEN_PROD, MYRIA_TOKEN_STAGING } from "../../utils/utils";
const timer = (ms: any) => new Promise((res) => setTimeout(res, ms));
export async function bulkListErc721(
client: MyriaClient,
account: string,
starkKey: string,
assets: any,
price: string,
listTokenType: TokenType
) {
const moduleFactory = new ModuleFactory(client);
const orderManager = moduleFactory.getOrderManager();
console.log("Get asset list by collection ID");
let bulkListResult: OrderEntity[] = [];
console.log("Initiating a bulk listing...", data);
for (let i = 0; i < assets.length; i++) {
const data = assets[i];
const feeData: FeeDto[] = [
{
feeType: data.fee?.[0].feeType,
percentage: data.fee?.[0]?.percentage,
address: account,
},
];
const paramCreateOrder: CreateOrderV2Params = {
orderType: OrderType.SELL,
ownerWalletAddress: account,
ownerStarkKey: starkKey,
assetRefId: parseInt(data.id, 10),
tokenSell: {
tokenType: TokenType.MINTABLE_ERC721,
data: {
tokenId: data.tokenId,
tokenAddress: data.tokenAddress,
},
},
tokenReceived: {
tokenType: listTokenType, // Must be TokenType.ERC20 (If NFTs intend to list under Myria tokens)
data: {
tokenAddress: 'MYRIA_TOKEN_ADDRESS_TESTNET / MYRIA_TOKEN_ADDRESS_MAINNET'
},
},
price: price + "",
fees: feeData,
};
const listingResponse = await orderManager?.createOrderV2(paramCreateOrder);
if (listingResponse) {
console.log(`Listed asset #${data.id}`);
bulkListResult.push(listingResponse);
}
await timer(3000);
}
if (bulkListResult && bulkListResult.length) {
console.log(
`Bulk listing is completed. Listed ${bulkListResult.length} assets...`
);
}
}
6. Bulk Listing/Listing assets via UI
For simplify the process of bulk-listing or single listing, you can access to this supported open sources domain in our Github repo and login with your wallet to retrieve the list of NFTs you intend for listing.
1. Select respective environment (Testnet/Mainnet)
Default is Mainnet
as it supposed you perform in the Production environments of Myria.
You can switch to Testnet
in case of testing with Testnet environment only.
2. Connect metamask wallet.
Select the respective environment in your metamask app and connect wallet.
3. Retrieve the list of assets
You will see the list of retrieve assets by defaults perform by getAllAssetsByStarkKey()
function.
You can input the collection ID (find in Dev Portal) in case if want to query only assets under specific collection and put total assets per page for listing.
Default Page: 1.
Default Limit: 10 items.
Note : Once the asset NFT is listed already, it would be disabled and checkbox is only available for unlisting assets. So if you'd to modify the price, then you can click into the asset bottom to navigate to asset details page in marketplace and modify price or cancel listing there.
4. Select the NFTs with checkbox tick.
Select the list of NFTs in your wish list to execute the bulk-listing.
5. Set the currency listing
There is the dropdown that allow developer to selected token that we'd to list.
Select MYRIA, if the NFTs is intend to list under Myria tokens.
Select ETH, if the NFTs is intend to list under ETH token.
6. Input the price of respective currency listing
Input the price of token. The price input will be shown in the Myria marketplace once it is listing.
Example of NFTs listing with 0.005 ETH
Example of NFTs listing with 500 MYRIA
7. Trigger bulk-listing
Click to the bulk-listing NFT button and wait few mins for the system to processing.
You can check the results at existing page or Inventory page to make sure the NFTs is listed successfully with correct price.