Fork of atp.tools as a universal profile for people on the ATmosphere
at main 82 lines 2.3 kB view raw
1/** 2 * TID (Transaction ID) implementation for ATProto 3 * Based on the original Go implementation from github.com/bluesky-social/indigo 4 */ 5 6// Base32 alphabet used for sorting 7const BASE32_SORT_ALPHABET = "234567abcdefghijklmnopqrstuvwxyz"; 8 9// Constants for bit operations 10const CLOCK_ID_MASK = 0x3ff; 11const MICROS_MASK = 0x1f_ffff_ffff_ffffn; 12const INTEGER_MASK = 0x7fff_ffff_ffff_ffffn; 13 14class TransactionId { 15 private readonly value: string; 16 17 constructor(value: string) { 18 this.value = value; 19 } 20 21 toString(): string { 22 return this.value; 23 } 24 25 static create(unixMicros: bigint, clockId: number): TransactionId { 26 const clockIdBig = BigInt(clockId & CLOCK_ID_MASK); 27 const v = ((unixMicros & MICROS_MASK) << 10n) | clockIdBig; 28 return TransactionId.fromInteger(v); 29 } 30 31 static createNow(clockId: number): TransactionId { 32 const nowMicros = BigInt(Date.now()) * 1000n; // Convert ms to μs 33 return TransactionId.create(nowMicros, clockId); 34 } 35 36 private static fromInteger(value: bigint): TransactionId { 37 value = INTEGER_MASK & value; 38 let result = ""; 39 40 for (let i = 0; i < 13; i++) { 41 result = BASE32_SORT_ALPHABET[Number(value & 0x1fn)] + result; 42 value = value >> 5n; 43 } 44 45 return new TransactionId(result); 46 } 47} 48 49/** 50 * Extracts timestamp from a TID string 51 * @param tid - The TID string to parse 52 * @returns Date object representing the timestamp 53 */ 54export function tidToTime(tid: string): Date { 55 // Convert TID string to integer 56 let value = 0n; 57 for (let i = 0; i < Math.min(tid.length, 13); i++) { 58 const char = tid[i]; 59 const charValue = BASE32_SORT_ALPHABET.indexOf(char); 60 if (charValue === -1) { 61 throw new Error(`Invalid base32 character: ${char}`); 62 } 63 value = (value << 5n) | BigInt(charValue); 64 } 65 66 // Extract timestamp (shift right 10 bits to remove clock ID, mask to get microseconds) 67 const micros = (value >> 10n) & 0x1fff_ffff_ffff_ffffn; 68 69 // Convert microseconds to milliseconds for JavaScript Date 70 const millis = Number(micros / 1000n); 71 72 return new Date(millis); 73} 74 75/** 76 * Generates a new Transaction ID with a random clock ID 77 * @returns TransactionId 78 */ 79export function generateTid(): TransactionId { 80 const clockId = Math.floor(Math.random() * 64 + 512); 81 return TransactionId.createNow(clockId); 82}