@superfluid-finance/sdk-core
Version:
SDK Core for building with Superfluid Protocol
275 lines • 14.4 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.listAllResults = void 0;
const lodash_1 = __importDefault(require("lodash"));
const ajvValidations_generated_1 = require("./ajvValidations.generated");
const mapGetAllEventsQueryEvents_1 = require("./mapGetAllEventsQueryEvents");
const pagination_1 = require("./pagination");
const SubgraphClient_1 = require("./subgraph/SubgraphClient");
const getAccountTokenSnapshots_generated_1 = require("./subgraph/queries/getAccountTokenSnapshots.generated");
const getAllEvents_generated_1 = require("./subgraph/queries/getAllEvents.generated");
const getIndexSubscriptions_generated_1 = require("./subgraph/queries/getIndexSubscriptions.generated");
const getIndexes_generated_1 = require("./subgraph/queries/getIndexes.generated");
const getStreams_generated_1 = require("./subgraph/queries/getStreams.generated");
const getTokens_generated_1 = require("./subgraph/queries/getTokens.generated");
const utils_1 = require("./utils");
/**
* Query Helper Class
* @description A helper class to create `Query` objects which can be used to query different data.
*/
class Query {
constructor(options) {
this.listAllSuperTokens = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "createdAtBlockNumber",
orderDirection: "desc",
}) => {
(0, ajvValidations_generated_1.validateSuperTokenRequest)(filter);
const response = await this.subgraphClient.request(getTokens_generated_1.GetTokensDocument, {
where: {
isListed: filter.isListed,
isSuperToken: true,
id_gt: paging.lastId,
},
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
const mappedResult = response.result.map((x) => (0, utils_1.typeGuard)({
...x,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
}));
return (0, pagination_1.createPagedResult)(mappedResult, paging);
};
this.listIndexes = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "createdAtBlockNumber",
orderDirection: "desc",
}) => {
var _a, _b;
(0, ajvValidations_generated_1.validateIndexRequest)(filter);
const response = await this.subgraphClient.request(getIndexes_generated_1.GetIndexesDocument, {
where: {
indexId: filter.indexId,
publisher: (_a = filter.publisher) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
token: (_b = filter.token) === null || _b === void 0 ? void 0 : _b.toLowerCase(),
id_gt: paging.lastId,
},
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
const mappedResult = response.result.map((x) => (0, utils_1.typeGuard)({
...x,
publisher: x.publisher.id,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
token: {
...x.token,
createdAtTimestamp: Number(x.token.createdAtTimestamp),
createdAtBlockNumber: Number(x.token.createdAtBlockNumber),
},
}));
return (0, pagination_1.createPagedResult)(mappedResult, paging);
};
this.listIndexSubscriptions = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "createdAtBlockNumber",
orderDirection: "desc",
}) => {
var _a;
(0, ajvValidations_generated_1.validateIndexSubscriptionRequest)(filter);
const response = await this.subgraphClient.request(getIndexSubscriptions_generated_1.GetIndexSubscriptionsDocument, {
where: {
subscriber: (_a = filter.subscriber) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
approved: filter.approved,
id_gt: paging.lastId,
},
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
const mappedResult = response.result.map((x) => (0, utils_1.typeGuard)({
...x,
subscriber: x.subscriber.id,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
index: {
...x.index,
token: {
...x.index.token,
createdAtTimestamp: Number(x.index.token.createdAtTimestamp),
createdAtBlockNumber: Number(x.index.token.createdAtBlockNumber),
},
},
}));
return (0, pagination_1.createPagedResult)(mappedResult, paging);
};
this.listStreams = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "createdAtBlockNumber",
orderDirection: "desc",
}) => {
var _a, _b, _c;
(0, ajvValidations_generated_1.validateStreamRequest)(filter);
const response = await this.subgraphClient.request(getStreams_generated_1.GetStreamsDocument, {
where: {
sender: (_a = filter.sender) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
receiver: (_b = filter.receiver) === null || _b === void 0 ? void 0 : _b.toLowerCase(),
token: (_c = filter.token) === null || _c === void 0 ? void 0 : _c.toLowerCase(),
id_gt: paging.lastId,
},
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
const mappedResult = response.result.map((x) => (0, utils_1.typeGuard)({
...x,
sender: x.sender.id,
receiver: x.receiver.id,
createdAtTimestamp: Number(x.createdAtTimestamp),
createdAtBlockNumber: Number(x.createdAtBlockNumber),
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
token: {
...x.token,
createdAtTimestamp: Number(x.token.createdAtTimestamp),
createdAtBlockNumber: Number(x.token.createdAtBlockNumber),
},
flowUpdatedEvents: x.flowUpdatedEvents.map((y) => ({
...y,
blockNumber: Number(y.blockNumber),
timestamp: Number(y.timestamp),
})),
}));
return (0, pagination_1.createPagedResult)(mappedResult, paging);
};
this.listUserInteractedSuperTokens = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "updatedAtBlockNumber",
orderDirection: "desc",
}) => {
var _a, _b;
(0, ajvValidations_generated_1.validateAccountTokenSnapshotRequest)(filter);
const response = await this.subgraphClient.request(getAccountTokenSnapshots_generated_1.GetAccountTokenSnapshotsDocument, {
where: {
account: (_a = filter.account) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
token: (_b = filter.token) === null || _b === void 0 ? void 0 : _b.toLowerCase(),
id_gt: paging.lastId,
},
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
const mappedResult = response.result.map((x) => (0, utils_1.typeGuard)({
...x,
account: x.account.id,
updatedAtTimestamp: Number(x.updatedAtTimestamp),
updatedAtBlockNumber: Number(x.updatedAtBlockNumber),
token: {
...x.token,
createdAtTimestamp: Number(x.token.createdAtTimestamp),
createdAtBlockNumber: Number(x.token.createdAtBlockNumber),
},
}));
return (0, pagination_1.createPagedResult)(mappedResult, paging);
};
this.listEvents = async (filter, paging = (0, pagination_1.createSkipPaging)(), ordering = {
orderBy: "blockNumber",
orderDirection: "desc",
}) => {
var _a, _b;
(0, ajvValidations_generated_1.validateEventRequest)(filter);
const response = await this.subgraphClient.request(getAllEvents_generated_1.GetAllEventsDocument, {
orderBy: ordering === null || ordering === void 0 ? void 0 : ordering.orderBy,
orderDirection: ordering === null || ordering === void 0 ? void 0 : ordering.orderDirection,
where: {
addresses_contains: filter.account
? [(_a = filter.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()]
: undefined,
timestamp_gt: (_b = filter.timestamp_gt) === null || _b === void 0 ? void 0 : _b.toString(),
id_gt: paging.lastId,
},
first: (0, pagination_1.takePlusOne)(paging),
skip: paging.skip,
});
return (0, pagination_1.createPagedResult)((0, mapGetAllEventsQueryEvents_1.mapGetAllEventsQueryEvents)(response.events), paging);
};
this.options = options;
this.subgraphClient = new SubgraphClient_1.SubgraphClient(this.options.customSubgraphQueriesEndpoint);
}
// TODO(KK): error callback?
// TODO(KK): retries?
// TODO(KK): tests
on(callback, ms, account, timeout) {
if (ms < 1000)
throw Error("Let's not go crazy with the queries...");
// Account for the fact that Subgraph has lag and will insert events with the timestamp of the event from blockchain.
const clockSkew = 25000;
// Convert millisecond-based time to second-based time (which Subgraph uses).
let eventQueryTimestamp = Math.floor((new Date().getTime() - clockSkew) / 1000);
let isUnsubscribed = false;
const unsubscribe = () => {
isUnsubscribed = true;
};
const pollingStep = async () => {
if (isUnsubscribed) {
return;
}
const allEvents = await (0, exports.listAllResults)((paging) => this.listEvents({
account: account,
timestamp_gt: eventQueryTimestamp,
}, paging, {
orderBy: "timestamp",
orderDirection: "asc",
}));
// Filter next events by last timestamp of an event.
// NOTE: Make sure to order events by timestamp in ascending order.
const lastEvent = lodash_1.default.last(allEvents);
if (lastEvent) {
callback(allEvents, unsubscribe);
// Next event polling is done for events that have a timestamp later than the current latest event.
eventQueryTimestamp = lastEvent.timestamp;
}
// This solution sets the interval based on last query returning, opposed to not taking request-response cycles into account at all.
// This solution is more friendly to the Subgraph & more effective resource-wise with slow internet.
return setTimeout(() => {
// Fire and forget
pollingStep();
}, ms);
};
if (timeout) {
setTimeout(() => {
unsubscribe();
}, timeout);
}
// Fire and forget
pollingStep();
return unsubscribe;
}
}
exports.default = Query;
/**
* A recursive function to fetch all possible results of a paged query.
* @param pagedQuery A paginated query that takes {@link Paging} as input.
*/
const listAllResults = async (pagedQuery) => {
const listAllRecursively = async (paging) => {
const pagedResult = await pagedQuery(paging);
if (!pagedResult.nextPaging)
return pagedResult.data;
const nextResults = await listAllRecursively(pagedResult.nextPaging);
return pagedResult.data.concat(nextResults);
};
return listAllRecursively((0, pagination_1.createLastIdPaging)({ take: 999 }));
};
exports.listAllResults = listAllResults;
//# sourceMappingURL=Query.js.map
;