@drift-labs/sdk-browser
Version:
SDK for Drift Protocol
211 lines (210 loc) • 8.28 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RevenueShareEscrowMap = void 0;
const web3_js_1 = require("@solana/web3.js");
const pda_1 = require("../addresses/pda");
const memcmp_1 = require("../memcmp");
class RevenueShareEscrowMap {
/**
* Creates a new RevenueShareEscrowMap instance.
*
* @param {DriftClient} driftClient - The DriftClient instance.
* @param {boolean} parallelSync - Whether to sync accounts in parallel.
*/
constructor(driftClient, parallelSync) {
/**
* map from authority pubkey to RevenueShareEscrow account data.
*/
this.authorityEscrowMap = new Map();
this.driftClient = driftClient;
this.parallelSync = parallelSync !== undefined ? parallelSync : true;
}
/**
* Subscribe to all RevenueShareEscrow accounts.
*/
async subscribe() {
if (this.size() > 0) {
return;
}
await this.driftClient.subscribe();
await this.sync();
}
has(authorityPublicKey) {
return this.authorityEscrowMap.has(authorityPublicKey);
}
get(authorityPublicKey) {
return this.authorityEscrowMap.get(authorityPublicKey);
}
/**
* Enforce that a RevenueShareEscrow will exist for the given authorityPublicKey,
* reading one from the blockchain if necessary.
* @param authorityPublicKey
* @returns
*/
async mustGet(authorityPublicKey) {
if (!this.has(authorityPublicKey)) {
await this.addRevenueShareEscrow(authorityPublicKey);
}
return this.get(authorityPublicKey);
}
async addRevenueShareEscrow(authority) {
const escrowAccountPublicKey = (0, pda_1.getRevenueShareEscrowAccountPublicKey)(this.driftClient.program.programId, new web3_js_1.PublicKey(authority));
try {
const accountInfo = await this.driftClient.connection.getAccountInfo(escrowAccountPublicKey, 'processed');
if (accountInfo && accountInfo.data) {
const escrow = this.driftClient.program.account.revenueShareEscrow.coder.accounts.decode('RevenueShareEscrow', accountInfo.data);
this.authorityEscrowMap.set(authority, escrow);
}
}
catch (error) {
// RevenueShareEscrow account doesn't exist for this authority, which is normal
console.debug(`No RevenueShareEscrow account found for authority: ${authority}`);
}
}
size() {
return this.authorityEscrowMap.size;
}
async sync() {
if (this.fetchPromise) {
return this.fetchPromise;
}
this.fetchPromise = new Promise((resolver) => {
this.fetchPromiseResolver = resolver;
});
try {
await this.syncAll();
}
finally {
this.fetchPromiseResolver();
this.fetchPromise = undefined;
}
}
/**
* A slow, bankrun test friendly version of sync(), uses getAccountInfo on every cached account to refresh data
* @returns
*/
async slowSync() {
if (this.fetchPromise) {
return this.fetchPromise;
}
for (const authority of this.authorityEscrowMap.keys()) {
const accountInfo = await this.driftClient.connection.getAccountInfo((0, pda_1.getRevenueShareEscrowAccountPublicKey)(this.driftClient.program.programId, new web3_js_1.PublicKey(authority)), 'confirmed');
const escrowNew = this.driftClient.program.account.revenueShareEscrow.coder.accounts.decode('RevenueShareEscrow', accountInfo.data);
this.authorityEscrowMap.set(authority, escrowNew);
}
}
async syncAll() {
const rpcRequestArgs = [
this.driftClient.program.programId.toBase58(),
{
commitment: this.driftClient.opts.commitment,
filters: [(0, memcmp_1.getRevenueShareEscrowFilter)()],
encoding: 'base64',
withContext: true,
},
];
const rpcJSONResponse =
// @ts-ignore
await this.driftClient.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
const rpcResponseAndContext = rpcJSONResponse.result;
const batchSize = 100;
for (let i = 0; i < rpcResponseAndContext.value.length; i += batchSize) {
const batch = rpcResponseAndContext.value.slice(i, i + batchSize);
if (this.parallelSync) {
await Promise.all(batch.map(async (programAccount) => {
try {
// @ts-ignore
const buffer = Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
const escrow = this.driftClient.program.account.revenueShareEscrow.coder.accounts.decode('RevenueShareEscrow', buffer);
// Extract authority from the account data
const authorityKey = escrow.authority.toBase58();
this.authorityEscrowMap.set(authorityKey, escrow);
}
catch (error) {
console.warn(`Failed to decode RevenueShareEscrow account ${programAccount.pubkey}:`, error);
}
}));
}
else {
for (const programAccount of batch) {
try {
// @ts-ignore
const buffer = Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
const escrow = this.driftClient.program.account.revenueShareEscrow.coder.accounts.decode('RevenueShareEscrow', buffer);
// Extract authority from the account data
const authorityKey = escrow.authority.toBase58();
this.authorityEscrowMap.set(authorityKey, escrow);
}
catch (error) {
console.warn(`Failed to decode RevenueShareEscrow account ${programAccount.pubkey}:`, error);
}
}
}
// Add a small delay between batches to avoid overwhelming the RPC
await new Promise((resolve) => setTimeout(resolve, 10));
}
}
/**
* Get all RevenueShareEscrow accounts
*/
getAll() {
return new Map(this.authorityEscrowMap);
}
/**
* Get all authorities that have RevenueShareEscrow accounts
*/
getAuthorities() {
return Array.from(this.authorityEscrowMap.keys());
}
/**
* Get RevenueShareEscrow accounts that have approved referrers
*/
getEscrowsWithApprovedReferrers() {
const result = new Map();
for (const [authority, escrow] of this.authorityEscrowMap) {
if (escrow.approvedBuilders && escrow.approvedBuilders.length > 0) {
result.set(authority, escrow);
}
}
return result;
}
/**
* Get RevenueShareEscrow accounts that have active orders
*/
getEscrowsWithOrders() {
const result = new Map();
for (const [authority, escrow] of this.authorityEscrowMap) {
if (escrow.orders && escrow.orders.length > 0) {
result.set(authority, escrow);
}
}
return result;
}
/**
* Get RevenueShareEscrow account by referrer
*/
getByReferrer(referrerPublicKey) {
for (const escrow of this.authorityEscrowMap.values()) {
if (escrow.referrer.toBase58() === referrerPublicKey) {
return escrow;
}
}
return undefined;
}
/**
* Get all RevenueShareEscrow accounts for a specific referrer
*/
getAllByReferrer(referrerPublicKey) {
const result = [];
for (const escrow of this.authorityEscrowMap.values()) {
if (escrow.referrer.toBase58() === referrerPublicKey) {
result.push(escrow);
}
}
return result;
}
async unsubscribe() {
this.authorityEscrowMap.clear();
}
}
exports.RevenueShareEscrowMap = RevenueShareEscrowMap;