This site requires Javascript to be enabled.

If it's your first time building an Archway dapp frontend, head over to the Creating Your First dapp guide to learn how to setup your basic project scaffolding. Once you're serving a web page that connects to Keplr, you'll be ready to follow the next steps.


One thing to note is that, by default, Keplr overrides the fees set by the frontend. To prevent Keplr from overriding these fees, set the Interactive Option value of preferNoSetFee to true. You can find more information on these override options here.

Loading NFT the collection

As we saw in the previous guide, to query a contract we need to know its address on chain. We also need an instance of SigningArchwayClient.

// For more on setting up this handler see the "Creating Your First dapp" guide (linked to above):const client = await SigningArchwayClient.connect('');// Replace this empty string with your deployed contract addressconst contractAddress = '';

Using the above two variables we can write JavaScript to query the NFT collection for its token ids like this:

async function getNfts() {  let entrypoint = {    all_tokens: {},  };  let query = await queryHandler(contract, entrypoint);  console.log('All NFTs of contract ' + contract + ':', query);  return query;}

The getNfts function returns a tokens object containing an array of all tokens minted by the contract.

Here's an example of calling it:

let nfts;async function doGetNfts() {  nfts = await getNfts();  console.log('All NFT ids', nfts);}doGetNfts();

Minting from the dapp

To mint from our dapp, we need to assemble the metadata fields for the NFT. We can achieve this by making a web UI with form fields where the NFT creator can add custom traits to their NFT.

We can simplify our remaining task by writing a function which takes the required NFT metadata as parameters. With that in mind, here's what a minting function looks like in JavaScript:

async function mintNft(owner, tokenId, imageUrl, name, description, attributes = []) {  // Ensure we collected the required arguments  if (!owner || !tokenId || !imageUrl || !name || !description) {    console.warn('Error parsing mint arguments', { owner, tokenId, imageUrl, name, description });    return;  }  // Prepare Tx  let entrypoint = {    mint: {      token_id: String(nfts.tokens.length),      owner: owner,      extension: {        name: name,        description: description,        image: imageUrl,      },    },  };  // If the creator used any arbitrary custom attributes, add them to the entrypoint  if (attributes.length) { = attributes;  }  try {    // Send Tx    let tx = await CosmWasmClient.execute(owner, contract, entrypoint, 'auto');    console.log('Mint Tx', tx);    // Refresh the NFT collection to resolve the new token    await getNfts();  } catch (e) {    console.warn('Error executing mint tx', e);  }}

Here's an example of what it might be like to call our mintNft function:

// Example call:async function doMintNft() {  let mintTx = await mintNft(    (owner = 'archway1f395p0gg67mmfd5zcqvpnp9cxnu0hg6r9hfczq'),    (tokenId = '2'),    (imageUrl = 'ipfs://QmY8Ei2NQkMg8rCFiUkcXH2NPWPNKMoWLBYDwBeMNsP5sr'),    (name = 'Archway NFT #2'),    (description = 'Building With NFTs (and Dapps)'),    (attributes = [{ trait_type: 'tutorial', value: '' }])  );  console.log('Mint tx', mintTx);}doMintNft();

Transferring NFTs

Now that we can mint from our dapp, the form and entrypoint parameters for transferring NFTs are much simpler. Just like transfers initiated from the Developer CLI, we need the recipient's Archway address and the token_id we are sending to them. We also need to know the address of the current owner, and a reference to the contract address that we set up earlier.

Here's what a JavaScript function to transfer an Archway NFT looks like:

async function transferNft(owner, recipient, tokenId) {  if (!owner || !recipient || !tokenId) {    console.warn('Error parsing transfer_nft arguments', { owner, recipient, tokenId });    return;  }  // Prepare Tx  let entrypoint = {    transfer_nft: {      recipient: recipient,      token_id: tokenId,    },  };  // Send Tx  try {    let tx = await SigningArchwayClient.connectWithSigner(network.endpoint, wallet);    console.log('Transfer Tx', tx);    // Refresh the NFT collection    await getNfts();  } catch (e) {    console.warn('Error executing NFT transfer', e);  }}

Calling the above function might look like this:

// Example call:async function doTransferNft() {  let transferTx = await transferNft(    (owner = 'archway1f395p0gg67mmfd5zcqvpnp9cxnu0hg6r9hfczq'),    (recipient = 'archway1y00hm50lffnxt5m0kuy9afk83gyuye684zwcr5'),    (tokenId = '2')  );  console.log('Transfer tx', transferTx);}doTransferNft();

Displaying NFTs

The getNfts function we created returns all token ids minted by the contract, but one more step is needed before we can display NFTs from our collection in our dapp. To read an NFT's metadata we call the nft_info entrypoint we executed from CLI in the previous lesson.

Here's what loading token metadata looks like using JavaScript:

async function getTokenMeta(tokenId) {  if (typeof tokenId !== 'string') {    console.warn('Invalid token ID. Token ID must be a string, but got ' + typeof tokenId);    return;  }  let entrypoint = {    nft_info: {      token_id: tokenId,    },  };  let query = await this.handlers.query(contract, entrypoint);  console.log('NFT contract succesfully  queried for token ID ' + tokenId, query);  return query;}

An example of calling the getTokenMeta function might look like this:

// Example call:async function doGetTokenMeta() {  let token2 = await getTokenMeta('2');  console.log('Metadata for token_id: "2"', token2);}doGetTokenMeta();


Note: If your NFT image was uploaded to IPFS, using an IPFS url like ipfs://... your web application will need to resolve the image source from an IPFS gateway (read more about IPFS gateways and providers).

Clone it and try yourself

This guide focused on core features of Archway NFTs, some basic aspects of web development haven't been looked at in detail, but you'll find working example frontends for this project in the dapp examples repository.