Crypto ICO Token Vesting Schedule Calculator
Vesting Parameters
Check Vesting Status at Specific Date
Vesting Schedule Summary & Projection
Detailed Vesting Schedule
| Unlock Date | Tokens Unlocked | Cumulative Tokens | % Total Vested |
|---|
This calculator provides an illustrative vesting schedule based on your inputs. "Linear Daily" vesting is approximated and shown with monthly snapshots. Ensure total vesting period includes any cliff duration. This tool does not provide financial or legal advice.
Full Vesting End Date: ${this.summaryData.fullVestingEndDate}
`; pdfHtml += `Total Tokens in Schedule: ${Number(this.summaryData.totalTokens).toLocaleString()}
`; if (this.summaryData.checkDate) { pdfHtml += ``; pdfHtml += `
Tokens Vested by ${this.summaryData.checkDate}: ${Number(this.summaryData.vestedAtCheckDate).toLocaleString(undefined, {maximumFractionDigits:2})} (${this.summaryData.percentAtCheckDate.toFixed(2)}%)
`; } pdfHtml += `Detailed Vesting Schedule
`; const tableClone = this.elements.scheduleTableBody.parentNode.cloneNode(true); tableClone.style.fontSize = '8pt'; tableClone.querySelectorAll('th, td').forEach(cell => cell.style.padding = '4px'); pdfHtml += tableClone.outerHTML; pdfHtml += `This schedule is illustrative, based on the provided inputs. "Linear Daily" vesting is approximated for table display.
`;
pdfExportContainer.innerHTML = pdfHtml;
document.body.appendChild(pdfExportContainer);
try {
const canvas = await html2canvas(pdfExportContainer, { scale: 1.5, useCORS: true, logging: false, windowWidth: pdfExportContainer.scrollWidth });
document.body.removeChild(pdfExportContainer);
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgProps = pdf.getImageProperties(imgData);
let imgFinalWidth = pdfWidth - 40;
let imgFinalHeight = (imgProps.height * imgFinalWidth) / imgProps.width;
if (imgFinalHeight > pdfHeight - 40) {
imgFinalHeight = pdfHeight - 40;
imgFinalWidth = (imgProps.width * imgFinalHeight) / imgProps.height;
}
let currentY = 20;
let heightProcessed = 0;
const pageMargin = 20;
const pageHeightAvailable = pdfHeight - 2 * pageMargin;
while(heightProcessed < canvas.height) {
let pageSegmentHeightOnCanvas = Math.min(canvas.height - heightProcessed, (pageHeightAvailable / imgFinalHeight) * canvas.height );
const segmentCanvas = document.createElement('canvas');
segmentCanvas.width = canvas.width;
segmentCanvas.height = pageSegmentHeightOnCanvas;
const sctx = segmentCanvas.getContext('2d');
sctx.drawImage(canvas, 0, heightProcessed, canvas.width, pageSegmentHeightOnCanvas, 0, 0, canvas.width, pageSegmentHeightOnCanvas);
const segmentImgData = segmentCanvas.toDataURL('image/png');
const segmentImgProps = pdf.getImageProperties(segmentImgData);
let segmentRenderWidth = pdfWidth - 2 * pageMargin;
let segmentRenderHeight = (segmentImgProps.height * segmentRenderWidth) / segmentImgProps.width;
if(segmentRenderHeight > pageHeightAvailable) {
segmentRenderHeight = pageHeightAvailable;
segmentRenderWidth = (segmentImgProps.width * segmentRenderHeight) / segmentImgProps.height;
}
if(heightProcessed > 0) pdf.addPage();
pdf.addImage(segmentImgData, 'PNG', pageMargin, pageMargin, segmentRenderWidth, segmentRenderHeight);
heightProcessed += pageSegmentHeightOnCanvas;
}
pdf.save('Token_Vesting_Schedule.pdf');
} catch (error) {
console.error("Error generating PDF:", error);
alert("An error occurred while generating PDF.");
if (document.body.contains(pdfExportContainer)) document.body.removeChild(pdfExportContainer);
}
}
};
document.addEventListener('DOMContentLoaded', function() {
tvcApp.init();
});
