hyperspace-sdk
Version:
An unofficial SDK for Hyperspace NFT Marketplace on Avalanche
1,375 lines (1,241 loc) • 34 kB
text/typescript
import { Wallet } from "ethers";
import { JsonRpcBatchProvider } from "@ethersproject/providers";
import axios from "axios";
import {
Result,
Listing,
CollectionBid,
Buy,
Sale,
Order,
Nft,
OrderConfig,
ProjectStats,
} from "./types";
import {
getWavaxBalance,
getWavaxApprovalStatus,
approveWavax,
getNftApprovalStatus,
approveNft,
handleSignAndExecute,
handleSignTransaction,
} from "./utils/helpers";
import { PaginationConfig } from "./types";
export class Hyperspace {
apiKey: string;
wallet: Wallet;
provider: JsonRpcBatchProvider;
gasPriceMultiplier: number = 1;
gasLimitMultiplier: number = 1;
constructor(apiKey: string, rpcHttpUrl: string, privateKey: string) {
this.apiKey = apiKey;
this.provider = new JsonRpcBatchProvider(rpcHttpUrl);
const wallet = new Wallet(`0x${privateKey}`);
this.wallet = wallet.connect(this.provider);
}
getGasPriceMultiplier(): number {
return this.gasPriceMultiplier;
}
updateGasPriceMultiplier(
newGasPriceMultiplier: number
): Result<number, Error> {
if (newGasPriceMultiplier < 1 || newGasPriceMultiplier > 20) {
return {
success: false,
error: new Error("Gas price multiplier must be between 1 and 10"),
};
}
this.gasPriceMultiplier = newGasPriceMultiplier;
return {
success: true,
value: newGasPriceMultiplier,
};
}
getGasLimitMultiplier(): number {
return this.gasLimitMultiplier;
}
updateGasLimitMultiplier(
newGasLimitMultiplier: number
): Result<number, Error> {
if (newGasLimitMultiplier < 1 || newGasLimitMultiplier > 20) {
return {
success: false,
error: new Error("Gas limit multiplier must be between 1 and 10"),
};
}
this.gasLimitMultiplier = newGasLimitMultiplier;
return {
success: true,
value: newGasLimitMultiplier,
};
}
public async getListingsForProject(
projectId?: string,
paginationInfo?: PaginationConfig
): Promise<Result<Listing[], Error>> {
const data = JSON.stringify({
condition: {
project_ids: [
{
project_id: projectId,
},
],
listing_type: "NORMAL",
},
order_by: {
field_name: "listing_display_price",
sort_order: "ASC",
},
pagination_info: paginationInfo,
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-collection-view",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to send request to fetch listings: ${error}`),
};
}
const listings: Listing[] = response.data.collection_view_data;
if (!listings) {
return {
success: false,
error: new Error("Unable to find listings"),
};
}
return {
success: true,
value: listings,
};
}
/**
* Fetch listings for a specific collection.
* Right now, it ONLY fetches in ASCENDING order of price.
* @param projectId Project ID of the collection to fetch listings for.
* @param quantity Maximum number of listings to fetch.
* @returns Array of listings or error.
*/
// TODO: Is `quantity` really necessary?
public async getListingsForUser(
userAddress?: string,
projectId?: string,
paginationInfo?: PaginationConfig
): Promise<Result<Listing[], Error>> {
const data = JSON.stringify({
condition: {
owner: userAddress ? userAddress : this.wallet.address,
project_ids: [
{
project_id: projectId,
},
],
listing_type: "NORMAL",
},
order_by: {
field_name: "listing_display_price",
sort_order: "ASC",
},
pagination_info: paginationInfo,
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-collection-view",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to send request to fetch listings: ${error}`),
};
}
const listings: Listing[] = response.data.collection_view_data;
if (!listings) {
return {
success: false,
error: new Error("Unable to find listings"),
};
}
return {
success: true,
value: listings,
};
}
/**
* Get a specific listing.
* @param collectionAddress Address of the collection to fetch listing for.
* @param tokenId Token ID of the listing to fetch.
* @returns Listing or error.
*/
async getListing(
collectionAddress: string,
tokenId: string
): Promise<Result<Listing, Error>> {
const data = JSON.stringify({
condition: {
token_addresses: [`${collectionAddress}_${tokenId}`],
},
order_by: {
field_name: "listing_display_price",
sort_order: "ASC",
},
pagination_info: {
page_number: 1,
page_size: 1,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-collection-view",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to send request to fetch listing: ${error}`),
};
}
const listing: Listing = response.data.collection_view_data[0];
if (!listing) {
return {
success: false,
error: new Error("Unable to find listing"),
};
}
return {
success: true,
value: listing,
};
}
/**
* Fetch collection bids for a specific collection.
* Right now, it ONLY outputs collection bids in DESCENDING order of price.
* @param collectionAddress
* @returns Array of collection bids or error.
*/
async getCollectionBidsForProject(
collectionAddress: string
): Promise<Result<CollectionBid[], Error>> {
const data = JSON.stringify({
condition: {
contract_address: collectionAddress,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-collection-bids-for-project",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to get collection bids for project: ${error}`
),
};
}
const bids: CollectionBid[] = response.data.bids;
if (!bids) {
return {
success: false,
error: new Error("No bids found for project"),
};
}
return {
success: true,
value: bids,
};
}
async getCollectionBidsForProjectAndUser(
collectionAddress: string,
userAddress?: string
): Promise<Result<CollectionBid[], Error>> {
if (collectionAddress === "") {
throw new Error("Missing collection address");
}
if (!userAddress) {
userAddress = this.wallet.address;
}
const data = JSON.stringify({
condition: {
contract_address: collectionAddress,
buyer_address: userAddress,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-collection-bids-for-project-and-user",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to get collection bids for project and user: ${error}`
),
};
}
const bids: CollectionBid[] = response.data.bids;
if (!bids) {
return {
success: false,
error: new Error("No bids found for project"),
};
}
return {
success: true,
value: bids,
};
}
async getTokenRarityScore(
collectionAddress: string,
tokenId: string
): Promise<Result<number, Error>> {
const getListingResult = await this.getListing(collectionAddress, tokenId);
if (!getListingResult.success) {
return {
success: false,
error: getListingResult.error,
};
}
const listing = getListingResult.value;
return {
success: true,
value: listing.data.rarity_snapshot.hyperspace,
};
}
/**
* List a specific NFT (executes on chain).
* @param collectionAddress
* @param tokenId
* @param listingPriceAvax
* @returns Order or error.
*/
async list(
collectionAddress: string,
tokenId: string,
listingPriceWei: number
): Promise<Result<Order, Error>> {
const sellerAddress = this.wallet.address;
const tokenAddress = `${collectionAddress}_${tokenId}`;
let isApproved;
try {
isApproved = await getNftApprovalStatus(
this.provider,
sellerAddress,
collectionAddress
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to get NFT approval status: ${error}`),
};
}
if (!isApproved) {
try {
await approveNft(this.wallet, collectionAddress);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to approve NFT: ${error}`),
};
}
}
const data = JSON.stringify({
condition: {
list_tx_args: [
{
token_address: tokenAddress,
seller_address: sellerAddress as string,
metadata: {
contractAddress: collectionAddress,
tokenId,
price: listingPriceWei.toString(),
},
},
],
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-list-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to create list transaction: ${error}`
),
};
}
const order = response.data[0].metadata;
if (response.data?.length && order) {
let handleSignTransactionResult;
try {
handleSignTransactionResult = await handleSignTransaction(
order,
this.wallet
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute: ${error}`),
};
}
const signedOrder = JSON.parse(
handleSignTransactionResult.transactionBlockBytes
);
try {
await this.validateSignature(signedOrder);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to validate signature: ${error}`),
};
}
return {
success: true,
value: order,
};
} else {
return {
success: false,
error: new Error(`Unable to create list transaction: ${response.data}`),
};
}
}
/**
* Delist a specific NFT (executes on chain).
* @param listing
* @returns Transaction hash or error.
*/
async delist(
collectionAddress: string,
price: number,
metadata: any
): Promise<Result<string, Error>> {
const data = JSON.stringify({
condition: {
delist_tx_args: [
{
seller_address: this.wallet.address,
token_address: collectionAddress,
price: (price * 10 ** 18).toString(),
metadata: metadata,
},
],
},
});
const requestConfig = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-delist-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestConfig);
} catch (error: any) {
return {
success: false,
error: new Error(
`Unable to send request to create delist transaction: ${error}`
),
};
}
const encodedTransaction = response.data[0].byte_string;
if (response.data?.length && encodedTransaction) {
let transactionReceipt;
try {
transactionReceipt = await handleSignAndExecute(
this.wallet,
this.gasPriceMultiplier,
this.gasLimitMultiplier,
{
data: encodedTransaction,
}
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute`),
};
}
if (transactionReceipt.transactionHash) {
return {
success: true,
value: transactionReceipt.transactionHash,
};
} else {
return {
success: false,
error: new Error(`Invalid transaction receipt`),
};
}
} else {
return {
success: false,
error: new Error(`Unable to create delist transaction`),
};
}
}
// async updateListing(
// collectionAddress: string,
// tokenId: string,
// newListingPriceWei: number
// ) {
// const sellerAddress = this.wallet.address;
// const tokenAddress = `${collectionAddress}_${tokenId}`;
// let isApproved;
// try {
// isApproved = await getNftApprovalStatus(
// this.provider,
// sellerAddress,
// collectionAddress
// );
// } catch (error: unknown) {
// return {
// success: false,
// error: new Error(`Unable to get NFT approval status: ${error}`),
// };
// }
// const data = JSON.stringify({
// condition: {
// list_tx_args: [
// {
// token_address: tokenAddress,
// seller_address: sellerAddress as string,
// metadata: {
// contractAddress: collectionAddress,
// tokenId,
// price: newListingPriceWei.toString(),
// },
// },
// ],
// },
// });
// const requestArguments = {
// method: "post",
// url: "https://avax.api.hyperspace.xyz/rest/create-update-listing-tx",
// headers: {
// "Content-Type": "application/json",
// Authorization: this.apiKey,
// },
// data: data,
// };
// let response;
// try {
// response = await axios.request(requestArguments);
// } catch (error: unknown) {
// return {
// success: false,
// error: new Error(
// `Unable to send request to create update listing transaction: ${error}`
// ),
// };
// }
// console.log(response.data);
// }
/**
* Creates a collection bid (), executes on chain
* @param contractAddress
* @param bidAmount
* @returns
*/
async collectionBid(
contractAddress: string,
bidAmountWei: number
): Promise<Result<Order, Error>> {
const bidderAddress = this.wallet.address;
const wavaxBalance = await getWavaxBalance(this.provider, bidderAddress);
let isApproved;
try {
isApproved = await getWavaxApprovalStatus(
this.provider,
bidderAddress,
wavaxBalance
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to fetch NFT approval status: ${error}`),
};
}
if (!isApproved) {
try {
await approveWavax(this.wallet);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to approve NFT: ${error}`),
};
}
}
const data = JSON.stringify({
condition: {
price: bidAmountWei,
buyer_address: bidderAddress,
metadata: {
contractAddress,
price: bidAmountWei.toString(),
},
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-collection-bid-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to create collection bid transaction: ${error}`
),
};
}
const order = response.data[0].metadata;
if (response.data?.length && order) {
let handleSignTransactionResult;
try {
handleSignTransactionResult = await handleSignTransaction(
order,
this.wallet
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute: ${error}`),
};
}
const signedOrder = JSON.parse(
handleSignTransactionResult.transactionBlockBytes
);
try {
await this.validateSignature(signedOrder);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to validate signature: ${error}`),
};
}
return {
success: true,
value: order,
};
} else {
return {
success: false,
error: new Error(
`Unable to create collection bid transaction: ${response.data}`
),
};
}
}
/**
* Cancel a collection bid (executes on-chain).
* @param collection_bid
* @returns Transaction hash or error.
*/
async cancelCollectionBid(
collectionBid: CollectionBid
): Promise<Result<string, Error>> {
const data = JSON.stringify({
condition: {
buyer_address: this.wallet.address,
price: collectionBid.price,
metadata: collectionBid.metadata,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-cancel-collection-bid-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to create cancel collection bid transaction: ${error}`
),
};
}
const encodedTransaction = response.data[0].byte_string;
if (response.data?.length && encodedTransaction) {
let transactionReceipt;
try {
transactionReceipt = await handleSignAndExecute(
this.wallet,
this.gasPriceMultiplier,
this.gasLimitMultiplier,
{
data: encodedTransaction,
}
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute: ${error}`),
};
}
if (transactionReceipt.transactionHash) {
return {
success: true,
value: transactionReceipt.transactionHash,
};
}
return {
success: false,
error: new Error(`Invalid transaction receipt`),
};
} else {
return {
success: false,
error: new Error(`Unable to create cancel collection bid transaction`),
};
}
}
async updateCollectionBid() {}
/**
* Buy (create buy transaction) a specific NFT on-chain.
* @param collectionAddress
* @param tokenId
* @returns Transaction hash or error.
*/
async buy(
collectionAddress: string,
tokenId: string
): Promise<Result<Buy, Error>> {
const getListingResult = await this.getListing(collectionAddress, tokenId);
if (!getListingResult.success) {
return {
success: false,
error: getListingResult.error,
};
}
const listing = getListingResult.value;
const listingPriceAvax = listing.price.raw_price;
const listingMetadata = listing.data.listing_snapshot.metadata;
if (!listingPriceAvax) {
return {
success: false,
error: new Error("Unable to find listing price"),
};
}
if (!listingMetadata) {
return {
success: false,
error: new Error("Unable to find listing metadata"),
};
}
const buyTransactionArguments = [
{
buyer_address: this.wallet.address.toString(),
token_address: listing.data.token_address,
price: listingPriceAvax,
metadata: listingMetadata,
},
];
const data = JSON.stringify({
condition: {
buy_tx_args: buyTransactionArguments,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-buy-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to create buy transaction: ${error}`
),
};
}
const totalAmountToPay = [
BigInt(listingMetadata.event_log.erc20TokenAmount),
...listingMetadata.event_log.fees.map((fee: any) => BigInt(fee.amount)),
].reduce((a, b) => a + b);
if (response.data?.length && response.data[0].byte_string) {
const encodedTransaction = response.data[0].byte_string;
let transactionReceipt;
try {
transactionReceipt = await handleSignAndExecute(
this.wallet,
this.gasPriceMultiplier,
this.gasLimitMultiplier,
{
data: encodedTransaction,
value: totalAmountToPay,
}
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute: ${error}`),
};
}
const transactionHash = transactionReceipt.transactionHash;
if (transactionReceipt.status == 1 && transactionHash) {
return {
success: true,
value: {
transactionHash: transactionReceipt.transactionHash,
price: listingPriceAvax,
},
};
}
return {
success: false,
error: new Error(`Invalid transaction receipt`),
};
} else {
return {
success: false,
error: new Error(`Unable to create buy transaction`),
};
}
}
/**
* Sell (create accept collection bid transaction) a specific NFT on-chain.
* By default, it will accept the highest bid for the NFT.
* If you want to accept a specific bid, pass the bid amount as a parameter.
* @param collectionAddress
* @param tokenId
* @returns Transaction hash, price, and fee or error.
*/
async executeSell(
collectionAddress: string,
tokenId: string
// bidAmount?: number
): Promise<Result<Sale, Error>> {
const sellerAddress = this.wallet.address;
let isApproved;
try {
isApproved = await getNftApprovalStatus(
this.provider,
sellerAddress,
collectionAddress
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to fetch NFT approval status: ${error}`),
};
}
if (!isApproved) {
try {
await approveNft(this.wallet, collectionAddress);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to approve NFT: ${error}`),
};
}
}
const getCollectionBidsForProjectResult =
await this.getCollectionBidsForProject(collectionAddress);
if (!getCollectionBidsForProjectResult.success) {
return {
success: false,
error: getCollectionBidsForProjectResult.error,
};
}
const bid = getCollectionBidsForProjectResult.value[0];
const bidPrice = bid.price;
const bidFee = bid.fee;
const bidMetadata = bid.metadata;
if (!bidPrice) {
return {
success: false,
error: new Error(`No collection bid price found for highest bid`),
};
}
if (!bidFee) {
return {
success: false,
error: new Error(`No collection bid fee found for highest bid`),
};
}
if (!bidMetadata) {
return {
success: false,
error: new Error(`No collection bid metadata found for highest bid`),
};
}
const data = JSON.stringify({
condition: {
token_address: `${collectionAddress}_${tokenId}`,
price: bidPrice,
seller_address: sellerAddress,
metadata: bidMetadata,
},
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/create-accept-collection-bid-tx",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to create accept collection bid transaction: ${error}`
),
};
}
if (response.data?.length && response.data[0].byte_string) {
const encodedTransaction = response.data[0].byte_string;
let transactionReceipt;
try {
transactionReceipt = await handleSignAndExecute(
this.wallet,
this.gasPriceMultiplier,
this.gasLimitMultiplier,
{
data: encodedTransaction,
}
);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to handle sign and execute: ${error}`),
};
}
const transactionHash = transactionReceipt.transactionHash;
if (transactionReceipt.status == 1 && transactionHash) {
return {
success: true,
value: {
transactionHash,
price: bidPrice,
fee: bidFee,
},
};
}
return {
success: false,
error: new Error(`Invalid transaction receipt`),
};
} else {
return {
success: false,
error: new Error(`Unable to create accept collection bid transaction`),
};
}
}
async userBids(contractAddress?: string, tokenId?: string) {
const userAddress = this.wallet.address;
try {
const data = JSON.stringify({
condition: {
owner: userAddress,
listing_type: "NORMAL",
project_ids: [
{
project_id: "c43f2070-8d90-40f2-a81a-d564889263ee",
},
],
},
});
const requestConfig = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-marketplace-snapshots",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
const response = await axios.request(requestConfig);
const marketplace_snapshots = response.data.marketplace_snapshots;
console.log(marketplace_snapshots);
} catch (error: any) {
console.log(error);
return {
digest: null,
errors: error.message,
};
}
}
async userListings() {
const userAddress = this.wallet.address;
// "condition": {
// "token_address": "string",
// "project_id": "string",
// "action_type": "string",
// "buyer_address": "string",
// "seller_address": "string",
// "marketplace_programs": [
// {}
// ],
// "populate_snapshot": true
// }
try {
const data = JSON.stringify({
condition: {
buyer_address: userAddress,
},
});
const requestConfig = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-user-listings",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
const res = await axios.request(requestConfig);
} catch (error: any) {
console.log(error);
return {
digest: null,
errors: error.message,
};
}
}
// TODO: Promise<Result<any, Error>>
async validateSignature(signedOrder: any) {
const data = JSON.stringify({
order: signedOrder,
});
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/validate-signature",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
throw new Error(`Unable to validate signature: ${error}`);
}
return response;
}
/**
* Get all NFTs owned by a specific user.
* If no user address is provided, it will fetch NFTs owned by this client's wallet address.
*/
async getUserOwnedNfts(
userAddress?: string,
projectId?: string,
pagination?: PaginationConfig
): Promise<Result<Nft[], Error>> {
const data = JSON.stringify(
projectId
? {
condition: {
owner: userAddress ? userAddress : this.wallet.address,
project_ids: [
{
project_id: projectId,
},
],
},
pagination_info: pagination,
}
: {
condition: {
owner: userAddress,
},
pagination_info: pagination,
}
);
const requestArguments = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-marketplace-snapshots",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data,
};
let response;
try {
response = await axios.request(requestArguments);
} catch (error: unknown) {
return {
success: false,
error: new Error(`Unable to send request to fetch listings: ${error}`),
};
}
return { success: true, value: response.data.marketplace_snapshots };
}
async getCollectionStats(
projectId?: string,
orderBy?: OrderConfig[],
pagination?: PaginationConfig
): Promise<Result<ProjectStats[], Error>> {
const data = JSON.stringify(
projectId
? {
condition: {
project_ids: [projectId],
},
order_by: orderBy,
pagination_info: pagination,
}
: {
order_by: orderBy,
pagination_info: pagination,
}
);
const args = {
method: "post",
url: "https://avax.api.hyperspace.xyz/rest/get-project-stats",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data,
};
let res;
try {
res = await axios.request(args);
} catch (error: unknown) {
return {
success: false,
error: new Error(
`Unable to send request to get collection stats: ${error}`
),
};
}
return { success: true, value: res.data.project_stats };
}
async getCollectionActivity(
collection: string,
actionTypes?: string[],
pagination?: PaginationConfig
) {
const data = JSON.stringify({
condition: {
projects: [
{
project_id: collection,
},
],
action_types: actionTypes,
},
pagination_info: pagination,
});
const config = {
method: "post",
maxBodyLength: Infinity,
url: "https://avax.api.hyperspace.xyz/rest/get-collection-activity",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
return (await axios.request(config)).data;
}
async getUserActivity(
walletAddress: string,
actionTypes?: string[],
pagination?: PaginationConfig
) {
const data = JSON.stringify({
condition: {
user_address: walletAddress,
action_types: actionTypes,
},
pagination_info: pagination,
});
const config = {
method: "post",
maxBodyLength: Infinity,
url: "https://avax.api.hyperspace.xyz/rest/get-user-activity",
headers: {
"Content-Type": "application/json",
Authorization: this.apiKey,
},
data: data,
};
return (await axios.request(config)).data;
}
}