List ERC721 Assets with Scripts Template
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)
- Myria Marketplace
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.
You can use the getAssetByStarkKey()
function of the OnchainAssetManager
.
- get-myria-erc721.ts
- MyriaAssets.tsx
The getMyriaErc721ByStarkKey()
function has the following parameters:
client
:MyriaClient
instancestarkKey
: Stark Key of your wallet
import { MyriaClient, OnchainAssetManager } from "myria-core-sdk";
export async function getMyriaErc721ByStarkKey(client: MyriaClient, starkKey: string) {
const assetManager: OnchainAssetManager = new OnchainAssetManager(client);
let assets: any = [];
return await assetManager.getAssetByStarkKey(starkKey).then((data: any) => {
assets = data.data.items
});
}
import { MyriaClient } from "myria-core-sdk";
import { useEffect, useState } from "react";
import { getMyriaErc721ByStarkKey } from "./get-myria-erc721";
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 getMyriaErc721ByStarkKey(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. List assets
Listing an ERC721 asset represents a SELL
order of the `MINTABLE_ERC721 token. You can list your asset using the *
OrderManager`*.
- list-erc721.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 fromgetMyriaErc721ByStarkKey()
You can specify the listing price in ETH by changing the price
variable.
import { CreateOrderEntity, FeeType, ModuleFactory, MyriaClient, SignableOrderInput, TokenType } from "myria-core-sdk";
export async function listErc721(client: MyriaClient, account: string, starkKey: string, assetId: string) {
const moduleFactory = new ModuleFactory(client);
const orderManager = moduleFactory.getOrderManager();
const assetManager = moduleFactory.getAssetOnchainManager();
const asset = (await assetManager.getAssetById(assetId)).data;
const price = "0.01";
const signableFee =
(asset.fee && asset?.fee?.length) > 0
? [
{
address: asset?.fee[0].address,
percentage: asset?.fee[0].percentage,
feeType: FeeType.ROYALTY
}
]
: undefined;
const payload: SignableOrderInput = {
orderType: "SELL",
ethAddress: account,
assetRefId: parseInt(assetId, 10),
starkKey: starkKey,
tokenSell: {
type: TokenType.MINTABLE_ERC721,
data: {
tokenId: asset?.tokenId,
tokenAddress: asset?.tokenAddress
}
},
amountSell: "1",
tokenBuy: {
type: TokenType.ETH,
data: {
quantum: "10000000000"
}
},
amountBuy: price + "",
includeFees: signableFee ? true : false,
fees: signableFee
};
const signature = await orderManager?.signableOrder(payload);
const feeSign = signature?.feeInfo
? {
feeLimit: signature?.feeInfo?.feeLimit,
feeToken: signature?.feeInfo?.assetId,
feeVaultId: signature?.feeInfo?.sourceVaultId
}
: undefined;
const feeData = signature?.feeInfo
? [
{
feeType: FeeType.ROYALTY,
percentage: asset?.fee[0].percentage,
address: account
}
]
: undefined;
if (signature) {
const paramCreateOrder: CreateOrderEntity = {
assetRefId: parseInt(assetId, 10),
orderType: "SELL",
feeSign: feeSign,
includeFees: true,
amountSell: signature.amountSell,
amountBuy: signature.amountBuy,
sellerStarkKey: starkKey,
vaultIdSell: signature.vaultIdSell,
vaultIdBuy: signature.vaultIdBuy,
sellerAddress: account,
assetIdBuy: signature.assetIdBuy,
assetIdSell: signature.assetIdSell,
fees: feeData
};
return await orderManager?.createOrder(paramCreateOrder);
}
}
import { MyriaClient } from "myria-core-sdk";
import { useEffect, useState } from "react";
import { getMyriaErc721ByStarkKey } from "./get-myria-erc721";
import { listErc721 } from "./list-erc721";
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 getMyriaErc721ByStarkKey(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;
Listing Multiple Assets
The best way to list a large number of NFTs is to run a script, making multiple calls. This does not incur any fees.
A basic sample script is available here.