Skip to content

Commit

Permalink
feat: getMultipleTokenPrices (#1175)
Browse files Browse the repository at this point in the history
* feat: add `getMultipleTokenPrices`
  • Loading branch information
b4rtaz authored Jan 31, 2024
1 parent f399901 commit b6f6e18
Show file tree
Hide file tree
Showing 15 changed files with 476 additions and 9 deletions.
7 changes: 7 additions & 0 deletions .changeset/cuddly-walls-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@moralisweb3/common-evm-utils': patch
'@moralisweb3/evm-api': patch
'moralis': patch
---

Added the `getMultipleTokenPrices` method to the EVM API.
3 changes: 2 additions & 1 deletion packages/common/evmUtils/generator.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"getNFTTokenStats",
"getNFTCollectionStats",
"getBlockStats",
"getTokenStats"
"getTokenStats",
"getMultipleTokenPrices"
]
}
}
Expand Down
24 changes: 22 additions & 2 deletions packages/common/evmUtils/src/generated/client/abstractClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { GetNFTTradesOperation, GetNFTTradesOperationRequest, GetNFTTradesOperationRequestJSON } from '../operations/GetNFTTradesOperation';
import { EvmTradeCollection, EvmTradeCollectionJSON } from '../types/EvmTradeCollection';
import { GetMultipleTokenPricesOperation, GetMultipleTokenPricesOperationRequest, GetMultipleTokenPricesOperationRequestJSON } from '../operations/GetMultipleTokenPricesOperation';
import { EvmErc20Price, EvmErc20PriceJSON } from '../types/EvmErc20Price';
import { EvmGetMultipleTokenPricesDto, EvmGetMultipleTokenPricesDtoInput, EvmGetMultipleTokenPricesDtoJSON } from '../types/EvmGetMultipleTokenPricesDto';
import { Web3ApiVersionOperation, Web3ApiVersionOperationRequest, Web3ApiVersionOperationRequestJSON } from '../operations/Web3ApiVersionOperation';
import { EvmWeb3version, EvmWeb3versionJSON } from '../types/EvmWeb3version';
import { EndpointWeightsOperation, EndpointWeightsOperationRequest, EndpointWeightsOperationRequestJSON } from '../operations/EndpointWeightsOperation';
Expand Down Expand Up @@ -120,10 +123,10 @@ export abstract class AbstractClient {
* * Provide the param 'from_block' or 'from_date'
* * If 'from_date' and 'from_block' are provided, 'from_block' will be used. (optional)
* @param {String} [request.toBlock] The block number to get the trades from (optional)
* @param {String} [request.fromDate] The start date from which to get the transfers (any format that is accepted by momentjs)
* @param {String} [request.fromDate] The start date from which to get the transfers (format in seconds or datestring accepted by momentjs)
* * Provide the param 'from_block' or 'from_date'
* * If 'from_date' and 'from_block' are provided, 'from_block' will be used. (optional)
* @param {String} [request.toDate] The end date from which to get the transfers (any format that is accepted by momentjs)
* @param {String} [request.toDate] The end date from which to get the transfers (format in seconds or datestring accepted by momentjs)
* * Provide the param 'to_block' or 'to_date'
* * If 'to_date' and 'to_block' are provided, 'to_block' will be used. (optional)
* @param {Object} [request.marketplace] Marketplace from which to get the trades (only OpenSea is supported at the moment) (optional)
Expand Down Expand Up @@ -166,6 +169,23 @@ export abstract class AbstractClient {
>(GetNFTTokenStatsOperation),
};
public readonly token = {
/**
* @description Returns an array of token prices denominated in the blockchain's native token and USD for a given token contract address
* @param request Request with parameters.
* @param {Object} [request.chain] The chain to query (optional)
* @param {Object} [request.include] If the result should contain the 24hr percent change (optional)
* @param body Request body.
* @param {Object[]} body.tokens The tokens to be fetched
* @returns {Object[]} Response for the request.
*/
getMultipleTokenPrices: this.createEndpointWithBody<
GetMultipleTokenPricesOperationRequest,
GetMultipleTokenPricesOperationRequestJSON,
EvmErc20Price[],
EvmErc20PriceJSON[],
EvmGetMultipleTokenPricesDtoInput | EvmGetMultipleTokenPricesDto,
EvmGetMultipleTokenPricesDtoJSON
>(GetMultipleTokenPricesOperation),
/**
* @description Get the stats for a erc20 token
* @param request Request with parameters.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { EvmChain, EvmChainInput, EvmChainJSON } from '../../dataTypes';
import { EvmGetMultipleTokenPricesIncludeEnum, EvmGetMultipleTokenPricesIncludeEnumValue, EvmGetMultipleTokenPricesIncludeEnumInput, EvmGetMultipleTokenPricesIncludeEnumJSON } from '../types/EvmGetMultipleTokenPricesIncludeEnum';
import { EvmErc20Price, EvmErc20PriceJSON } from '../types/EvmErc20Price';
import { EvmGetMultipleTokenPricesDto, EvmGetMultipleTokenPricesDtoInput, EvmGetMultipleTokenPricesDtoJSON } from '../types/EvmGetMultipleTokenPricesDto';

// request parameters:
// - chain ($ref: #/components/schemas/chainList)
// - include ($ref: #/paths/~1erc20~1prices/post/parameters/1/schema)

export interface GetMultipleTokenPricesOperationRequest {
/**
* @description The chain to query
*/
readonly chain?: EvmChainInput | EvmChain;
/**
* @description If the result should contain the 24hr percent change
*/
readonly include?: EvmGetMultipleTokenPricesIncludeEnumInput | EvmGetMultipleTokenPricesIncludeEnumValue;
}

export interface GetMultipleTokenPricesOperationRequestJSON {
readonly chain?: EvmChainJSON;
readonly include?: EvmGetMultipleTokenPricesIncludeEnumJSON;
}

export type GetMultipleTokenPricesOperationResponse = EvmErc20Price[];
export type GetMultipleTokenPricesOperationResponseJSON = EvmErc20PriceJSON[];

export type GetMultipleTokenPricesOperationBody = EvmGetMultipleTokenPricesDtoInput | EvmGetMultipleTokenPricesDto;

export const GetMultipleTokenPricesOperation = {
operationId: "getMultipleTokenPrices",
groupName: "token",
httpMethod: "post",
routePattern: "/erc20/prices",
parameterNames: ["chain","include"],
hasResponse: true,
hasBody: true,

parseResponse(json: EvmErc20PriceJSON[]): EvmErc20Price[] {
return json.map((item) => EvmErc20Price.fromJSON(item));
},

serializeRequest(request: GetMultipleTokenPricesOperationRequest): GetMultipleTokenPricesOperationRequestJSON {
const chain = request.chain ? EvmChain.create(request.chain) : undefined;
const include = request.include ? EvmGetMultipleTokenPricesIncludeEnum.create(request.include) : undefined;
return {
chain: chain ? chain.toJSON() : undefined,
include: include ? include : undefined,
};
},

serializeBody(body: EvmGetMultipleTokenPricesDtoInput | EvmGetMultipleTokenPricesDto): EvmGetMultipleTokenPricesDtoJSON {
const value = EvmGetMultipleTokenPricesDto.create(body);
return value.toJSON();
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ export interface GetNFTTradesOperationRequest {
*/
readonly toBlock?: string;
/**
* @description The start date from which to get the transfers (any format that is accepted by momentjs)
* @description The start date from which to get the transfers (format in seconds or datestring accepted by momentjs)
* * Provide the param 'from_block' or 'from_date'
* * If 'from_date' and 'from_block' are provided, 'from_block' will be used.
*/
readonly fromDate?: string;
/**
* @description The end date from which to get the transfers (any format that is accepted by momentjs)
* @description The end date from which to get the transfers (format in seconds or datestring accepted by momentjs)
* * Provide the param 'to_block' or 'to_date'
* * If 'to_date' and 'to_block' are provided, 'to_block' will be used.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/common/evmUtils/src/generated/operations/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './GetNFTTradesOperation';
export * from './GetMultipleTokenPricesOperation';
export * from './Web3ApiVersionOperation';
export * from './EndpointWeightsOperation';
export * from './GetTopERC20TokensByMarketCapOperation';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GetNFTTradesOperation } from './GetNFTTradesOperation';
import { GetMultipleTokenPricesOperation } from './GetMultipleTokenPricesOperation';
import { Web3ApiVersionOperation } from './Web3ApiVersionOperation';
import { EndpointWeightsOperation } from './EndpointWeightsOperation';
import { GetTopERC20TokensByMarketCapOperation } from './GetTopERC20TokensByMarketCapOperation';
Expand All @@ -15,6 +16,7 @@ import { GetBlockStatsOperation } from './GetBlockStatsOperation';

export const operations = [
GetNFTTradesOperation,
GetMultipleTokenPricesOperation,
Web3ApiVersionOperation,
EndpointWeightsOperation,
GetTopERC20TokensByMarketCapOperation,
Expand Down
6 changes: 3 additions & 3 deletions packages/common/evmUtils/src/generated/types/EvmChainList.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// $ref: #/components/schemas/chainList
// typeName: chainList

export type EvmChainListJSON = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1";
export type EvmChainListInput = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1";
export type EvmChainListValue = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1";
export type EvmChainListJSON = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1" | "chiliz" | "0x15b38" | "chiliz testnet" | "0x15b32" | "gnosis" | "0x64" | "gnosis testnet" | "0x27d8" | "base" | "0x2105" | "base testnet" | "0x14a33" | "optimism" | "0xa";
export type EvmChainListInput = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1" | "chiliz" | "0x15b38" | "chiliz testnet" | "0x15b32" | "gnosis" | "0x64" | "gnosis testnet" | "0x27d8" | "base" | "0x2105" | "base testnet" | "0x14a33" | "optimism" | "0xa";
export type EvmChainListValue = "eth" | "0x1" | "goerli" | "0x5" | "sepolia" | "0xaa36a7" | "polygon" | "0x89" | "mumbai" | "0x13881" | "bsc" | "0x38" | "bsc testnet" | "0x61" | "avalanche" | "0xa86a" | "fantom" | "0xfa" | "palm" | "0x2a15c308d" | "cronos" | "0x19" | "arbitrum" | "0xa4b1" | "chiliz" | "0x15b38" | "chiliz testnet" | "0x15b32" | "gnosis" | "0x64" | "gnosis testnet" | "0x27d8" | "base" | "0x2105" | "base testnet" | "0x14a33" | "optimism" | "0xa";

export abstract class EvmChainList {
public static create(input: EvmChainListInput | EvmChainListValue): EvmChainListValue {
Expand Down
162 changes: 162 additions & 0 deletions packages/common/evmUtils/src/generated/types/EvmErc20Price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { EvmNativeErc20Price, EvmNativeErc20PriceInput, EvmNativeErc20PriceJSON } from '../types/EvmNativeErc20Price';

// $ref: #/components/schemas/erc20Price
// type: erc20Price
// properties:
// - tokenName ($ref: #/components/schemas/erc20Price/properties/tokenName)
// - tokenSymbol ($ref: #/components/schemas/erc20Price/properties/tokenSymbol)
// - tokenLogo ($ref: #/components/schemas/erc20Price/properties/tokenLogo)
// - tokenDecimals ($ref: #/components/schemas/erc20Price/properties/tokenDecimals)
// - nativePrice ($ref: #/components/schemas/nativeErc20Price)
// - usdPrice ($ref: #/components/schemas/erc20Price/properties/usdPrice)
// - usdPriceFormatted ($ref: #/components/schemas/erc20Price/properties/usdPriceFormatted)
// - 24hrPercentChange ($ref: #/components/schemas/erc20Price/properties/24hrPercentChange)
// - exchangeAddress ($ref: #/components/schemas/erc20Price/properties/exchangeAddress)
// - exchangeName ($ref: #/components/schemas/erc20Price/properties/exchangeName)
// - tokenAddress ($ref: #/components/schemas/erc20Price/properties/tokenAddress)
// - toBlock ($ref: #/components/schemas/erc20Price/properties/toBlock)
// - verifiedContract ($ref: #/components/schemas/erc20Price/properties/verifiedContract)

export interface EvmErc20PriceJSON {
readonly tokenName?: string;
readonly tokenSymbol?: string;
readonly tokenLogo?: string;
readonly tokenDecimals?: string;
readonly nativePrice?: EvmNativeErc20PriceJSON;
readonly usdPrice: number;
readonly usdPriceFormatted?: string;
readonly '24hrPercentChange'?: string;
readonly exchangeAddress?: string;
readonly exchangeName?: string;
readonly tokenAddress?: string;
readonly toBlock?: string;
readonly verifiedContract?: boolean;
}

export interface EvmErc20PriceInput {
readonly tokenName?: string;
readonly tokenSymbol?: string;
readonly tokenLogo?: string;
readonly tokenDecimals?: string;
readonly nativePrice?: EvmNativeErc20PriceInput | EvmNativeErc20Price;
readonly usdPrice: number;
readonly usdPriceFormatted?: string;
readonly '24hrPercentChange'?: string;
readonly exchangeAddress?: string;
readonly exchangeName?: string;
readonly tokenAddress?: string;
readonly toBlock?: string;
readonly verifiedContract?: boolean;
}

export class EvmErc20Price {
public static create(input: EvmErc20PriceInput | EvmErc20Price): EvmErc20Price {
if (input instanceof EvmErc20Price) {
return input;
}
return new EvmErc20Price(input);
}

public static fromJSON(json: EvmErc20PriceJSON): EvmErc20Price {
const input: EvmErc20PriceInput = {
tokenName: json.tokenName,
tokenSymbol: json.tokenSymbol,
tokenLogo: json.tokenLogo,
tokenDecimals: json.tokenDecimals,
nativePrice: json.nativePrice ? EvmNativeErc20Price.fromJSON(json.nativePrice) : undefined,
usdPrice: json.usdPrice,
usdPriceFormatted: json.usdPriceFormatted,
'24hrPercentChange': json['24hrPercentChange'],
exchangeAddress: json.exchangeAddress,
exchangeName: json.exchangeName,
tokenAddress: json.tokenAddress,
toBlock: json.toBlock,
verifiedContract: json.verifiedContract,
};
return EvmErc20Price.create(input);
}

/**
* @description The name of the token
*/
public readonly tokenName?: string;
/**
* @description The symbol of the token
*/
public readonly tokenSymbol?: string;
/**
* @description The logo of the token
*/
public readonly tokenLogo?: string;
/**
* @description The number of decimals of the token
*/
public readonly tokenDecimals?: string;
public readonly nativePrice?: EvmNativeErc20Price;
/**
* @description The price in USD for the token
*/
public readonly usdPrice: number;
/**
* @description The price in USD for the token in string format
*/
public readonly usdPriceFormatted?: string;
/**
* @description The 24hr percent change of the token
*/
public readonly '24hrPercentChange'?: string;
/**
* @description The address of the exchange used to calculate the price
*/
public readonly exchangeAddress?: string;
/**
* @description The name of the exchange used to calculate the price
*/
public readonly exchangeName?: string;
/**
* @description The address of the token
*/
public readonly tokenAddress?: string;
/**
* @description toBlock
*/
public readonly toBlock?: string;
/**
* @description Indicates if the contract is verified
*/
public readonly verifiedContract?: boolean;

private constructor(input: EvmErc20PriceInput) {
this.tokenName = input.tokenName;
this.tokenSymbol = input.tokenSymbol;
this.tokenLogo = input.tokenLogo;
this.tokenDecimals = input.tokenDecimals;
this.nativePrice = input.nativePrice ? EvmNativeErc20Price.create(input.nativePrice) : undefined;
this.usdPrice = input.usdPrice;
this.usdPriceFormatted = input.usdPriceFormatted;
this['24hrPercentChange'] = input['24hrPercentChange'];
this.exchangeAddress = input.exchangeAddress;
this.exchangeName = input.exchangeName;
this.tokenAddress = input.tokenAddress;
this.toBlock = input.toBlock;
this.verifiedContract = input.verifiedContract;
}

public toJSON(): EvmErc20PriceJSON {
return {
tokenName: this.tokenName,
tokenSymbol: this.tokenSymbol,
tokenLogo: this.tokenLogo,
tokenDecimals: this.tokenDecimals,
nativePrice: this.nativePrice ? this.nativePrice.toJSON() : undefined,
usdPrice: this.usdPrice,
usdPriceFormatted: this.usdPriceFormatted,
'24hrPercentChange': this['24hrPercentChange'],
exchangeAddress: this.exchangeAddress,
exchangeName: this.exchangeName,
tokenAddress: this.tokenAddress,
toBlock: this.toBlock,
verifiedContract: this.verifiedContract,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { EvmTokenPriceItem, EvmTokenPriceItemInput, EvmTokenPriceItemJSON } from '../types/EvmTokenPriceItem';

// $ref: #/components/schemas/GetMultipleTokenPricesDto
// type: GetMultipleTokenPricesDto
// properties:
// - tokens ($ref: #/components/schemas/tokenPriceItem)

export interface EvmGetMultipleTokenPricesDtoJSON {
readonly tokens: EvmTokenPriceItemJSON[];
}

export interface EvmGetMultipleTokenPricesDtoInput {
readonly tokens: EvmTokenPriceItemInput[] | EvmTokenPriceItem[];
}

export class EvmGetMultipleTokenPricesDto {
public static create(input: EvmGetMultipleTokenPricesDtoInput | EvmGetMultipleTokenPricesDto): EvmGetMultipleTokenPricesDto {
if (input instanceof EvmGetMultipleTokenPricesDto) {
return input;
}
return new EvmGetMultipleTokenPricesDto(input);
}

public static fromJSON(json: EvmGetMultipleTokenPricesDtoJSON): EvmGetMultipleTokenPricesDto {
const input: EvmGetMultipleTokenPricesDtoInput = {
tokens: json.tokens.map((item) => EvmTokenPriceItem.fromJSON(item)),
};
return EvmGetMultipleTokenPricesDto.create(input);
}

/**
* @description The tokens to be fetched
*/
public readonly tokens: EvmTokenPriceItem[];

private constructor(input: EvmGetMultipleTokenPricesDtoInput) {
this.tokens = input.tokens.map((item) => EvmTokenPriceItem.create(item));
}

public toJSON(): EvmGetMultipleTokenPricesDtoJSON {
return {
tokens: this.tokens.map((item) => item.toJSON()),
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// $ref: #/paths/~1erc20~1prices/post/parameters/1/schema
// typeName: getMultipleTokenPrices_include_Enum

export type EvmGetMultipleTokenPricesIncludeEnumJSON = "percent_change";
export type EvmGetMultipleTokenPricesIncludeEnumInput = "percent_change";
export type EvmGetMultipleTokenPricesIncludeEnumValue = "percent_change";

export abstract class EvmGetMultipleTokenPricesIncludeEnum {
public static create(input: EvmGetMultipleTokenPricesIncludeEnumInput | EvmGetMultipleTokenPricesIncludeEnumValue): EvmGetMultipleTokenPricesIncludeEnumValue {
return input;
}

public static fromJSON(json: EvmGetMultipleTokenPricesIncludeEnumJSON): EvmGetMultipleTokenPricesIncludeEnumValue {
return json;
}
}
Loading

1 comment on commit b6f6e18

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage

Title Lines Statements Branches Functions
api-utils Coverage: 20%
20.6% (61/296) 20.48% (17/83) 19.04% (12/63)
auth Coverage: 89%
92.45% (98/106) 83.33% (20/24) 86.66% (26/30)
evm-api Coverage: 90%
90.9% (90/99) 66.66% (6/9) 86.15% (56/65)
common-aptos-utils Coverage: 4%
4.56% (151/3306) 4.49% (25/556) 5.53% (45/813)
common-evm-utils Coverage: 64%
64.51% (1698/2632) 24.4% (186/762) 43.42% (426/981)
sol-api Coverage: 97%
97.56% (40/41) 66.66% (6/9) 93.75% (15/16)
common-sol-utils Coverage: 64%
65.42% (229/350) 41.86% (18/43) 50.89% (57/112)
common-streams-utils Coverage: 90%
90.73% (1204/1327) 73.63% (363/493) 82.07% (444/541)
streams Coverage: 91%
90.54% (603/666) 72.34% (68/94) 90.97% (131/144)

Please sign in to comment.