@btc-vision/transaction
Version:
OPNet transaction library allows you to create and sign transactions for the OPNet network.
129 lines (104 loc) • 3.54 kB
text/typescript
import { Address } from '../keypair/Address.js';
import { FastMap } from './FastMap.js';
/**
* A map implementation using Address with both MLDSA and tweaked keys.
* Uses the tweaked public key for lookup/indexing, but stores the full Address.
*/
export class ExtendedAddressMap<V> implements Disposable {
// Store tweaked bigint -> index mapping for fast lookup
private indexMap: FastMap<bigint, number>;
// Store actual addresses and values
private _keys: Address[] = [];
private _values: V[] = [];
constructor(iterable?: ReadonlyArray<readonly [Address, V]> | null) {
this.indexMap = new FastMap();
if (iterable) {
for (const [key, value] of iterable) {
this.set(key, value);
}
}
}
public get size(): number {
return this._keys.length;
}
public set(key: Address, value: V): this {
const keyBigInt = key.tweakedToBigInt();
const existingIndex = this.indexMap.get(keyBigInt);
if (existingIndex !== undefined) {
// Update existing entry
this._values[existingIndex] = value;
} else {
// Add new entry
const newIndex = this._keys.length;
this._keys.push(key);
this._values.push(value);
this.indexMap.set(keyBigInt, newIndex);
}
return this;
}
public get(key: Address): V | undefined {
const keyBigInt = key.tweakedToBigInt();
const index = this.indexMap.get(keyBigInt);
if (index === undefined) {
return undefined;
}
return this._values[index];
}
public has(key: Address): boolean {
return this.indexMap.has(key.tweakedToBigInt());
}
public delete(key: Address): boolean {
const keyBigInt = key.tweakedToBigInt();
const index = this.indexMap.get(keyBigInt);
if (index === undefined) {
return false;
}
// Remove from arrays
this._keys.splice(index, 1);
this._values.splice(index, 1);
// Rebuild index map (indices shifted after splice)
this.indexMap.clear();
for (let i = 0; i < this._keys.length; i++) {
this.indexMap.set((this._keys[i] as Address).tweakedToBigInt(), i);
}
return true;
}
public clear(): void {
this.indexMap.clear();
this._keys = [];
this._values = [];
}
public [Symbol.dispose](): void {
this.clear();
}
public indexOf(address: Address): number {
const index = this.indexMap.get(address.tweakedToBigInt());
return index !== undefined ? index : -1;
}
*entries(): IterableIterator<[Address, V]> {
for (let i = 0; i < this._keys.length; i++) {
yield [this._keys[i] as Address, this._values[i] as V];
}
}
*keys(): IterableIterator<Address> {
for (const key of this._keys) {
yield key;
}
}
*values(): IterableIterator<V> {
for (const value of this._values) {
yield value;
}
}
forEach(
callback: (value: V, key: Address, map: ExtendedAddressMap<V>) => void,
thisArg?: unknown,
): void {
for (let i = 0; i < this._keys.length; i++) {
callback.call(thisArg, this._values[i] as V, this._keys[i] as Address, this);
}
}
*[Symbol.iterator](): IterableIterator<[Address, V]> {
yield* this.entries();
}
}