Alchemy SDK QuickStart
Alchemy SDK is a lightweight, modular JavaScript SDK that encapsulates common usage patterns and abstracts away the complexities of both HTTP and JSON-RPC endpoints.

Alchemy SDK for Javascript

Alchemy SDK helps developers use Alchemy's APIs and endpoints more efficiently. This is a lightweight, modular SDK that encapsulates common usage patterns and abstracts away the complexities of both our HTTP and JSON-RPC endpoints.

Public Beta

Note that the SDK is still in public beta. Alchemy reserves the right to (and almost certainly will) make breaking API changes in subsequent releases (don't write production code around it just yet).

Questions & Feedback

For all SDK related questions and feedback please send us a message in the SDK channel in discord :)

Getting started

Check out the full Github repo here:
https://github.com/alchemyplatform/alchemy-sdk-js
github.com
Install the SDK:
1
npm install @alch/alchemy-sdk
Copied!
After installing the app, you can then import and use the SDK:
1
import { Network, initializeAlchemy } from '@alch/alchemy-sdk';
2
โ€‹
3
// Optional Config object, but defaults to demo api-key and eth-mainnet.
4
const settings = {
5
apiKey: 'demo', // Replace with your Alchemy API Key.
6
network: Network.ETH_MAINNET, // Replace with your network.
7
maxRetries: 10
8
};
9
โ€‹
10
const alchemy = initializeAlchemy(settings);
Copied!
The SDK's modular approach exports all functions at the top-level to reduce bundle size (only the functions you import and use will be included). This means you access each method using the following pattern:
1
// Initializing the alchemy config object
2
import { initializeAlchemy, getNftsForOwner } from '@alch/alchemy-sdk';
3
โ€‹
4
const alchemy = initializeAlchemy(); // using default settings - pass in a settings object to specify your API key and network
5
โ€‹
6
getNftsForOwner(alchemy, '0xshah.eth').then(console.log);
Copied!
However, this can make it harder to discover the full API surface. If you want your IDE to find all functions, you can alternatively import the entire SDK (though this is not recommended, as it will increase the bundle size):
1
import * as alchemySdk from '@alch/alchemy-sdk';
2
โ€‹
3
const alchemy = alchemySdk.initializeAlchemy();
4
alchemySdk.getNftsForOwner(alchemy, '0xshah.eth').then(console.log);
Copied!

SDK Structure

The Alchemy object returned by initializeAlchemy() provides access to the Alchemy API. An optional config object can be passed in when initializing to set your API key, change the network, or specify the max number of retries.
There are two different patterns for the Alchemy object to be used:
  1. 1.
    It can be passed into top-level functions like getNftsForOwner() or getAssetTransfers(). The current supported functions using this pattern are the Alchemy NFT API endpoints and Alchemy Enhanced APIs.
  2. 2.
    It can be used to generate an Ethers.js provider that allows access to Alchemy Provider-specific Ethers.js methods. These encompass most standard JSON-RPC requests to the blockchain.

Ethers.js for standard JSON-RPC Calls

To access standard JSON-RPC calls not in the NFT API or Alchemy Enhanced APIs, the SDK includes Ethers.js. The Alchemy.getProvider() function configures the Ethers.js AlchemyProvider and returns it. This allows you to perform core JSON-RPC calls with an Alchemy provider, just as you normally would with Ethers. If you are already using Ethers, you can simply use the provider from alchemy-sdk and the rest of your code should just work:
1
import { initializeAlchemy } from '@alch/alchemy-sdk';
2
โ€‹
3
const alchemy = initializeAlchemy();
4
โ€‹
5
// ETH JSON-RPC calls through ethers.js Provider
6
const ethersAlchemyProvider = alchemy.getProvider();
7
ethersAlchemyProvider
8
.getBalance('0x994b342dd87fc825f66e51ffa3ef71ad818b6893', 'latest')
9
.then(console.log);
Copied!
Consult the Ethers.js documentation for how to use it to call standard JSON-RPC methods.

