Skip to content

Commit

Permalink
feat: profitability endpoint (#1214)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabkk authored Jun 24, 2024
1 parent 4f50dae commit 9ddc8c3
Show file tree
Hide file tree
Showing 17 changed files with 894 additions and 2 deletions.
7 changes: 7 additions & 0 deletions .changeset/proud-cycles-sit.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
---

Adding new Profitability endpoints to the SDK
21 changes: 21 additions & 0 deletions demos/cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ async function main() {
protocol: 'uniswap-v2',
});
console.log('defiProtocolPositions', defiProtocolPositions.result.toJSON().positions);

const walletProfitabilitySummary = await Moralis.EvmApi.wallets.getWalletProfitabilitySummary({
address: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
days: 'all',
chain: '0x1',
});
console.log('walletProfitabilitySummary', walletProfitabilitySummary.result.toJSON());

const walletProfitability = await Moralis.EvmApi.wallets.getWalletProfitability({
address: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
days: 'all',
chain: '0x1',
});
console.log('walletProfitability', walletProfitability.result.toJSON());

const topProfitableWalletPerToken = await Moralis.EvmApi.token.getTopProfitableWalletPerToken({
address: '0x4a220e6096b25eadb88358cb44068a3248254675',
days: 'all',
chain: '0x1',
});
console.log('topProfitableWalletPerToken', topProfitableWalletPerToken.result.toJSON());
}

