@langchain/community
Version:
Third-party integrations for LangChain.js
147 lines (146 loc) • 5.52 kB
JavaScript
import { Document } from "@langchain/core/documents";
import { BaseDocumentLoader } from "@langchain/core/document_loaders/base";
/**
* Class representing a document loader for loading data from the SortXYZ
* blockchain using the SortXYZ API.
* @example
* ```typescript
* const blockchainLoader = new SortXYZBlockchainLoader({
* apiKey: "YOUR_SORTXYZ_API_KEY",
* query: {
* type: "NFTMetadata",
* blockchain: "ethereum",
* contractAddress: "0x887F3909C14DAbd9e9510128cA6cBb448E932d7f".toLowerCase(),
* },
* });
*
* const blockchainData = await blockchainLoader.load();
*
* const prompt =
* "Describe the character with the attributes from the following json document in a 4 sentence story. ";
* const model = new ChatOpenAI({ temperature: 0.9 })
* const response = await model.invoke(
* prompt + JSON.stringify(blockchainData[0], null, 2),
* );
* console.log(`user > ${prompt}`);
* console.log(`chatgpt > ${response}`);
* ```
*/
export class SortXYZBlockchainLoader extends BaseDocumentLoader {
constructor({ apiKey, query }) {
super();
Object.defineProperty(this, "contractAddress", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "blockchain", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "apiKey", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "queryType", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "sql", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "limit", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
if (!apiKey) {
throw new Error(`apiKey is required! Head over to https://docs.sort.xyz/docs/api-keys to get your free Sort API key.`);
}
this.apiKey = apiKey;
if (typeof query === "string") {
this.sql = query;
}
else {
this.contractAddress = query.contractAddress.toLowerCase();
this.blockchain = query.blockchain;
this.queryType = query.type;
this.limit = query.limit ?? 100;
}
}
/**
* Method that loads the data from the SortXYZ blockchain based on the
* specified query parameters. It makes requests to the SortXYZ API and
* returns an array of Documents representing the retrieved data.
* @returns Promise<Document[]> - An array of Documents representing the retrieved data.
*/
async load() {
if (this.limit > 1000) {
throw new Error(`Limit is set too high. Please set limit to 1000 or lower.`);
}
const docs = [];
let queryOffset = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
let query = "";
if (this.sql) {
query = this.sql;
}
else if (this.queryType === "NFTMetadata") {
// All parameters here are user defined
query = `SELECT * FROM ${this.blockchain}.nft_metadata WHERE contract_address = '${this.contractAddress}' ORDER BY token_id DESC LIMIT ${this.limit} OFFSET ${queryOffset}`;
}
else if (this.queryType === "latestTransactions") {
// All parameters here are user defined
query = `SELECT * FROM ${this.blockchain}.transaction t, ethereum.block b WHERE t.to_address = '${this.contractAddress}' AND b.id=t.block_id ORDER BY b.timestamp DESC LIMIT ${this.limit} OFFSET ${queryOffset}`;
}
try {
const response = await fetch("https://api.sort.xyz/v1/queries/run", {
method: "POST",
headers: {
"x-api-key": this.apiKey,
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ query }),
});
const fullResponse = await response.json();
// Reached the end, no more records
if (fullResponse &&
fullResponse.data &&
fullResponse.data.records.length === 0) {
break;
}
const data = fullResponse?.data || [];
for (let i = 0; i < data.records.length; i += 1) {
const doc = new Document({
pageContent: JSON.stringify(data.records[i], null, 2),
metadata: {
row: i,
},
});
docs.push(doc);
}
queryOffset += this.limit;
if (queryOffset >= this.limit || this.sql) {
break;
}
}
catch (error) {
console.error("Error:", error);
}
}
return docs;
}
}