Websockets and Subscription Listeners

In addition to the built-in Ethers.js listeners, the Alchemy SDK includes support for Alchemy's Subscription API. This allows you to subscribe to events and receive updates as they occur. The two supported subscriptions are alchemy_newFullPendingTransactions and alchemy_filteredNewFullPendingTransactions .
The Alchemy.getWebsocketProvider() function configures the Alchemy AlchemyWebSocketProvider and returns it. This can be used like the standard Ethers.js Websocket provider to add listeners for Alchemy events:
1
import { initializeAlchemy } from '@alch/alchemy-sdk';
2
โ€‹
3
const alchemy = initializeAlchemy();
4
โ€‹
5
const websocketProvider = alchemy.getWebsocketProvider();
6
โ€‹
7
// Listen to all new pending transactions.
8
websocketProvider.on({
9
method: 'alchemy_newFullPendingTransactions',
10
}, res => console.log(res));
11
โ€‹
12
// Listen to all transactions on the USDC contract.
13
websocketProvider.on({
14
method: 'alchemy_filteredNewFullPendingTransactions',
15
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
16
}, res => console.log(res));
Copied!
The SDK brings multiple improvements to ensure correct WebSocket behavior in cases of temporary network failure or dropped connections. As with any network connection, you should not assume that a WebSocket will remain open forever without interruption, but correctly handling dropped connections and reconnection by hand can be challenging to get right. alchemy-sdk automatically handles these failures with no configuration necessary. The main benefits are:
  • Resilient event delivery: Unlike standard Web3.js or Ethers.js, you will not permanently miss events which arrive while the backing WebSocket is temporarily down. Instead, you will receive these events as soon as the connection is reopened. Note that if the connection is down for more than 120 blocks (approximately 20 minutes), you may still miss some events that were not part of the most recent 120 blocks.
  • Lowered rate of failure: Compared to standard Web3.js or Ethers.js, there are fewer failures when sending requests over the WebSocket while the connection is down. Alchemy Web3 will attempt to send the requests once the connection is reopened. Note that it is still possible, with a lower likelihood, for outgoing requests to be lost, so you should still have error handling as with any network request.

NFT Module

The SDK currently supports the following NFT API endpoints, for the full list see here:
  • getNftMetadata(): Gets the NFT metadata for a contract address and tokenId.
  • getNftsForOwner(): Get NFTs for an owner address.
  • getNftsForOwnerIterator(): Get NFTs for an owner address as an async iterator (handles paging automatically).
  • getNftsForCollection(): Gets all NFTs for a contract address.
  • getNftForCollectionIterator(): Gets all NFTs for a contract address as an async iterator (handles paging automatically).
  • getOwnersForNft(): Get all the owners for a given NFT contract address and token ID.
  • checkNftOwnership(): Checks that the provided owner address owns one or more of the provided NFT contract addresses.
  • findContractDeployer(): Finds the contract deployer and block number for a given NFT contract address.
  • refreshNftMetadata(): Refreshes the cached NFT metadata for a contract address and tokenId.

Comparing BaseNft and Nftโ€‹

The SDK currently uses the BaseNft and Nft classes to represent NFTs returned by the Alchemy. The BaseNft object does not hold any metadata information and only contains the NFT contract and token ID. The Nft object additionally contains the NFT metadata, token URI information, and media.
By default, the SDK will return the Nft object. You can optionally choose to fetch the BaseNft object instead by setting the omitMetadata parameter to true. The SDK documentation describes the different parameter and response interfaces in more detail.

Pagination

