
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@generalprotocols/oracle-client
Advanced tools
The Oracle Client is an all-in-one library for interacting with General Protocol's Oracle Relay API. It provides developers with type-safe methods for fetching data over HTTP and realtime updates with Server-Sent Events (SSE). With built in Zod validation, it ensures the responses can be reliably handled and type-safe.
To simplify message handling and development, all messages that are returned from the API have their signatures validated and the message content is parsed into the appropriate type, and can be readily used without additional validation.
The Oracle Client is designed to make consuming Oracle Messages easier, but lacks some features found in the Price Oracle Library, such as:
npm install @generalprotocols/oracle-client
// Creating a client that listens for new messages
const client = await OracleClient.from('https://oracles.generalprotocols.com', {
// Called when any kind of message is received
onMessage: (message: OracleMessage) => {
console.log(`Received new Message: ${message.message}`);
},
// Called when a price message is received
onPriceMessage: (priceMessage: OraclePriceMessage) => {
console.log(`Received new Price Message: ${priceMessage.price}`);
},
// Called when a metadata message is received
onMetadataMessage: (metadataMessage: OracleMetadataMessage) => {
console.log(`Received new Metadata Message: ${metadataMessage.metadata}`);
},
});
import {
OracleClient,
type OracleMessage,
type OraclePriceMessage,
type OracleMetadataMessage,
} from 'oracle-client';
// Creating a client
const client = await OracleClient.from('https://oracles.generalprotocols.com');
// Fetching the oracles
const oracles = await client.getOracles();
console.log(oracles);
// Fetching messages for an oracle
const BCHUSD =
'02d09db08af1ff4e8453919cc866a4be427d7bfe18f2c05e5444c196fcf6fd2818';
// Fetching price messages for the BCH/USD oracle
const messages = await client.getOracleMessages({
publicKey: BCHUSD,
minDataSequence: 1,
});
console.log(messages);
/**
* Getting the current price of the BCH/USD oracle
*/
// Fetch the metadata and create a map of the available oracles so we can scale the price accordingly
const metadataMap = await client.getMetadataMap();
console.log(metadataMap);
// Grab the first message
const message = messages[0];
// Make sure the message is a price message
if (!(message instanceof OraclePriceMessage)) {
throw new Error('Message is not a price message');
}
// Make sure the metadata map contains the BCHUSD oracle
if (!metadataMap[BCHUSD]) {
throw new Error('Metadata map does not contain BCHUSD');
}
// Make sure the metadata map's ATTESTATION_SCALING value is not undefined
if (typeof metadataMap[BCHUSD].ATTESTATION_SCALING === 'undefined') {
throw new Error(`Metadata map's ATTESTATION_SCALING value is undefined`);
}
// Divide the priceValue by the metadata map's ATTESTATION_SCALING value
const oracleUnitsPerCommonUnit = metadataMap[BCHUSD].ATTESTATION_SCALING;
const price = message.priceValue / oracleUnitsPerCommonUnit;
console.log(price);
Messages are returned as either a OraclePriceMessage or a OracleMetadataMessage.
To parse a message to a single type, you can use either instanceof or the static isMetadataMessage or isPriceMessage methods.
const message: OraclePriceMessage | OracleMetadataMessage =
OracleMessage.from(signedMessage);
// Using instanceof
if (message instanceof OracleMetadataMessage) {
// Use as a metadata message
} else {
// Use as a price message
}
// Using static methods
const isMetadata = OracleMessage.isMetadataMessage(message);
if (isMetadata) {
// Use as a metadata message
} else {
// Use as a price message
}
// Create a client
const client = await OracleClient.from('https://oracles.generalprotocols.com');
// Get the metadata for the available oracles so we can scale the price accordingly
const metadataMap = await client.getMetadataMap();
// Create a callback that updates the metadataMap when a new metadata message is received
client.setOnMetadataMessage((metadataMessage) => {
// Update the metadata map using the Client's static method
OracleClient.updateMetadataMap(metadataMap, metadataMessage);
});
| Option | Description | Default |
|---|---|---|
sse | The SSE options | { method: 'GET', attemptReconnect: true, retryDelay: 1000, persistent: true } & { subscriptionUrl: ${baseURL}/sse/v1/messages } |
onMessage | Called when a message is received | (message: OracleMessage) => {} |
onPriceMessage | Called when a price message is received | (priceMessage: OraclePriceMessage) => {} |
onMetadataMessage | Called when a metadata message is received | (metadataMessage: OracleMetadataMessage) => {} |
| Option | Description | Default |
|---|---|---|
method | The HTTP method to use | GET |
headers | The HTTP headers to send with the request | {} |
body | The body to send with POST requests | null |
onMessage | Called when a Server-Sent Event is received | (event: SSEEvent) => {} |
onConnected | Called when the connection is established | () => {} |
onDisconnected | Called when the connection is closed | () => {} |
onError | Called when an error occurs | (error: unknown) => {} |
attemptReconnect | Whether to attempt to reconnect | true |
retryDelay | The delay in milliseconds between reconnection attempts | 1000 |
persistent | Whether to reconnect when the session is terminated by the server | true |
Get a list of the available oracles and their metrics.
Oracle's may return without any metrics. Metrics are only provided if the oracle has messages from the last 24 hours.
client.getOracles(options?: RequestOptions): Promise<GetOraclesResponse>;
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetOraclesResponse = {
oracles: {
publicKey: string;
messageMetrics?: {
maxMessageSequence: number;
minMessageTimestamp: number;
maxMessageTimestamp: number;
};
}[];
};
client.getPrices(params: GetPricesRequest, options?: RequestOptions): Promise<GetPricesResponse>;
| Option | Description | Type |
|---|---|---|
maxPriceSequence | (Optional) The maximum price sequence to fetch | number |
limit | (Default: 50) The maximum number of prices to fetch | number |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetPricesResponse = {
prices: {
priceSequence: number;
priceValue: number;
messageId?: number;
}[];
};
Get a list of messages for an oracle.
You can filter messages by timestamp, sequence, data sequence, and metadata type
client.getMessages(params: GetMessagesRequest, options?: RequestOptions): Promise<GetMessagesResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | The public key of the oracle to fetch messages for | string |
minMessageTimestamp | (Optional) The minimum message (Unix)timestamp to fetch | number |
maxMessageTimestamp | (Optional) The maximum message (Unix) timestamp to fetch | number |
minMessageSequence | (Optional) The minimum message sequence to fetch | number |
maxMessageSequence | (Optional) The maximum message sequence to fetch | number |
minDataSequence | (Optional) The minimum data sequence to fetch | number |
maxDataSequence | (Optional) The maximum data sequence to fetch | number |
minMetadataType | (Optional) The minimum metadata type to fetch | number |
maxMetadataType | (Optional) The maximum metadata type to fetch | number |
count | (Default: 50) The maximum number of messages to fetch | number |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetMessagesResponse = {
oracleMessages: {
message: string;
publicKey: string;
signature: string;
}[];
};
Get a list of metadata messages for an oracle.
You can filter messages by publicKey and sequence
client.getMetadataMessages(params: GetMetadataMessagesRequest, options?: RequestOptions): Promise<GetMetadataMessagesResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | (Optional) The public key of the oracle to fetch metadata messages for | string |
maxMessageSequence | (Optional) The maximum message sequence to fetch | number |
count | (Default: 50) The maximum number of metadata messages to fetch | number |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetMetadataMessagesResponse = {
oracleMetadata: {
publicKey: string;
message: string;
signature: string;
}[];
};
Get an string encoded SVG of the price graph for an oracle.
client.getPriceGraphImage(params: GetPriceGraphImageRequest, options?: RequestOptions): Promise<GetPriceGraphImageResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | The public key of the oracle to fetch the price graph image for | string |
minMessageTimestamp | (Optional) The minimum message (Unix) timestamp to fetch | number |
maxMessageTimestamp | (Optional) The maximum message (Unix) timestamp to fetch | number |
timePeriodGranularity | (Default: 'day') The time period granularity to fetch | 'minute', 'hour', 'day', 'week', 'month' |
chartWidth | (Optional) The width of the chart | number |
chartHeight | (Optional) The height of the chart | number |
strokeColor | (Optional) The color of the stroke | string |
strokeWidth | (Optional) The width of the stroke | number |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetPriceGraphImageResponse = string;
Get the price graph data for an oracle.
client.getPriceGraphData(params: GetPriceGraphDataRequest, options?: RequestOptions): Promise<GetPriceGraphDataResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | The public key of the oracle to fetch the price graph data for | string |
minMessageTimestamp | (Optional) The minimum message timestamp to fetch | number |
maxMessageTimestamp | (Optional)The maximum message timestamp to fetch | number |
timePeriodGranularity | (Default: 'day') The time period granularity to fetch | 'minute', 'hour', 'day', 'week', 'month' |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetPriceGraphDataResponse = {
priceGraphPoints: {
averagePrice: number;
timePeriod: string;
}[];
};
Get the price graph data for an oracle.
client.getAggregatedPriceGraphData(params: GetAggregatedPriceGraphDataRequest, options?: RequestOptions): Promise<GetAggregatedPriceGraphDataResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | The public key of the oracle to fetch the aggregated price graph data for | string |
minMessageTimestamp | The minimum message (Unix) timestamp to fetch | number |
maxMessageTimestamp | The maximum message (Unix) timestamp to fetch | number |
aggregationPeriod | The aggregation period (in seconds) to fetch | number |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetAggregatedPriceGraphDataResponse = {
priceGraphPoints: {
minimumTimestamp: number;
maximumTimestamp: number;
averageTimestamp: number;
minimumPrice: number;
maximumPrice: number;
averagePrice: number;
}[];
};
Get the recovery progress for an oracle.
client.getRecoveryProgress(params: GetRecoveryProgressRequest, options?: RequestOptions): Promise<GetRecoveryProgressResponse>;
| Option | Description | Type |
|---|---|---|
publicKey | The public key of the oracle to fetch the recovery progress for | string |
| Option | Description | Default |
|---|---|---|
validate | Whether to validate the response with Zod | true |
type GetRecoveryProgressResponse = {
recoveryProgress: {
messagesCount: number;
maxMessageSequence: number;
maxMessageTimestamp: number;
recoveryProgressPercent: string;
};
};
client.getMetadataMap(): Promise<OracleMetadataMap>;
type OracleMetadataMap = Partial<{
OPERATOR_NAME: string; // -1
OPERATOR_WEBSITE: string; // -2
RELAY_SERVER: string; // -3
STARTING_TIMESTAMP: number; // -4
ENDING_TIMESTAMP: number; // -5
ATTESTATION_SCALING: number; // -6
ATTESTATION_PERIOD: number; // -7
OPERATOR_HASH: string; // -8
SOURCE_NAME: string; // -51
SOURCE_WEBSITE: string; // -52
SOURCE_NUMERATOR_UNIT_NAME: string; // -53
SOURCE_NUMERATOR_UNIT_CODE: string; // -54
SOURCE_HASH: string; // -55
SOURCE_DENOMINATOR_UNIT_NAME: string; // -56
SOURCE_DENOMINATOR_UNIT_CODE: string; // -57
}>;
FAQs
Client to interact with GeneralProtocols Oracle HTTP API
We found that @generalprotocols/oracle-client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.