Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packages/api/src/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ import type {
AcquisitionDeal,
getOrganizationsParameters,
getProjectsParameters,
getInfluencersResponse,
getInfluencerResponse,
getInfluencerMindshareTimeSeriesParameters,
getInfluencerMindshareTimeSeriesResponse,
getInfluencerParameters,
getAssetMindshareTimeSeriesParameters,
getAssetResponse,
getAssetParameters,
getAssetsResponse,
getAssetMindshareTimeSeriesResponse,
} from "../types";
import { LogLevel, type Logger, makeConsoleLogger, createFilteredLogger, noOpLogger } from "../logging";
import type { PaginatedResult, RequestOptions, ClientEventMap, ClientEventType, ClientEventHandler } from "./types";
Expand Down Expand Up @@ -316,6 +326,19 @@ export interface TokenUnlocksInterface {
getEvents(params: getTokenUnlockEventsParameters, options?: RequestOptions): Promise<getTokenUnlockEventsResponse>;
}

/**
* Interface for the Signal API methods
*/
export interface SignalAPIInterface {
getInfluencers(): Promise<getInfluencersResponse>;
getInfluencer(params: getInfluencerParameters): Promise<getInfluencerResponse>;
getInfluencerMindshareTimeSeries(params: getInfluencerMindshareTimeSeriesParameters): Promise<getInfluencerMindshareTimeSeriesResponse>;

getAssets(): Promise<getAssetsResponse>;
getAsset(params: getAssetParameters): Promise<getAssetResponse>;
getAssetMindshareTimeSeries(params: getAssetMindshareTimeSeriesParameters): Promise<getAssetMindshareTimeSeriesResponse>;
}

/**
* Abstract base class for the Messari client
* Defines the structure and common functionality that all client implementations must provide
Expand Down Expand Up @@ -371,6 +394,11 @@ export abstract class MessariClientBase {
*/
// public abstract readonly recaps: RecapsAPIInterface;

/**
* Interface for Signal-related API methods
*/
public abstract readonly signal: SignalAPIInterface;

/**
* Logger instance for the client
*/
Expand Down
59 changes: 59 additions & 0 deletions packages/api/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ import {
getTokenUnlockVestingSchedule,
getOrganizations,
getProjects,
getInfluencers,
getInfluencer,
getInfluencerMindshareTimeSeries,
getAssets,
getAsset,
getAssetMindshareTimeSeries,
} from "../types";
import type {
createChatCompletionParameters,
Expand Down Expand Up @@ -93,6 +99,16 @@ import type {
getOrganizationsResponse,
getProjectsParameters,
getProjectsResponse,
getInfluencersResponse,
getInfluencerParameters,
getInfluencerResponse,
getInfluencerMindshareTimeSeriesResponse,
getInfluencerMindshareTimeSeriesParameters,
getAssetMindshareTimeSeriesResponse,
getAssetParameters,
getAssetMindshareTimeSeriesParameters,
getAssetsResponse,
getAssetResponse,
} from "../types";
import type { Agent } from "node:http";
import { pick } from "../utils";
Expand Down Expand Up @@ -120,6 +136,7 @@ import type {
RecapsAPIInterface,
ResearchInterface,
TokenUnlocksInterface,
SignalAPIInterface,
} from "./base";
import { MessariClientBase } from "./base";

Expand Down Expand Up @@ -897,6 +914,48 @@ export class MessariClient extends MessariClientBase {
},
};

public readonly signal: SignalAPIInterface = {
getInfluencers: async () => {
return this.request<getInfluencersResponse>({
method: getInfluencers.method,
path: getInfluencers.path(),
});
},
getInfluencer: async (params: getInfluencerParameters) => {
return this.request<getInfluencerResponse>({
method: getInfluencer.method,
path: getInfluencer.path(params),
});
},
getInfluencerMindshareTimeSeries: async (params: getInfluencerMindshareTimeSeriesParameters) => {
return this.request<getInfluencerMindshareTimeSeriesResponse>({
method: getInfluencerMindshareTimeSeries.method,
path: getInfluencerMindshareTimeSeries.path(params),
});
},
getAssets: async (options?: RequestOptions) => {
return this.request<getAssetsResponse>({
method: getAssets.method,
path: getAssets.path(),
options,
});
},
getAsset: async (params: getAssetParameters, options?: RequestOptions) => {
return this.request<getAssetResponse>({
method: getAsset.method,
path: getAsset.path(params),
options,
});
},
getAssetMindshareTimeSeries: async (params: getAssetMindshareTimeSeriesParameters, options?: RequestOptions) => {
return this.request<getAssetMindshareTimeSeriesResponse>({
method: getAssetMindshareTimeSeries.method,
path: getAssetMindshareTimeSeries.path(params),
options,
});
},
};

