Learn how to manage multiple API keys and network endpoints in the same project using Alchemy SDK
Introduction
Web3 development often requires interacting with multiple blockchain networks, each with its own API endpoint and authentication keys. Managing all these connections and ensuring the correct API key and endpoint are used for each chain can be time-consuming and error-prone. Alchemy SDK provides a solution to this problem with its AlchemyMultiChainClient
, a wrapper around the Alchemy SDK that allows for easy management of multiple chains in a single application. In this tutorial, we'll walk through a demo project that demonstrates how to use the AlchemyMultiChainClient
to query NFTs for an owner on multiple chains.
Project Setup
To follow along with this tutorial, you'll need to have Node.js and npm installed on your machine. You'll also need to clone the demo project from Alchemy's GitHub repository by running the following command in your terminal:
git clone https://github.com/alchemyplatform/alchemy-multichain-demo.git
After cloning the repo, navigate to the project directory and run the following command to install its dependencies:
cd alchemy-multichain-demo
npm install
Now that we have the demo project set up, we can move on to querying multiple chains.
Querying Multiple Chains
The src/index.ts
file contains a simple demo that uses the AlchemyMultichainClient
class to make requests across multiple chains. Let's walk through the code to understand how it works.
import { AlchemyMultichainClient } from './alchemy-multichain-client';
import { Network } from 'alchemy-sdk';
async function main() {
// Default config to use for all networks.
const defaultConfig = {
apiKey: 'demo', // TODO: Replace with your Mainnet Alchemy API key.
network: Network.ETH_MAINNET
};
// Include optional setting overrides for specific networks.
const overrides = {
// TODO: Replace with your API keys.
[Network.MATIC_MAINNET]: { apiKey: 'demo', maxRetries: 10 }, // Replace with your Matic Alchemy API key.
[Network.ARB_MAINNET]: { apiKey: 'demo' } // Replace with your Arbitrum Alchemy API key.
};
const alchemy = new AlchemyMultichainClient(defaultConfig, overrides);
// get NFTs in multiple networks
const owner = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';
const mainnetNfts = await alchemy
.forNetwork(Network.ETH_MAINNET)
.nft.getNftsForOwner(owner, { pageSize: 5 });
const maticNfts = await alchemy
.forNetwork(Network.MATIC_MAINNET)
.nft.getNftsForOwner(owner, { pageSize: 5 });
console.log('mainnetNfts', mainnetNfts);
console.log('maticNfts', maticNfts);
}
main();
First, we import the necessary modules:
import { AlchemyMultichainClient } from './alchemy-multichain-client';
import { Network } from 'alchemy-sdk';
The AlchemyMultichainClient
class is imported from the alchemy-multichain-client
file in the same directory, and the Network
is imported from the Alchemy SDK.
Next, we define the configuration settings for our multichain application. This is done by creating a defaultConfig
object which contains the default settings that will be used across all networks. In this example, the defaultConfig
object includes an Alchemy API key and specifies the ETH_MAINNET
as the default network.
const defaultConfig = {
apiKey: 'demo',
network: Network.ETH_MAINNET
};
We can also include optional setting overrides for specific networks, if needed. This is done by creating an overrides
object which maps network IDs to their respective configuration overrides. For example, in the overrides object in the example code below, we are overriding the API key for the MATIC_MAINNET
and ARB_MAINNET
networks.
const overrides = {
[Network.MATIC_MAINNET]: { apiKey: 'demo', maxRetries: 10 }, // Replace 'demo' with your Alchemy Matic API key
[Network.ARB_MAINNET]: { apiKey: 'demo' } // Replace 'demo' with your Alchemy Arbitrum key
};
With the configuration settings defined, we can now create an instance of the AlchemyMultichainClient
by passing in the defaultConfig
and overrides
objects.
const alchemy = new AlchemyMultichainClient(defaultConfig, overrides);
Once the AlchemyMultichainClient
instance is created, we can start making requests to different networks using the forNetwork
method. This method returns a new instance of the AlchemyMultichainClient
with the specified network settings, so you can chain requests together.
In the example code below, we are using the forNetwork
method to make requests to the ETH_MAINNET
and MATIC_MAINNET
networks to get the NFTs for an owner with a specified wallet address. We are also specifying the pageSize option to limit the number of NFTs returned to 5.
const owner = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';
const mainnetNfts = await alchemy
.forNetwork(Network.ETH_MAINNET)
.nft.getNftsForOwner(owner, { pageSize: 5 });
const maticNfts = await alchemy
.forNetwork(Network.MATIC_MAINNET)
.nft.getNftsForOwner(owner, { pageSize: 5 });
Finally, we log the results of our requests to the console.
console.log('mainnetNfts', mainnetNfts);
console.log('maticNfts', maticNfts);
Testing the Script
To test the script, make sure you have typescript installed by running this command, in the root of terminal:
npm install -g typescript
Next, you need to compile your TypeScript file by running the following command:
tsc src/index.ts
This will generate a JavaScript file called index.js in the same directory as your index.ts file. You can then run the index.js file using Node.js:
node src/index.js
Finally, it will log the mainnetNfts
and maticNfts
for the given owner in your terminal 🎉
mainnetNfts {
ownedNfts: [
{
contract: [Object],
tokenId: '1',
tokenType: 'ERC721',
title: '',
description: '',
timeLastUpdated: '2023-02-17T16:10:26.611Z',
metadataError: undefined,
rawMetadata: {},
tokenUri: [Object],
media: [],
spamInfo: [Object],
balance: 26
},
{
contract: [Object],
tokenId: '2',
tokenType: 'ERC721',
title: '',
description: '',
timeLastUpdated: '2023-02-17T14:43:29.829Z',
metadataError: undefined,
rawMetadata: {},
tokenUri: [Object],
media: [],
spamInfo: [Object],
balance: 31
},
{
contract: [Object],
tokenId: '3',
tokenType: 'ERC721',
title: '',
description: '',
timeLastUpdated: '2023-02-17T15:55:26.778Z',
metadataError: undefined,
rawMetadata: {},
tokenUri: [Object],
media: [],
spamInfo: [Object],
balance: 18
},
{
contract: [Object],
tokenId: '4',
tokenType: 'ERC721',
title: '',
description: '',
timeLastUpdated: '2023-02-17T16:06:04.731Z',
metadataError: undefined,
rawMetadata: {},
tokenUri: [Object],
media: [],
spamInfo: [Object],
balance: 33
},
{
contract: [Object],
tokenId: '5',
tokenType: 'ERC721',
title: '',
description: '',
timeLastUpdated: '2023-02-17T16:05:53.096Z',
metadataError: undefined,
rawMetadata: {},
tokenUri: [Object],
media: [],
spamInfo: [Object],
balance: 33
}
],
pageKey: 'MHgwMDAzODZlM2Y3NTU5ZDliNmEyZjVjNDZiNGFkMWE5NTg3ZDU5ZGMzOjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNTpmYWxzZQ==',
totalCount: 25853
}
maticNfts {
ownedNfts: [
{
contract: [Object],
tokenId: '2168',
tokenType: 'ERC721',
title: 'Process Series. Artdrop II. Natalie Portman',
description: 'Accursed Share is proud to present Captured Moment: The Master’s Process, the first NFT collection by photographer-to-the-stars Frederic Auerbach. The collection consists of NFT drops of process and master photos (1/1s) of five A-listers, plus airdrops. The stars in this collection are Benedict Cumberbatch, Natalie Portman, Sharon Stone, Mike Tyson and Zendaya.\n' +
'\n' +
'The Process Series reveals the delicate behind-the-scenes construction required for the production of a Master work. It includes 1,700 NFTs of 30 unique photographs of different rarity (150, 100, 50, 25, 10, 5). \n' +
' \n' +
'For the Master Series, each celebrity will have their own NFT set, including: a dynamic NFT highlighting different aspects of the Master photo by displaying various edits of the image at different times of day; the high-res digital photo NFT of the Master (one per star); a high-res and autographed print of each Master photo, and a unique video NFT of the behind-the-scenes interview detailing Auerbach’s creative approach, from Process to Master.\n' +
'\n' +
'Artdrop I corresponds to the Process Series. It is a slightly animated video NFT of a process photo of Zendaya’s 2013 Flaunt photoshoot by Frederic Auerbach. \n' +
'\n' +
'Artdrop I is exclusively for the first 1000 wallets on the whitelist. It is stored on the Polygon blockchain.\n' +
'\n' +
'\n' +
'Credits: Photography: Frederic Auerbach / Filmography: Gary Grenier / Producers: Accursed Share (Mónica Belevan, John Thomas Connor, Marcus de Ataide); André Antonelli, Frederic Auerbach, Eric Holdener / Engineer: Marcus de Ataide \n' +
'\n' +
'Captured Moment: The Master’s Process is an Accursed Share production, in association with Frederic Auerbach. \n' +
'\n' +
'Part of the proceeds from this project will be donated to Farm2People, Los Angeles.',
timeLastUpdated: '2023-01-31T11:45:48.853Z',
metadataError: undefined,
rawMetadata: [Object],
tokenUri: [Object],
media: [Array],
spamInfo: undefined,
balance: 1
},
{
contract: [Object],
tokenId: '1',
tokenType: 'ERC1155',
title: 'Forgotten Sketch #1',
description: '***Minting is currently live here: https://doodlesnft.shop.*** *First time minting of original AI sketches of the Doodles collection.* Doodles have quickly become one of the most actively traded and highly valued NFT collections on OpenSea. Before colorful Doodles graced the NFT world, each character first had to be sketched. For the first time, we are offering exquisite AI-generated sketches of each Doodle in the 10,000-piece collection. Close inspection of the each detailed drawing will reveal the artistic care and sophisticated AI that went into creating this collection. Over 100 different AI tools has been used in rendering these one-of-a kind sketches. No others will be produced like them. In this public offering, only one minting is available for each unique Doodle, and every owner will receive an individual ERC-721 token with proof of ownership on the Ethereum blockchain.',
timeLastUpdated: '2023-02-01T23:58:19.990Z',
metadataError: undefined,
rawMetadata: [Object],
tokenUri: [Object],
media: [Array],
spamInfo: undefined,
balance: 1
},
{
contract: [Object],
tokenId: '3232',
tokenType: 'ERC721',
title: 'Post by @rabbithole.lens',
description: "Crypto can be a scary place sometimes. But you're on a journey of a lifetime. The short term challenges don't dictate our destination. \n" +
'\n' +
'The deeper you go, the brighter it gets.',
timeLastUpdated: '2023-02-01T19:24:49.335Z',
metadataError: undefined,
rawMetadata: [Object],
tokenUri: [Object],
media: [],
spamInfo: undefined,
balance: 1
},
{
contract: [Object],
tokenId: '1',
tokenType: 'ERC1155',
title: "Ethereum World's Metaverse Genesis Chest",
description: "The Ethereum World's Metaverse Genesis Chest represents the access to an exclusive airdrop within the Ethereum Worlds' ecosystem. Claim your apt and take part in our [metaverse](https://www.ethereumtowers.world/?ps=50).",
timeLastUpdated: '2023-02-15T20:49:16.868Z',
metadataError: undefined,
rawMetadata: [Object],
tokenUri: [Object],
media: [Array],
spamInfo: undefined,
balance: 1
},
{
contract: [Object],
tokenId: '6702',
tokenType: 'ERC721',
title: 'Astrobot #6702',
description: 'Astrobots arrived on Earth from Deep Space. They can be funny, cute, grumpy or mysterious. BEWARE: not all of them are friendly!',
timeLastUpdated: '2023-01-31T10:47:18.461Z',
metadataError: undefined,
rawMetadata: [Object],
tokenUri: [Object],
media: [Array],
spamInfo: undefined,
balance: 1
}
],
pageKey: 'MHgwMzNmN2IyMGM5Y2ZlNGQwYTQxZDhlMTVkNDVmOGM3OTkzZTRlMzhhOjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMWEyZTpmYWxzZQ==',
totalCount: 2497
}
Conclusion
In this tutorial, we have seen how to use the Alchemy SDK with multiple chains in a single application using the AlchemyMultichainClient
class. We have also seen how to manage the different API keys and endpoints for different chains. With the knowledge gained from this tutorial, you can now start building your own multichain applications using the Alchemy SDK.