@btc-vision/transaction
Version:
OPNet transaction library allows you to create and sign transactions for the OPNet network.
70 lines (69 loc) • 2.79 kB
JavaScript
import { networks, toXOnly } from '@btc-vision/bitcoin';
import { BinaryWriter } from '../buffer/BinaryWriter.js';
import { Features } from './Features.js';
import { Address } from '../keypair/Address.js';
import { Compressor } from '../bytecode/Compressor.js';
export class Generator {
constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
this.network = networks.bitcoin;
this.senderPubKey = senderPubKey;
this.contractSaltPubKey = contractSaltPubKey;
this.network = network;
this.xSenderPubKey = toXOnly(senderPubKey);
}
buildHeader(features) {
let flags = 0;
for (const feature of features) {
flags |= feature;
}
const bytesU24 = Buffer.alloc(3);
bytesU24.writeUIntBE(flags, 0, 3);
return Buffer.from([this.senderPubKey[0], ...bytesU24]);
}
getHeader(maxPriority, features = []) {
const writer = new BinaryWriter(12);
writer.writeBytes(this.buildHeader(features));
writer.writeU64(maxPriority);
return Buffer.from(writer.getBuffer());
}
splitBufferIntoChunks(buffer, chunkSize = Generator.DATA_CHUNK_SIZE) {
const chunks = [];
for (let i = 0; i < buffer.length; i += chunkSize) {
const dataLength = Math.min(chunkSize, buffer.length - i);
const buf2 = Buffer.alloc(dataLength);
for (let j = 0; j < dataLength; j++) {
buf2.writeUInt8(buffer[i + j], j);
}
chunks.push([buf2]);
}
return chunks;
}
encodeFeature(feature) {
switch (feature.opcode) {
case Features.ACCESS_LIST:
return this.splitBufferIntoChunks(this.encodeAccessListFeature(feature));
default:
throw new Error(`Unknown feature type: ${feature.opcode}`);
}
}
encodeAccessListFeature(feature) {
const writer = new BinaryWriter();
writer.writeU16(Object.keys(feature.data).length);
for (const contract in feature.data) {
const parsedContract = Address.fromString(contract);
const data = feature.data[contract];
writer.writeAddress(parsedContract);
writer.writeU32(data.length);
for (const pointer of data) {
const pointerBuffer = Buffer.from(pointer, 'base64');
if (pointerBuffer.length !== 32) {
throw new Error(`Invalid pointer length: ${pointerBuffer.length}`);
}
writer.writeBytes(pointerBuffer);
}
}
return Compressor.compress(Buffer.from(writer.getBuffer()));
}
}
Generator.DATA_CHUNK_SIZE = 512;
Generator.MAGIC = Buffer.from('op', 'utf-8');