@kamino-finance/klend-sdk
Version:
Typescript SDK for interacting with the Kamino Lending (klend) protocol
227 lines • 7.12 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HashablePublicKey = exports.PubkeyHashMap = exports.PublicKeyMap = exports.PublicKeySet = exports.COMPUTE_BUDGET_PROGRAM_ID = exports.NULL_PUBKEY = void 0;
exports.isNotNullPubkey = isNotNullPubkey;
const web3_js_1 = require("@solana/web3.js");
const bn_js_1 = __importDefault(require("bn.js"));
exports.NULL_PUBKEY = new web3_js_1.PublicKey('nu11111111111111111111111111111111111111111');
exports.COMPUTE_BUDGET_PROGRAM_ID = new web3_js_1.PublicKey('ComputeBudget111111111111111111111111111111');
/**
* Helper function to check if a configured pubkey is null or default.
* @param pubkey
* @returns {boolean}
*/
function isNotNullPubkey(pubkey) {
return pubkey && !pubkey.equals(exports.NULL_PUBKEY) && !pubkey.equals(web3_js_1.PublicKey.default);
}
/**
* Custom set implementation for PublicKey
* Calling toString() on a PublicKey is pretty slow and pubkeys do not support `SameValueZero` comparison, so we use a custom set implementation where keys are compared with `PublicKey.equals(PublicKey)`
*/
class PublicKeySet {
items = [];
constructor(items) {
items.forEach((item) => this.add(item));
}
add(item) {
if (!this.contains(item)) {
this.items.push(item);
}
}
contains(item) {
return this.items.some((existingItem) => this.equals(existingItem, item));
}
equals(item1, item2) {
return item1.equals(item2);
}
isEmpty() {
return this.items.length === 0;
}
toArray() {
return this.items.slice(); // Return a copy of the array to prevent external modifications
}
}
exports.PublicKeySet = PublicKeySet;
/**
* Custom map implementation for PublicKey, backed by a list for o(n) lookup speed
* Calling toString() on a PublicKey is pretty slow and pubkeys do not support `SameValueZero` comparison, so we use a custom map implementation where keys are compared with `PublicKey.equals(PublicKey)`
*/
class PublicKeyMap {
record = [];
set(key, value) {
const index = this.findIndex(key);
if (index !== -1) {
// Update existing entry
this.record[index].value = value;
}
else {
// Add new entry
this.record.push({ key, value });
}
}
get(key) {
const index = this.findIndex(key);
return index !== -1 ? this.record[index].value : undefined;
}
has(key) {
return this.findIndex(key) !== -1;
}
delete(key) {
const index = this.findIndex(key);
if (index !== -1) {
this.record.splice(index, 1);
}
}
findIndex(key) {
return this.record.findIndex((entry) => entry.key.equals(key));
}
clear() {
this.record = [];
}
forEach(callback) {
this.record.forEach((entry) => {
callback(entry.value, entry.key);
});
}
keys() {
return this.record.map((entry) => entry.key);
}
values() {
return this.record.map((entry) => entry.value);
}
entries() {
return this.record.map((entry) => [entry.key, entry.value]);
}
isEmpty() {
return this.record.length === 0;
}
}
exports.PublicKeyMap = PublicKeyMap;
/**
* Custom map implementation for PublicKey, backed by a hashmap for o(1) lookup speed
* Calling toString() on a PublicKey is pretty slow and pubkeys do not support `SameValueZero` comparison, so we use a custom map implementation where keys are compared with `PublicKey.equals(PublicKey)`, and a hash is derived from the final 32 bits of the public key
*/
class PubkeyHashMap {
buckets;
size;
constructor(entries) {
this.buckets = new Map();
this.size = 0;
if (entries) {
for (const [key, value] of entries) {
this.set(key, value);
}
}
}
*[Symbol.iterator]() {
for (const [, bucket] of this.buckets) {
for (const { key, value } of bucket) {
yield [key, value];
}
}
}
[Symbol.toStringTag] = 'PubkeyHashMap';
set(key, value) {
const hash = new HashablePublicKey(key).hashCode();
const bucket = this.buckets.get(hash);
if (!bucket) {
this.buckets.set(hash, [{ key, value }]);
this.size++;
}
else {
const entry = bucket.find((entry) => entry.key.equals(key));
if (entry) {
entry.value = value;
}
else {
bucket.push({ key, value });
this.size++;
}
}
return this;
}
get(key) {
const hash = new HashablePublicKey(key).hashCode();
const bucket = this.buckets.get(hash);
if (!bucket) {
return undefined;
}
const entry = bucket.find((entry) => entry.key.equals(key));
return entry ? entry.value : undefined;
}
has(key) {
const hash = new HashablePublicKey(key).hashCode();
const bucket = this.buckets.get(hash);
if (!bucket) {
return false;
}
const entry = bucket.find((entry) => entry.key.equals(key));
return !!entry;
}
delete(key) {
const hash = new HashablePublicKey(key).hashCode();
const bucket = this.buckets.get(hash);
if (!bucket) {
return false;
}
const index = bucket.findIndex((entry) => entry.key.equals(key));
if (index === -1) {
return false;
}
bucket.splice(index, 1);
if (bucket.length === 0) {
this.buckets.delete(hash);
}
this.size--;
return true;
}
clear() {
this.buckets = new Map();
this.size = 0;
}
isEmpty() {
return this.size === 0;
}
forEach(callbackfn, thisArg) {
this.buckets.forEach((bucket) => {
bucket.forEach((entry) => {
callbackfn(entry.value, entry.key, this);
}, thisArg);
}, thisArg);
}
*keys() {
for (const [key] of this) {
yield key;
}
}
*values() {
for (const [, value] of this) {
yield value;
}
}
entries() {
return this[Symbol.iterator]();
}
}
exports.PubkeyHashMap = PubkeyHashMap;
class HashablePublicKey extends web3_js_1.PublicKey {
// We only use the last 32 bits of the public key for hashing
static MASK = new bn_js_1.default(1).shln(32).subn(1);
constructor(value) {
super(value);
}
hashCode() {
let hash = 13;
hash = hash * 7 + this.getBN().clone().iuand(HashablePublicKey.MASK).toNumber();
return hash;
}
getBN() {
//@ts-ignore
return this._bn;
}
}
exports.HashablePublicKey = HashablePublicKey;
//# sourceMappingURL=pubkey.js.map