Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
36 changes: 18 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions lazer/sdk/js/examples/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* eslint-disable no-console */

import { displayParsedPrices } from "./util.js";
import { PythLazerClient } from "../src/index.js";

const client = await PythLazerClient.create({
token: "your-token-here",
logger: console,
});

// Example 1: Get latest price for BTC using feed IDs
console.log("\n=== Example 1: Latest BTC price (requested with feed ID) ===");
const response1 = await client.get_latest_price({
priceFeedIds: [1],
properties: ["price", "confidence", "exponent"],
formats: [],
jsonBinaryEncoding: "hex",
parsed: true,
channel: "fixed_rate@200ms",
});
displayParsedPrices(response1);

// Example 2: Get latest price using symbols
console.log("\n=== Example 2: Latest ETH price (requested with symbols) ===");
const response2 = await client.get_latest_price({
priceFeedIds: [2],
properties: ["price", "confidence", "exponent"],
formats: [],
parsed: true,
channel: "real_time",
});
displayParsedPrices(response2);

// Example 3: Get historical price at specific timestamp
console.log("\n=== Example 3: Historical BTC price at timestamp ===");
const timestamp = 1_754_348_458_565_000;
console.log(
`Requesting price from timestamp: ${timestamp.toString()} (${new Date(timestamp / 1000).toISOString()})`,
);
const response3 = await client.get_price({
timestamp: timestamp,
priceFeedIds: [1],
properties: ["price", "confidence", "exponent"],
formats: [],
parsed: true,
channel: "real_time",
});
displayParsedPrices(response3);
89 changes: 0 additions & 89 deletions lazer/sdk/js/examples/index.ts

This file was deleted.

115 changes: 115 additions & 0 deletions lazer/sdk/js/examples/streaming.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-empty-function */

import { renderFeeds, refreshFeedDisplay } from "./util.js";
import type { JsonUpdate } from "../src/index.js";
import { PythLazerClient } from "../src/index.js";

// Ignore debug messages
console.debug = () => {};
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be doing this at a file level? I feel like we should respect the log level that is passed into the execution call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah there is no console.setLevel unfortunately, this is a common workaround to set "log level" when using console directly as a logger. Functionally its the same as passing in a ts-log instance or something, but again its just an example so didn't want to prescribe things like which logger to pass in.


// Store feed data for in-place updates
const feedData = new Map<
string,
{
priceFeedId: string | number;
price: number;
confidence: number | undefined;
exponent: number;
lastUpdate: Date;
}
>();

const client = await PythLazerClient.create({
token: "your-token-here", // Replace with your actual access token
logger: console, // Optionally log operations (to the console in this case.)
webSocketPoolConfig: {
numConnections: 4, // Optionally specify number of parallel redundant connections to reduce the chance of dropped messages. The connections will round-robin across the provided URLs. Default is 4.
onError: (error) => {
console.error("WebSocket error:", error);
},
// Optional configuration for resilient WebSocket connections
rwsConfig: {
heartbeatTimeoutDurationMs: 5000, // Optional heartbeat timeout duration in milliseconds
maxRetryDelayMs: 1000, // Optional maximum retry delay in milliseconds
logAfterRetryCount: 10, // Optional log after how many retries
},
},
});

// Read and display messages from the Lazer stream
client.addMessageListener((message) => {
switch (message.type) {
case "json": {
if (message.value.type == "streamUpdated") {
refreshFeedDisplay(message.value as JsonUpdate, feedData);
}
break;
}
case "binary": {
// Print out the binary hex messages if you want:
// if ("solana" in message.value) {
// console.info("solana message:", message.value.solana?.toString("hex"));
// }
// if ("evm" in message.value) {
// console.info("evm message:", message.value.evm?.toString("hex"));
// }
Comment on lines +59 to +65
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Left it in as a hint for people who want to use the binary message

break;
}
}
});

// Monitor for all connections in the pool being down simultaneously (e.g. if the internet goes down)
// The connections may still try to reconnect in the background. To shut down the client completely, call shutdown().
client.addAllConnectionsDownListener(() => {
console.error("All connections are down!");
});

renderFeeds(feedData);

// Create and remove one or more subscriptions on the fly
client.subscribe({
type: "subscribe",
subscriptionId: 1,
priceFeedIds: [1, 2],
properties: ["price"],
formats: ["solana"],
deliveryFormat: "binary",
channel: "fixed_rate@200ms",
parsed: false,
jsonBinaryEncoding: "base64",
});
client.subscribe({
type: "subscribe",
subscriptionId: 2,
priceFeedIds: [1, 2, 3, 4, 5],
properties: ["price", "exponent", "publisherCount", "confidence"],
formats: ["evm"],
deliveryFormat: "json",
channel: "fixed_rate@200ms",
parsed: true,
jsonBinaryEncoding: "hex",
});
client.subscribe({
type: "subscribe",
subscriptionId: 3,
priceFeedIds: [1],
properties: ["price", "confidence"],
formats: ["solana"],
deliveryFormat: "json",
channel: "fixed_rate@200ms",
parsed: true,
jsonBinaryEncoding: "hex",
});

await new Promise((resolve) => setTimeout(resolve, 30_000));

client.unsubscribe(1);
client.unsubscribe(2);
client.unsubscribe(3);

process.stdout.write("\u001B[2J\u001B[H");
console.log("🛑 Shutting down Pyth Lazer demo after 30 seconds...");
console.log("👋 Goodbye!");

client.shutdown();
29 changes: 29 additions & 0 deletions lazer/sdk/js/examples/symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* eslint-disable no-console */

import { PythLazerClient } from "../src/index.js";

const client = await PythLazerClient.create({
token: "your-token-here",
logger: console,
});

// Example 1: Get latest price for BTC using feed IDs
console.log("\n=== Example 1: Search feeds by name/symbol ===");
const response1 = await client.get_symbols({ query: "BTC" });
console.log(response1);

// Example 2: Get latest price using symbols
console.log("\n=== Example 2: Get feeds by asset type ===");
const response2 = await client.get_symbols({
asset_type: "equity",
});
console.log(response2);

// Example 3: Get feeds by asset type and query
console.log("\n=== Example 3: Get feeds by asset type and name/symbol ===");
const response3 = await client.get_symbols({
asset_type: "equity",
query: "AAPL",
});

console.log(response3);
Loading
Loading