Created
April 8, 2025 14:33
-
-
Save heyitsarpit/5411925fb10bb410edcf23ceb73c4d70 to your computer and use it in GitHub Desktop.
Address utility with cross conversion fns
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bs58 from 'bs58'; | |
export class Address { | |
private buffer: Buffer; | |
private constructor(buffer: Buffer) { | |
if (buffer.length !== 32) { | |
throw new Error('Internal representation must be 32 bytes.'); | |
} | |
this.buffer = buffer; | |
} | |
static fromEvm20(address: string): Address { | |
if (!Address.isValidEvm20(address)) { | |
throw new Error('Invalid EVM 20-byte address.'); | |
} | |
address = address.startsWith('0x') ? address.slice(2) : address; | |
const evm20 = Buffer.from(address, 'hex'); | |
// Create a 12-byte zero buffer for padding | |
const padding = Buffer.alloc(12, 0); | |
const fullBuffer = Buffer.concat([padding, evm20]); | |
return new Address(fullBuffer); | |
} | |
static fromEvm32(address: string): Address { | |
if (!Address.isValidEvm32(address)) { | |
throw new Error('Invalid EVM 32-byte address.'); | |
} | |
address = address.startsWith('0x') ? address.slice(2) : address; | |
const buffer = Buffer.from(address, 'hex'); | |
return new Address(buffer); | |
} | |
static fromSolana(address: string): Address { | |
if (!Address.isValidSolana(address)) { | |
throw new Error('Invalid Solana address.'); | |
} | |
const decoded = bs58.decode(address); | |
const buffer = Buffer.from(decoded); | |
return new Address(buffer); | |
} | |
toEvm32(): string { | |
return '0x' + this.buffer.toString('hex'); | |
} | |
toEvm20(): string { | |
// Slice the lower 20 bytes. | |
return '0x' + this.buffer.slice(12).toString('hex'); | |
} | |
toSolana(): string { | |
return bs58.encode(this.buffer); | |
} | |
static isValidEvm20(address: string): boolean { | |
if (address.startsWith('0x')) { | |
address = address.slice(2); | |
} | |
return /^[0-9a-fA-F]{40}$/.test(address); | |
} | |
static isValidEvm32(address: string): boolean { | |
if (address.startsWith('0x')) { | |
address = address.slice(2); | |
} | |
return /^[0-9a-fA-F]{64}$/.test(address); | |
} | |
static isValidSolana(address: string): boolean { | |
try { | |
const decoded = bs58.decode(address); | |
return decoded.length === 32; | |
} catch { | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
updated implementation with more generic naming