Skip to content

Commit

Permalink
Merge pull request #420 from crypto-org-chain/feat/upgrade-web3
Browse files Browse the repository at this point in the history
feat: upgrade web3
  • Loading branch information
calvinaco authored Sep 2, 2024
2 parents 6d07cb3 + 58370c6 commit 406ecc5
Show file tree
Hide file tree
Showing 14 changed files with 493 additions and 5,317 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16

- uses: actions/checkout@v2

Expand All @@ -34,7 +34,7 @@ jobs:
steps:
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16

- uses: actions/checkout@v2

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Generate coverage report
uses: actions/setup-node@v1
with:
node-version: '12'
node-version: '16'
- run: npm install
- run: npm run run-coverage
- run: npm run generate-report
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
steps:
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16

- uses: actions/checkout@v2
- name: Build
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [10, 11, 12, 13]
node: [16]

steps:
- uses: actions/setup-node@v1
Expand All @@ -26,7 +26,7 @@ jobs:
with:
path: node_modules
key: ${{ runner.os }}-node${{ matrix.code }}-${{ hashFiles('**/package-lock.json') }}

- name: Run test
run: |
npm install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 14
node-version: 16

- uses: actions/cache@v2
id: cache-deps
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_e2e_IBC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 14
node-version: 16

- uses: actions/cache@v2
id: cache-deps
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/upload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/setup-node@v1
with:
node-version: 12
node-version: 16

- uses: actions/checkout@v2
- name: build lib
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog

All notable changes to this project will be documented in this file.
## v1.1.3
- Remove dependencies from `web3 1.x`

## v1.1.2
- Added CRO `Croeseid-5` Testnet network
- Update CRO `Mainnet` & `Croeseid-4` Testnet network endpoints
Expand Down
2 changes: 1 addition & 1 deletion lib/src/transaction/v2.raw.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ describe('Transaction', function () {
expect(() => {
anyTx.toCosmosJSON();
}).to.throw(
"error converting RawTransaction to Cosmos compatible JSON: TypeError: Cannot read property 'value' of undefined",
"error converting RawTransaction to Cosmos compatible JSON: TypeError: Cannot read properties of undefined (reading 'value')",
);
});

Expand Down
92 changes: 91 additions & 1 deletion lib/src/utils/address.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import 'mocha';
import { expect } from 'chai';
import { AddressType, AddressValidator, validateAddress, getBech32AddressFromEVMAddress } from './address';
import {
AddressType,
AddressValidator,
validateAddress,
getBech32AddressFromEVMAddress,
isHexPrefixed,
isHexStrict,
isUint8Array,
stripHexPrefix,
uint8ArrayToHexString,
isAddress,
checkAddressCheckSum,
} from './address';
import { CroNetwork } from '../core/cro';

