From a324dce1bb433c50696c73e4dfc611d88398b89a Mon Sep 17 00:00:00 2001 From: aman035 Date: Thu, 12 Sep 2024 20:47:47 +0530 Subject: [PATCH] add: push Address conversion --- package-lock.json | 18 ++++++--- packages/core/package.json | 1 + packages/core/src/lib/address/address.ts | 42 +++++++++++++++++++++ packages/core/src/lib/index.ts | 3 +- packages/core/tests/address/address.test.ts | 30 +++++++++++++++ 5 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 packages/core/src/lib/address/address.ts create mode 100644 packages/core/tests/address/address.test.ts diff --git a/package-lock.json b/package-lock.json index 68059b57..8724eb35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3348,6 +3348,10 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@pushprotocol/node-core": { + "resolved": "packages/core", + "link": true + }, "node_modules/@scure/base": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", @@ -4608,6 +4612,12 @@ ], "license": "MIT" }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -4998,10 +5008,6 @@ "dev": true, "license": "MIT" }, - "node_modules/core": { - "resolved": "packages/core", - "link": true - }, "node_modules/core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -9764,11 +9770,13 @@ } }, "packages/core": { - "version": "0.0.1", + "name": "@pushprotocol/node-core", + "version": "0.0.4", "dependencies": { "@bufbuild/protobuf": "^2.0.0", "@noble/hashes": "^1.5.0", "axios": "^1.7.7", + "bech32": "^2.0.0", "tslib": "^2.3.0", "uuid": "^10.0.0", "viem": "^2.21.1" diff --git a/packages/core/package.json b/packages/core/package.json index c8c69b02..718c937a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -5,6 +5,7 @@ "@bufbuild/protobuf": "^2.0.0", "@noble/hashes": "^1.5.0", "axios": "^1.7.7", + "bech32": "^2.0.0", "tslib": "^2.3.0", "uuid": "^10.0.0", "viem": "^2.21.1" diff --git a/packages/core/src/lib/address/address.ts b/packages/core/src/lib/address/address.ts new file mode 100644 index 00000000..ab27db3a --- /dev/null +++ b/packages/core/src/lib/address/address.ts @@ -0,0 +1,42 @@ +import { hexToBytes, bytesToHex } from '@noble/hashes/utils'; +import { getAddress } from 'viem'; +import { bech32m } from 'bech32'; + +const PUSH_PREFIX = 'push'; + +export class Address { + /** + ** NOTE + * - bech32m prefix is always in lowercase + * - bech32m address is always in lowercase + */ + + /** + * Converts an EVM address to a Push (bech32m) address + * @param address EVM address + * @returns Push address + */ + static evmToPush = (address: `0x${string}`): string => { + try { + const words = bech32m.toWords(hexToBytes(getAddress(address).slice(2))); + return bech32m.encode(PUSH_PREFIX, words); + } catch (e) { + throw new Error('Invalid EVM address'); + } + }; + + /** + * Converts a Push (bech32m) address to an EVM address + * @param address Push address + * @returns EVM address in checksum format + */ + static pushToEvm = (address: `push${string}`): string => { + try { + const decoded = bech32m.decode(address); + const bytes = new Uint8Array(bech32m.fromWords(decoded.words)); + return getAddress(`0x${bytesToHex(bytes)}`); + } catch (e) { + throw new Error('Invalid Push address'); + } + }; +} diff --git a/packages/core/src/lib/index.ts b/packages/core/src/lib/index.ts index 10ccb8b8..e5c5e3aa 100644 --- a/packages/core/src/lib/index.ts +++ b/packages/core/src/lib/index.ts @@ -2,6 +2,7 @@ import { PushNetwork } from './pushNetwork'; import { Block } from './block/block'; import { Tx } from './tx/tx'; import { Validator } from './validator/validator'; +import { Address } from './address/address'; import { CONSTANTS } from './constants'; /** @@ -9,6 +10,6 @@ import { CONSTANTS } from './constants'; * serialization / deserialization capabilities for block & tx * Validator calls */ -export { CONSTANTS, Block, Tx, Validator }; +export { CONSTANTS, Block, Tx, Validator, Address }; export default PushNetwork; diff --git a/packages/core/tests/address/address.test.ts b/packages/core/tests/address/address.test.ts new file mode 100644 index 00000000..45f84f80 --- /dev/null +++ b/packages/core/tests/address/address.test.ts @@ -0,0 +1,30 @@ +import { Address } from '../../src/lib/address/address'; // Adjust the import path accordingly + +describe('Address', () => { + const evmAddress = '0x35B84d6848D16415177c64D64504663b998A6ab4'; + const pushAddress = 'push1xkuy66zg69jp29muvnty2prx8wvc5645f9y5ux'; + + describe('evmToPush', () => { + it('should convert a valid EVM address to a Push address', () => { + const result = Address.evmToPush(evmAddress); + expect(result).toEqual(pushAddress); + }); + + it('should throw an error for invalid EVM addresses', () => { + const invalidAddress = '0xinvalidaddress'; + expect(() => Address.evmToPush(invalidAddress)).toThrow(); + }); + }); + + describe('pushToEvm', () => { + it('should convert a valid Push address back to an EVM address', () => { + const result = Address.pushToEvm(pushAddress); + expect(result).toEqual(evmAddress); + }); + + it('should throw an error for invalid Push addresses', () => { + const invalidPushAddress = 'pushinvalidaddress'; + expect(() => Address.pushToEvm(invalidPushAddress)).toThrow(); + }); + }); +});