main();
5 changes: 4 additions & 1 deletion packages/common/evmUtils/generator.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@
"getTokenOwners",
"getDefiSummary",
"getDefiPositionsByProtocol",
"getDefiPositionsSummary"
"getDefiPositionsSummary",
"getWalletProfitabilitySummary",
"getWalletProfitability",
"getTopProfitableWalletPerToken"
]
}
}
Expand Down
49 changes: 49 additions & 0 deletions packages/common/evmUtils/src/generated/client/abstractClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ import { GetTokenStatsOperation, GetTokenStatsOperationRequest, GetTokenStatsOpe
import { EvmErc20TokenStat, EvmErc20TokenStatJSON } from '../types/EvmErc20TokenStat';
import { GetBlockStatsOperation, GetBlockStatsOperationRequest, GetBlockStatsOperationRequestJSON } from '../operations/GetBlockStatsOperation';
import { EvmBlockTokenStat, EvmBlockTokenStatJSON } from '../types/EvmBlockTokenStat';
import { GetWalletProfitabilitySummaryOperation, GetWalletProfitabilitySummaryOperationRequest, GetWalletProfitabilitySummaryOperationRequestJSON } from '../operations/GetWalletProfitabilitySummaryOperation';
import { EvmGetWalletProfitabilitySummary, EvmGetWalletProfitabilitySummaryJSON } from '../types/EvmGetWalletProfitabilitySummary';
import { GetWalletProfitabilityOperation, GetWalletProfitabilityOperationRequest, GetWalletProfitabilityOperationRequestJSON } from '../operations/GetWalletProfitabilityOperation';
import { EvmWalletProfitabilityResponse, EvmWalletProfitabilityResponseJSON } from '../types/EvmWalletProfitabilityResponse';
import { GetTopProfitableWalletPerTokenOperation, GetTopProfitableWalletPerTokenOperationRequest, GetTopProfitableWalletPerTokenOperationRequestJSON } from '../operations/GetTopProfitableWalletPerTokenOperation';
import { EvmWalletTopProfitableWalletPerTokenResponse, EvmWalletTopProfitableWalletPerTokenResponseJSON } from '../types/EvmWalletTopProfitableWalletPerTokenResponse';

export interface OperationV3<Request, RequestJSON, Response, ResponseJSON, Body, BodyJSON> {
operationId: string;
Expand Down Expand Up @@ -329,6 +335,20 @@ export abstract class AbstractClient {
EvmErc20TokenStat,
EvmErc20TokenStatJSON
>(GetTokenStatsOperation),
/**
* @description Retrieves a list of the top profitable wallets for a specific ERC20 token.
* @param request Request with parameters.
* @param {Object} request.address The ERC20 token address.
* @param {String} [request.days] Timeframe in days for which profitability is calculated, can be 'all', '7d' or '30d' (optional)
* @param {Object} [request.chain] The chain to query (optional)
* @returns {Object} Response for the request.
*/
getTopProfitableWalletPerToken: this.createEndpoint<
GetTopProfitableWalletPerTokenOperationRequest,
GetTopProfitableWalletPerTokenOperationRequestJSON,
EvmWalletTopProfitableWalletPerTokenResponse,
EvmWalletTopProfitableWalletPerTokenResponseJSON
>(GetTopProfitableWalletPerTokenOperation),
};
public readonly utils = {
/**
Expand Down Expand Up @@ -504,5 +524,34 @@ export abstract class AbstractClient {
EvmWalletStat,
EvmWalletStatJSON
>(GetWalletStatsOperation),
/**
* @description Retrieves a summary of wallet profitability based on specified parameters including optional token addresses.
* @param request Request with parameters.
* @param {Object} request.address The wallet address for which profitability summary is to be retrieved.
* @param {String} [request.days] Timeframe in days for the profitability summary. Options include 'all', '7', '30', '60', '90' default is 'all'. (optional)
* @param {Object} [request.chain] The chain to query (optional)
* @returns {Object} Response for the request.
*/
getWalletProfitabilitySummary: this.createEndpoint<
GetWalletProfitabilitySummaryOperationRequest,
GetWalletProfitabilitySummaryOperationRequestJSON,
EvmGetWalletProfitabilitySummary,
EvmGetWalletProfitabilitySummaryJSON
>(GetWalletProfitabilitySummaryOperation),
/**
* @description Retrieves profitability information for a specific wallet address. Can be filtered by one or more tokens.
* @param request Request with parameters.
* @param {Object} request.address The wallet address for which profitability is to be retrieved.
* @param {String} [request.days] Timeframe in days for which profitability is calculated, Options include 'all', '7', '30', '60', '90' default is 'all'. (optional)
* @param {Object} [request.chain] The chain to query (optional)
* @param {Object[]} [request.tokenAddresses] The token addresses list to filter the result with (optional)
* @returns {Object} Response for the request.
*/
getWalletProfitability: this.createEndpoint<
GetWalletProfitabilityOperationRequest,
GetWalletProfitabilityOperationRequestJSON,
EvmWalletProfitabilityResponse,
EvmWalletProfitabilityResponseJSON
>(GetWalletProfitabilityOperation),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { EvmAddress, EvmAddressInput, EvmAddressJSON, EvmChain, EvmChainInput, EvmChainJSON } from '../../dataTypes';
import { EvmWalletTopProfitableWalletPerTokenResponse, EvmWalletTopProfitableWalletPerTokenResponseJSON } from '../types/EvmWalletTopProfitableWalletPerTokenResponse';

// request parameters:
// - address ($ref: #/paths/~1erc20~1{address}~1top-gainers/get/parameters/0/schema)
// - days ($ref: #/paths/~1erc20~1{address}~1top-gainers/get/parameters/1/schema)
// - chain ($ref: #/components/schemas/discoveryApiChainsList)

export interface GetTopProfitableWalletPerTokenOperationRequest {
/**
* @description The ERC20 token address.
*/
readonly address: EvmAddressInput | EvmAddress;
/**
* @description Timeframe in days for which profitability is calculated, can be 'all', '7d' or '30d'
*/
readonly days?: string;
/**
* @description The chain to query
*/
readonly chain?: EvmChainInput | EvmChain;
}

export interface GetTopProfitableWalletPerTokenOperationRequestJSON {
readonly address: EvmAddressJSON;
readonly days?: string;
readonly chain?: EvmChainJSON;
}

export type GetTopProfitableWalletPerTokenOperationResponse = EvmWalletTopProfitableWalletPerTokenResponse;
export type GetTopProfitableWalletPerTokenOperationResponseJSON = EvmWalletTopProfitableWalletPerTokenResponseJSON;

export const GetTopProfitableWalletPerTokenOperation = {
operationId: "getTopProfitableWalletPerToken",
groupName: "token",
httpMethod: "get",
routePattern: "/erc20/{address}/top-gainers",
parameterNames: ["address","days","chain"],
hasResponse: true,
hasBody: false,

parseResponse(json: EvmWalletTopProfitableWalletPerTokenResponseJSON): EvmWalletTopProfitableWalletPerTokenResponse {
return EvmWalletTopProfitableWalletPerTokenResponse.fromJSON(json);
},

serializeRequest(request: GetTopProfitableWalletPerTokenOperationRequest): GetTopProfitableWalletPerTokenOperationRequestJSON {
const address = EvmAddress.create(request.address);
const days = request.days;
const chain = request.chain ? EvmChain.create(request.chain) : undefined;
return {
address: address.toJSON(),
days: days,
chain: chain ? chain.toJSON() : undefined,
};
},

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { EvmAddress, EvmAddressInput, EvmAddressJSON, EvmChain, EvmChainInput, EvmChainJSON } from '../../dataTypes';
import { EvmWalletProfitabilityResponse, EvmWalletProfitabilityResponseJSON } from '../types/EvmWalletProfitabilityResponse';

// request parameters:
// - address ($ref: #/paths/~1wallets~1{address}~1profitability/get/parameters/0/schema)
// - days ($ref: #/paths/~1wallets~1{address}~1profitability/get/parameters/1/schema)
// - chain ($ref: #/components/schemas/discoveryApiChainsList)
// - token_addresses ($ref: #/paths/~1wallets~1{address}~1profitability/get/parameters/3/schema)

export interface GetWalletProfitabilityOperationRequest {
/**
* @description The wallet address for which profitability is to be retrieved.
*/
readonly address: EvmAddressInput | EvmAddress;
/**
* @description Timeframe in days for which profitability is calculated, Options include 'all', '7', '30', '60', '90' default is 'all'.
*/
readonly days?: string;
/**
* @description The chain to query
*/
readonly chain?: EvmChainInput | EvmChain;
/**
* @description The token addresses list to filter the result with
*/
readonly tokenAddresses?: EvmAddressInput[] | EvmAddress[];
}

export interface GetWalletProfitabilityOperationRequestJSON {
readonly address: EvmAddressJSON;
readonly days?: string;
readonly chain?: EvmChainJSON;
readonly token_addresses?: EvmAddressJSON[];
}

export type GetWalletProfitabilityOperationResponse = EvmWalletProfitabilityResponse;
export type GetWalletProfitabilityOperationResponseJSON = EvmWalletProfitabilityResponseJSON;

export const GetWalletProfitabilityOperation = {
operationId: "getWalletProfitability",
groupName: "wallets",
httpMethod: "get",
routePattern: "/wallets/{address}/profitability",
parameterNames: ["address","days","chain","token_addresses"],
hasResponse: true,
hasBody: false,

parseResponse(json: EvmWalletProfitabilityResponseJSON): EvmWalletProfitabilityResponse {
return EvmWalletProfitabilityResponse.fromJSON(json);
},

serializeRequest(request: GetWalletProfitabilityOperationRequest): GetWalletProfitabilityOperationRequestJSON {
const address = EvmAddress.create(request.address);
const days = request.days;
const chain = request.chain ? EvmChain.create(request.chain) : undefined;
const tokenAddresses = request.tokenAddresses ? request.tokenAddresses.map((item) => EvmAddress.create(item)) : undefined;
return {
address: address.toJSON(),
days: days,
chain: chain ? chain.toJSON() : undefined,
token_addresses: tokenAddresses ? tokenAddresses.map((item) => item.toJSON()) : undefined,
};
},

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { EvmAddress, EvmAddressInput, EvmAddressJSON, EvmChain, EvmChainInput, EvmChainJSON } from '../../dataTypes';
import { EvmGetWalletProfitabilitySummary, EvmGetWalletProfitabilitySummaryJSON } from '../types/EvmGetWalletProfitabilitySummary';

// request parameters:
// - address ($ref: #/paths/~1wallets~1{address}~1profitability~1summary/get/parameters/0/schema)
// - days ($ref: #/paths/~1wallets~1{address}~1profitability~1summary/get/parameters/1/schema)
// - chain ($ref: #/components/schemas/discoveryApiChainsList)

export interface GetWalletProfitabilitySummaryOperationRequest {
/**
* @description The wallet address for which profitability summary is to be retrieved.
*/
readonly address: EvmAddressInput | EvmAddress;
/**
* @description Timeframe in days for the profitability summary. Options include 'all', '7', '30', '60', '90' default is 'all'.
*/
readonly days?: string;
/**
* @description The chain to query
*/
readonly chain?: EvmChainInput | EvmChain;
}

export interface GetWalletProfitabilitySummaryOperationRequestJSON {
readonly address: EvmAddressJSON;
readonly days?: string;
readonly chain?: EvmChainJSON;
}

export type GetWalletProfitabilitySummaryOperationResponse = EvmGetWalletProfitabilitySummary;
export type GetWalletProfitabilitySummaryOperationResponseJSON = EvmGetWalletProfitabilitySummaryJSON;

export const GetWalletProfitabilitySummaryOperation = {
operationId: "getWalletProfitabilitySummary",
groupName: "wallets",
httpMethod: "get",
routePattern: "/wallets/{address}/profitability/summary",
parameterNames: ["address","days","chain"],
hasResponse: true,
hasBody: false,

parseResponse(json: EvmGetWalletProfitabilitySummaryJSON): EvmGetWalletProfitabilitySummary {
return EvmGetWalletProfitabilitySummary.fromJSON(json);
},

serializeRequest(request: GetWalletProfitabilitySummaryOperationRequest): GetWalletProfitabilitySummaryOperationRequestJSON {
const address = EvmAddress.create(request.address);
const days = request.days;
const chain = request.chain ? EvmChain.create(request.chain) : undefined;
return {
address: address.toJSON(),
days: days,
chain: chain ? chain.toJSON() : undefined,
};
},

}
3 changes: 3 additions & 0 deletions packages/common/evmUtils/src/generated/operations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ export * from './GetNFTCollectionStatsOperation';
export * from './GetNFTTokenStatsOperation';
export * from './GetTokenStatsOperation';
export * from './GetBlockStatsOperation';
export * from './GetWalletProfitabilitySummaryOperation';
export * from './GetWalletProfitabilityOperation';
export * from './GetTopProfitableWalletPerTokenOperation';
export * from './operations';
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import { GetNFTCollectionStatsOperation } from './GetNFTCollectionStatsOperation
import { GetNFTTokenStatsOperation } from './GetNFTTokenStatsOperation';
import { GetTokenStatsOperation } from './GetTokenStatsOperation';
import { GetBlockStatsOperation } from './GetBlockStatsOperation';
import { GetWalletProfitabilitySummaryOperation } from './GetWalletProfitabilitySummaryOperation';
import { GetWalletProfitabilityOperation } from './GetWalletProfitabilityOperation';
import { GetTopProfitableWalletPerTokenOperation } from './GetTopProfitableWalletPerTokenOperation';

export const operations = [
GetNFTTradesOperation,
Expand Down Expand Up @@ -56,4 +59,7 @@ export const operations = [
GetNFTTokenStatsOperation,
GetTokenStatsOperation,
GetBlockStatsOperation,
GetWalletProfitabilitySummaryOperation,
GetWalletProfitabilityOperation,
GetTopProfitableWalletPerTokenOperation,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// $ref: #/components/schemas/discoveryApiChainsList
// typeName: discoveryApiChainsList

export type EvmDiscoveryApiChainsListJSON = "eth" | "mainnet" | "0x1" | "matic" | "0x89" | "polygon" | "bsc" | "binance" | "0x38" | "fantom" | "ftm" | "0xfa" | "arbitrum" | "0xa4b1" | "optimism" | "0xa" | "pulsechain" | "0x171" | "base" | "0x2105";
export type EvmDiscoveryApiChainsListInput = "eth" | "mainnet" | "0x1" | "matic" | "0x89" | "polygon" | "bsc" | "binance" | "0x38" | "fantom" | "ftm" | "0xfa" | "arbitrum" | "0xa4b1" | "optimism" | "0xa" | "pulsechain" | "0x171" | "base" | "0x2105";
export type EvmDiscoveryApiChainsListValue = "eth" | "mainnet" | "0x1" | "matic" | "0x89" | "polygon" | "bsc" | "binance" | "0x38" | "fantom" | "ftm" | "0xfa" | "arbitrum" | "0xa4b1" | "optimism" | "0xa" | "pulsechain" | "0x171" | "base" | "0x2105";

export abstract class EvmDiscoveryApiChainsList {
public static create(input: EvmDiscoveryApiChainsListInput | EvmDiscoveryApiChainsListValue): EvmDiscoveryApiChainsListValue {
return input;
}

public static fromJSON(json: EvmDiscoveryApiChainsListJSON): EvmDiscoveryApiChainsListValue {
return json;
}
}
Loading

1 comment on commit 9ddc8c3

@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: 76%
78.26% (90/115) 66.66% (6/9) 69.13% (56/81)
common-aptos-utils Coverage: 4%
4.56% (151/3306) 4.49% (25/556) 5.53% (45/813)
common-evm-utils Coverage: 55%
55.94% (2168/3875) 16.91% (172/1017) 37.19% (482/1296)
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.