UNPKG

lotus-sdk

Version:

Central repository for several classes of tools for integrating with, and building for, the Lotusia ecosystem

95 lines (94 loc) 3.57 kB
import { Output } from '../../bitcore/transaction/output.js'; import { Script } from '../../bitcore/script.js'; import { Opcode } from '../../bitcore/opcode.js'; import { DEFAULT_BURN_CONFIG } from './types.js'; export class SwapSigBurnMechanism { config; constructor(config) { this.config = { ...DEFAULT_BURN_CONFIG, ...config }; } calculateBurnAmount(swapAmount, burnPercentage) { const percentage = burnPercentage ?? this.config.burnPercentage; const rawBurn = Math.floor(swapAmount * percentage); return Math.max(this.config.minimumBurn, Math.min(rawBurn, this.config.maximumBurn)); } createBurnOutput(burnAmount, poolId, config) { const burnConfig = config ?? this.config; const burnId = Buffer.from(burnConfig.burnIdentifier, 'utf8'); const poolIdBuf = Buffer.from(poolId, 'hex'); const versionBuf = Buffer.from([burnConfig.version]); const script = new Script().add(Opcode.OP_RETURN).add(burnId); if (burnConfig.poolIdInBurn) { script.add(poolIdBuf); } script.add(versionBuf); return new Output({ satoshis: burnAmount, script, }); } validateBurn(tx, expectedAmount, expectedPoolId, config) { const burnConfig = config ?? this.config; const burnOutput = tx.outputs.find(output => { const script = output.script; if (!script || script.chunks.length === 0) return false; return script.chunks[0].opcodenum === Opcode.OP_RETURN; }); if (!burnOutput) { return false; } if (burnOutput.satoshis !== expectedAmount) { return false; } const script = burnOutput.script; const chunks = script.chunks; const minChunks = burnConfig.poolIdInBurn ? 4 : 3; if (chunks.length < minChunks) { return false; } if (chunks[0].opcodenum !== Opcode.OP_RETURN) { return false; } const burnId = chunks[1].buf; if (!burnId || burnId.toString('utf8') !== burnConfig.burnIdentifier) { return false; } let chunkIndex = 2; if (burnConfig.poolIdInBurn) { const poolIdBuf = chunks[chunkIndex].buf; if (!poolIdBuf || poolIdBuf.toString('hex') !== expectedPoolId) { return false; } chunkIndex++; } const versionBuf = chunks[chunkIndex].buf; if (!versionBuf || versionBuf[0] !== burnConfig.version) { return false; } return true; } calculateTotalBurned(participantCount, denomination) { const burnPerParticipant = this.calculateBurnAmount(denomination); return participantCount * burnPerParticipant; } calculateSybilAttackCost(fakeParticipants, denomination, feePerTx) { const burnPerParticipant = this.calculateBurnAmount(denomination); const lockedFunds = fakeParticipants * denomination; const burnedFunds = fakeParticipants * burnPerParticipant; const feesFunds = fakeParticipants * 2 * feePerTx; return { lockedFunds, burnedFunds, feesFunds, totalIrrecoverable: burnedFunds + feesFunds, totalCost: lockedFunds + burnedFunds + feesFunds, }; } getConfig() { return { ...this.config }; } updateConfig(config) { this.config = { ...this.config, ...config }; } }