// Recaps is commented out as we don't want to expose it yet
// public readonly recaps: RecapsAPIInterface = {
// getProjectRecap: async (params: getProjectRecapParameters) => {
Expand Down
90 changes: 90 additions & 0 deletions packages/api/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,5 +496,95 @@ export const getTokenUnlockEvents = {
path: (p: PathParams) => `/token-unlocks/v1/assets/${p.assetId}/events`
} as const;


export type getInfluencersResponse = components['schemas']['Influencer'][];
export type getInfluencersError = components['schemas']['APIError'];

export type getInfluencersParameters = { page?: number; pageSize?: number };


export const getInfluencers = {
method: 'GET' as const,
pathParams: [] as const,
queryParams: ['page', 'pageSize'] as const,
bodyParams: [] as const,
path: () => '/signal/v0/influencers'
} as const;


export type getInfluencerResponse = components['schemas']['Influencer'];
export type getInfluencerError = components['schemas']['APIError'];

export type getInfluencerParameters = { influencerId: string };


export const getInfluencer = {
method: 'GET' as const,
pathParams: ['influencerId'] as const,
queryParams: [] as const,
bodyParams: [] as const,
path: (p: PathParams) => `/signal/v0/influencers/${p.influencerId}`
} as const;


export type getInfluencerMindshareTimeSeriesResponse = components['schemas']['TimeseriesData'];
export type getInfluencerMindshareTimeSeriesError = components['schemas']['APIError'];

export type getInfluencerMindshareTimeSeriesParameters = { start?: string; end?: string; granularity?: string } & { influencerId: string };


export const getInfluencerMindshareTimeSeries = {
method: 'GET' as const,
pathParams: ['influencerId'] as const,
queryParams: ['start', 'end', 'granularity'] as const,
bodyParams: [] as const,
path: (p: PathParams) => `/signal/v0/influencers/${p.influencerId}/time-series/mindshare/${p.granularity}`
} as const;


export type getAssetsResponse = components['schemas']['SignalAsset'][];
export type getAssetsError = components['schemas']['APIError'];

export type getAssetsParameters = { page?: number; pageSize?: number };


export const getAssets = {
method: 'GET' as const,
pathParams: [] as const,
queryParams: ['page', 'pageSize'] as const,
bodyParams: [] as const,
path: () => '/signal/v0/assets'
} as const;


export type getAssetResponse = components['schemas']['SignalAsset'];
export type getAssetError = components['schemas']['APIError'];

export type getAssetParameters = { assetId: string };


export const getAsset = {
method: 'GET' as const,
pathParams: ['assetId'] as const,
queryParams: [] as const,
bodyParams: [] as const,
path: (p: PathParams) => `/signal/v0/assets/${p.assetId}`
} as const;


export type getAssetMindshareTimeSeriesResponse = components['schemas']['TimeseriesData'];
export type getAssetMindshareTimeSeriesError = components['schemas']['APIError'];

export type getAssetMindshareTimeSeriesParameters = { start?: string; end?: string } & { assetId: string; granularity: string };


export const getAssetMindshareTimeSeries = {
method: 'GET' as const,
pathParams: ['assetId', 'granularity'] as const,
queryParams: ['start', 'end'] as const,
bodyParams: [] as const,
path: (p: PathParams) => `/signal/v0/assets/${p.assetId}/time-series/mindshare/${p.granularity}`
} as const;

// Re-export schema types
export * from './schema';
14 changes: 14 additions & 0 deletions packages/api/src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export type GetProjectRecapResponse = components['schemas']['GetProjectRecapResp

export type GroupedEntity = components['schemas']['GroupedEntity'];

export type Influencer = components['schemas']['Influencer'];

export type IntelResponse = components['schemas']['IntelResponse'];

export type Investors = components['schemas']['Investors'];
Expand All @@ -117,6 +119,10 @@ export type Person = components['schemas']['Person'];

export type PlatformContract = components['schemas']['PlatformContract'];

export type Point = components['schemas']['Point'];

export type PointSchema = components['schemas']['PointSchema'];

export type Project = components['schemas']['Project'];

export type ProjectRecapResponse = components['schemas']['ProjectRecapResponse'];
Expand All @@ -139,6 +145,10 @@ export type Resource = components['schemas']['Resource'];

export type SelectedEntity = components['schemas']['SelectedEntity'];

export type SignalAsset = components['schemas']['SignalAsset'];

export type SnapshotListingMetadata = components['schemas']['SnapshotListingMetadata'];

export type Source = components['schemas']['Source'];

export type SourceList = components['schemas']['SourceList'];
Expand All @@ -151,6 +161,10 @@ export type Tag = components['schemas']['Tag'];

export type TimeUTC = components['schemas']['TimeUTC'];

export type TimeseriesData = components['schemas']['TimeseriesData'];

export type TimeseriesMetadata = components['schemas']['TimeseriesMetadata'];

export type TokenUnlockAllocation = components['schemas']['TokenUnlockAllocation'];

export type TokenUnlockData = components['schemas']['TokenUnlockData'];
Expand Down
Loading