describe('Validate address against network and checksums', function () {
Expand Down Expand Up @@ -52,6 +64,84 @@ describe('Validate address against network and checksums', function () {
).to.throw('Invalid checksum for tcrocncl1reyshfdygf7673xm9p8v0xvtd96m6cd6canhu3xcqa');
});

describe('Hex and Bytes conversion checking', function () {
const address = {
tendermint: 'cro1pndm4ywdf4qtmupa0fqe75krmqed2znjyj6x8f',
EVM: '0xD47286f025F947482a2C374Fb70e9D4c94d809CF',
};
it('isHexPrefixed should return false for tendermint address', function () {
expect(isHexPrefixed(address.tendermint)).to.be.eq(false);
});

it('isHexPrefixed should return true for EVM address', function () {
expect(isHexPrefixed(address.EVM)).to.be.eq(true);
});

it('isHexStrict should return true for hexString', function () {
expect(isHexStrict('0xc1912')).to.be.eq(true);
});
it('isHexStrict should return false for hex', function () {
expect(isHexStrict(0xc1912)).to.be.eq(false);
});
it('isHexStrict should return false for normal string', function () {
expect(isHexStrict('c1912')).to.be.eq(false);
});
it('isHexStrict should return false for number', function () {
expect(isHexStrict(345)).to.be.eq(false);
});
it('isUint8Array should return true for Uint8Array instance', function () {
expect(isUint8Array(new Uint8Array([21, 31]))).to.be.eq(true);
});
it('isUint8Array should return true for Buffer instance', function () {
expect(isUint8Array(Buffer.from([21, 31]))).to.be.eq(true);
});
it('isUint8Array should return false for string', function () {
expect(isUint8Array('string')).to.be.eq(false);
});
it(`stripHexPrefix should return ${address.tendermint} without modification`, function () {
expect(stripHexPrefix(address.tendermint)).to.be.eq(address.tendermint);
});
it(`stripHexPrefix should trim '0x' from ${address.EVM}`, function () {
expect(stripHexPrefix(address.EVM)).to.be.eq('D47286f025F947482a2C374Fb70e9D4c94d809CF');
});
it(`uint8ArrayToHexString convert empty Uint8Array to HexString`, function () {
expect(uint8ArrayToHexString(new Uint8Array(4))).to.be.eq('0x00000000');
});
it(`uint8ArrayToHexString convert Uint8Array to HexString`, function () {
expect(uint8ArrayToHexString(new Uint8Array([0x1f, 0x2f, 0x3f, 0x4f]))).to.be.eq('0x1f2f3f4f');
});
it(`isAddress should return false for valid EVM address`, function () {
expect(isAddress(address.tendermint)).to.be.eq(false);
});
it(`isAddress should return true for valid EVM address`, function () {
expect(isAddress(address.EVM)).to.be.eq(true);
});
it(`isAddress should return true with EVM-valid Uint8Array`, function () {
expect(isAddress(new Uint8Array(20))).to.be.eq(true);
});
it(`isAddress should return false for non 40-length string`, function () {
expect(isAddress('should return false')).to.be.eq(false);
});
it(`isAddress should return false for 40-length non EVM-valid string`, function () {
expect(isAddress('0xD47286f025F947482a2C374Fb70e9D4c94d809CG')).to.be.eq(false);
});
it(`isAddress should return true for valid capitalized EVM address`, function () {
expect(isAddress(address.EVM.toUpperCase())).to.be.eq(true);
});
it(`isAddress should return true for valid trimmed EVM address`, function () {
expect(isAddress(stripHexPrefix(address.EVM))).to.be.eq(true);
});
it(`checkAddressCheckSum should return true for valid EVM address`, function () {
expect(checkAddressCheckSum(address.EVM)).to.be.eq(true);
});
it(`checkAddressCheckSum should return false for invalid EVM address`, function () {
expect(checkAddressCheckSum('0x6c46a1e212f127a6a8787b456a243c0d')).to.be.eq(false);
});
it(`checkAddressCheckSum should return false`, function () {
expect(checkAddressCheckSum('0xd47286f025F947482a2C374Fb70e9D4c94d809CF')).to.be.eq(false);
});
});

describe('AddressValidator', function () {
it('validate should throw Error when the address is invalid', function () {
const addressProps = {
Expand Down
81 changes: 72 additions & 9 deletions lib/src/utils/address.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import bech32 from 'bech32';
import { isAddress, stripHexPrefix } from 'web3-utils';
import { keccak256 } from 'ethereum-cryptography/keccak';
import { utf8ToBytes } from 'ethereum-cryptography/utils';
import { Network } from '../network/network';
import { Bytes } from './bytes/bytes';
// import { toBase64 } from '@cosmjs/encoding';

export interface AddressValidationProperties {
address: string;
Expand All @@ -14,13 +14,76 @@ export enum AddressType {
USER,
VALIDATOR,
}
// https://stackoverflow.com/questions/49434751/how-to-declare-a-function-that-throws-an-error-in-typescript
/**
* Check address validity against its type and provided network
* @param {AddressValidationProperties} addressProps
* @returns {boolean}
* @throws {Error} when Bech32 encoding is not correct
*/

export function isHexPrefixed(str: string): boolean {
return str.startsWith('0x');
}

export function stripHexPrefix(str: string): string {
return isHexPrefixed(str) ? str.slice(2) : str;
}

export function isUint8Array(data: unknown | Uint8Array): data is Uint8Array {
return (
data instanceof Uint8Array ||
(data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array' ||
(data as { constructor: { name: string } })?.constructor?.name === 'Buffer'
);
}

export function uint8ArrayToHexString(uint8Array: Uint8Array): string {
return uint8Array.reduce((hexString, e) => {
const hex = e.toString(16);
return hexString + (hex.length === 1 ? `0${hex}` : hex);
}, '0x');
}

export function isHexStrict(hex: Uint8Array | bigint | string | number | boolean) {
return typeof hex === 'string' && /^((-)?0x[0-9a-f]+|(0x))$/i.test(hex);
}

export function checkAddressCheckSum(data: string): boolean {
if (!/^(0x)?[0-9a-f]{40}$/i.test(data)) return false;
const address = data.slice(2);
const updatedData = utf8ToBytes(address.toLowerCase());

const addressHash = uint8ArrayToHexString(keccak256(updatedData)).slice(2);

for (let i = 0; i < 40; i += 1) {
// the nth letter should be uppercase if the nth digit of casemap is 1
if (
(parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) ||
(parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])
) {
return false;
}
}
return true;
}

export const isAddress = (value: Uint8Array | string, checkChecksum = true) => {
let valueToCheck: string;

if (isUint8Array(value)) {
valueToCheck = uint8ArrayToHexString(value);
} else if (typeof value === 'string' && !isHexStrict(value)) {
valueToCheck = value.toLowerCase().startsWith('0x') ? value : `0x${value}`;
} else {
valueToCheck = value;
}

// check if it has the basic requirements of an address
if (!/^(0x)?[0-9a-f]{40}$/i.test(valueToCheck)) {
return false;
}
// If it's ALL lowercase or ALL upppercase
if (/^(0x|0X)?[0-9a-f]{40}$/.test(valueToCheck) || /^(0x|0X)?[0-9A-F]{40}$/.test(valueToCheck)) {
return true;
// Otherwise check each case
}
return checkChecksum ? checkAddressCheckSum(valueToCheck) : true;
};

export function validateAddress(addressProps: AddressValidationProperties): boolean | never {
const { network } = addressProps;
const bech32Decoded = bech32.decode(addressProps.address);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils/txDecoder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('TxDecoder', function () {
const txDecoder = new TxDecoder();
const txBytes = Bytes.fromBase64String('CpQBCpEBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnEKK3Rjcm8xMnlnd2R2ZnZndDRjNzJlMG11N2g2Z21mdjl5d2gzNHI5a2FjanISK3Rjcm8xMnlnd2R2ZnZndDRjNzJlMG11N2g2Z21mdjl5d2gzNHI5a2FjanIaFQoIYmFzZXRjcm8SCTEwMDAwMDAwMBKxAgqoAgqIAgopL2Nvc21vcy5jcnlwdG8ubXVsdGlzaWcuTGVnYWN5QW1pbm9QdWJLZXkS2gEIAxJGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQMmHiFA8uJvK1ug4G0W1/pPLiZ+Ora8MsrgRPO9ZUbAxBJGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQIXveFFPdAc68u/wp8cyiSeVxSSaieLvHDr/a6ut9gf2RJGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQILzYXwxGx61Az+IAaYhDpsTKIPgRwhIOEgePSj1Ae5vhIbEhkKBQgDEgHgEgQKAgh/EgQKAgh/EgQKAgh/EgQQwJoMGsYBCkAqnZ+kKTI2KNThqP4bi67jdF4vUItthnQjzzUbbpVrNS1L1JzRKAk8p3JAD/ZcJv5NrYH6nj/XA3BIY5aDGORRCkC+o5tK8zr8OZLuFIwias8t7v2U6u8XXrfNFL6uF3TyBSpvmW8BwCRZDFkwKosz6ryg6rObF6NCpheN0t+e7j+UCkCntQCqbypaLXA8RD0o7B/Gb5iQqD5jpOR0hd7rVQZ1xm+g6bKXS6Vd+vpNlzXmCUD1h8AxgEkKWxN5cQzL/0ZW');

expect(() => txDecoder.fromHex(txBytes.toHexString()).toCosmosJSON()).to.throw("Cannot read property 'length' of undefined");
expect(() => txDecoder.fromHex(txBytes.toHexString()).toCosmosJSON()).to.throw("Cannot read properties of undefined (reading 'length')");
});

it('should throw on invalid tx body messages array', function () {
Expand Down
Loading

0 comments on commit 406ecc5

Please sign in to comment.