The Alchemy NFT endpoints return 100 results per page. To get the next page, you can pass in the pageKey returned by the previous call. To simplify paginating through all results, the SDK provides the getNftsIterator() and getNftsForCollectionIterator() functions that automatically paginate through all NFTs and yields them via an AsyncIterable.
Here's an example of how to paginate through all the NFTs in Vitalik's ENS address:
1
import { initializeAlchemy, getNftsForOwnerIterator } from "@alch/alchemy-sdk";
2
const alchemy = initializeAlchemy();
3
โ€‹
4
async function main() {
5
const ownerAddress = "vitalik.eth";
6
for await (const nft of getNftsForOwnerIterator(alchemy, ownerAddress)) {
7
console.log("ownedNft:", nft);
8
}
9
}
10
โ€‹
11
main();
Copied!

SDK vs NFT API Differences

The NFT API in the SDK standardizes response types to reduce developer friction, but note this results in some differences compared to the Alchemy REST endpoints:
  • Some methods have different naming that the REST API counterparts in order to provide a consistent API interface ( e.g. getNftsForOwner() is alchemy_getNfts, getOwnersForNft() is alchemy_getOwnersForToken).
  • SDK standardizes to omitMetadata parameter (vs. withMetadata).
  • Standardization to pageKey parameter for pagination (vs. nextToken/startToken)
  • Empty TokenUri fields are omitted.
  • Token ID is always normalized to an integer string on BaseNft and Nft.
  • Some fields omitted in the REST response are included in the SDK response in order to return an Nft object.
  • Some fields in the SDK's Nft object are named differently than the REST response.

Documentation

The SDK is documented via tsdoc comments in the source code. The generated types and documentation are included when using an IDE. To browse the documentation separately, you can view the generated API interfaces in the GitHub repository.

Future Work

There's a long list, but here are the main ones:
  • More config options for the base ethers.js AlchemyProvider.
  • Most of these changes require extending the base ethers.js SDK with custom implementations.
  • Separating SDK into separate packages.

Examples

Below are a few usage examples:

Getting the NFTs owned by an address

1
import {
2
getNftsForOwner,
3
getNftsForOwnerIterator,
4
NftExcludeFilters,
5
initializeAlchemy,
6
} from "@alch/alchemy-sdk";
7
โ€‹
8
const alchemy = initializeAlchemy();
9
โ€‹
10
// Get how many NFTs an address owns.
11
getNftsForOwner(alchemy, "0xshah.eth").then((nfts) => {
12
console.log(nfts.totalCount);
13
});
14
โ€‹
15
// Get all the image urls for all the NFTs an address owns.
16
async function main() {
17
for await (const nft of getNftsForOwnerIterator(alchemy, "0xshah.eth")) {
18
console.log(nft.media);
19
}
20
}
21
โ€‹
22
main();
23
โ€‹
24
// Filter out spam NFTs.
25
getNftsForOwner(alchemy, "0xshah.eth", {
26
excludeFilters: [NftExcludeFilters.SPAM],
27
}).then(console.log);
Copied!

Getting all the owners of the BAYC NFT

1
import {
2
getOwnersForNft,
3
getNftsForCollectionIterator,
4
initializeAlchemy
5
} from '@alch/alchemy-sdk';
6
โ€‹
7
const alchemy = initializeAlchemy();
8
โ€‹
9
// Bored Ape Yacht Club contract address.
10
const baycAddress = '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D';
11
โ€‹
12
async function main() {
13
for await (const nft of getNftsForCollectionIterator(alchemy, baycAddress, {
14
// Omit the NFT metadata for smaller payloads.
15
omitMetadata: true
16
})) {
17
await getOwnersForNft(alchemy, nft).then(response =>
18
console.log('owners:', response.owners, 'tokenId:', nft.tokenId)
19
);
20
}
21
}
22
โ€‹
23
main();
Copied!

Get all outbound transfers for a provided address

1
import { getTokenBalances, initializeAlchemy } from "@alch/alchemy-sdk";
2
const alchemy = initializeAlchemy();
3
โ€‹
4
getTokenBalances(alchemy, "0x994b342dd87fc825f66e51ffa3ef71ad818b6893").then(
5
console.log
6
);
Copied!