address.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { hexStr2byteArray, byteArray2hexStr } from './code.js';
  2. import { decodeBase58Address, getBase58CheckAddress, isAddressValid, pkToAddress } from './crypto.js';
  3. import { isHex, isString } from './validations.js';
  4. import { keccak256 } from './ethersUtils.js';
  5. export const ADDRESS_SIZE = 34;
  6. export const ADDRESS_PREFIX = '41';
  7. export const ADDRESS_PREFIX_BYTE = 0x41;
  8. export const ADDRESS_PREFIX_REGEX = /^(41)/;
  9. export const TRON_BIP39_PATH_PREFIX = "m/44'/195'";
  10. export const TRON_BIP39_PATH_INDEX_0 = TRON_BIP39_PATH_PREFIX + "/0'/0/0";
  11. export function fromHex(address: string) {
  12. if (!isHex(address)) return address;
  13. return getBase58CheckAddress(hexStr2byteArray(address.replace(/^0x/, ADDRESS_PREFIX)));
  14. }
  15. export function toHex(address: string) {
  16. if (isHex(address)) return address.toLowerCase().replace(/^0x/, ADDRESS_PREFIX);
  17. return byteArray2hexStr(decodeBase58Address(address) as number[]).toLowerCase();
  18. }
  19. function getChecksumAddress(address: string): string {
  20. address = address.toLowerCase();
  21. const chars = address.substring(2).split('');
  22. const expanded = new Uint8Array(40);
  23. for (let i = 0; i < 40; i++) {
  24. expanded[i] = chars[i].charCodeAt(0);
  25. }
  26. const hashed = hexStr2byteArray(keccak256(expanded).slice(2));
  27. for (let i = 0; i < 40; i += 2) {
  28. if ((hashed[i >> 1] >> 4) >= 8) {
  29. chars[i] = chars[i].toUpperCase();
  30. }
  31. if ((hashed[i >> 1] & 0x0f) >= 8) {
  32. chars[i + 1] = chars[i + 1].toUpperCase();
  33. }
  34. }
  35. return ADDRESS_PREFIX + chars.join('');
  36. }
  37. export function toChecksumAddress(address: string) {
  38. if (!isAddress(address)) throw new Error(`'${address}' is not a valid address string`);
  39. return getChecksumAddress(toHex(address));
  40. }
  41. export function isChecksumAddress(address: string) {
  42. if (!isHex(address) || address.length !== 42) return false;
  43. try {
  44. return toChecksumAddress(address) === address;
  45. } catch {
  46. return false;
  47. }
  48. }
  49. export function fromPrivateKey(privateKey: string, strict = false) {
  50. try {
  51. return pkToAddress(privateKey, strict);
  52. } catch {
  53. return false;
  54. }
  55. }
  56. export function isAddress(address: unknown): boolean {
  57. if (!address || !isString(address)) return false;
  58. // Convert HEX to Base58
  59. if (address.length === 42) {
  60. try {
  61. // it throws an error if the address starts with 0x
  62. return isAddress(getBase58CheckAddress(hexStr2byteArray(address)));
  63. } catch (err) {
  64. return false;
  65. }
  66. }
  67. try {
  68. return isAddressValid(address);
  69. } catch (err) {
  70. return false;
  71. }
  72. }