diff --git a/CODEOWNERS b/CODEOWNERS index 614b8730ac..c117c16963 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -62,6 +62,7 @@ /modules/sdk-coin-bsc/ @BitGo/ethalt-team /modules/sdk-coin-canton/ @BitGo/ethalt-team /modules/sdk-coin-coredao/ @BitGo/ethalt-team +/modules/sdk-coin-coreum/ @BitGo/ethalt-team /modules/sdk-coin-cosmos/ @BitGo/ethalt-team /modules/sdk-coin-cronos/ @BitGo/ethalt-team /modules/sdk-coin-cspr/ @BitGo/ethalt-team diff --git a/modules/sdk-coin-coreum/src/lib/constants.ts b/modules/sdk-coin-coreum/src/lib/constants.ts index 9eb480e28d..0dd076c21f 100644 --- a/modules/sdk-coin-coreum/src/lib/constants.ts +++ b/modules/sdk-coin-coreum/src/lib/constants.ts @@ -2,10 +2,12 @@ import { CosmosUtils } from '@bitgo/abstract-cosmos'; const cosmosUtils = new CosmosUtils(); export const validDenoms = ['ucore', 'utestcore', ...cosmosUtils.getTokenDenomsUsingCoinFamily('coreum')]; -export const mainnetAccountAddressRegex = /^(core)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; +export const mainnetAccountAddressRegex = + /^(core)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38}|['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58})$/; export const mainnetValidatorAddressRegex = /^(corevaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const MAINNET_ADDRESS_PREFIX = 'core'; -export const testnetAccountAddressRegex = /^(testcore)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; +export const testnetAccountAddressRegex = + /^(testcore)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38}|['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58})$/; export const testnetValidatorAddressRegex = /^(testcorevaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const TESTNET_ADDRESS_PREFIX = 'testcore'; diff --git a/modules/sdk-coin-coreum/test/resources/coreum.ts b/modules/sdk-coin-coreum/test/resources/coreum.ts index 72222feb7b..32540ce78d 100644 --- a/modules/sdk-coin-coreum/test/resources/coreum.ts +++ b/modules/sdk-coin-coreum/test/resources/coreum.ts @@ -19,6 +19,7 @@ export const mainnetAddress = { address2: 'core1ssh2d2ft6hzrgn9z6k7mmsamy2hfpxl9y8re5x', address3: 'core35udp7m30va5njkdrguj27wvk9lnutfwkevk7n9', address4: 'core1v7n3mrjg58udt7cyhv9gs62t8wcf9sh8w604yy', + address32byte1: 'core1pnxmcuxqvumfe6ktv40v2vm3z0zckluupzxu3uuq0f7t07w6xuwsc7td3m', validatorAddress1: 'corevaloper1gsaxrwfu5glgw764mqhc4t8f3yxg2h07rmwt0k', validatorAddress2: 'corevaloper1x9hd9r7duv2gagztvvqlw94v5gy4zd9xwhqnlm', validatorAddress3: 'corevaloper2flaz3hzgg3tjszl372lu2zz5jsmxd8pvydl7gg', diff --git a/modules/sdk-coin-coreum/test/unit/utils.ts b/modules/sdk-coin-coreum/test/unit/utils.ts index c8716daec5..08122c6f8b 100644 --- a/modules/sdk-coin-coreum/test/unit/utils.ts +++ b/modules/sdk-coin-coreum/test/unit/utils.ts @@ -1,7 +1,8 @@ import { NetworkType } from '@bitgo/statics'; import should from 'should'; import { CoreumUtils } from '../../src/lib/utils'; -import { blockHash, mainnetCoinAmounts, txIds } from '../resources/coreum'; +import { mainnetAccountAddressRegex, testnetAccountAddressRegex } from '../../src/lib/constants'; +import { blockHash, mainnetAddress, mainnetCoinAmounts, txIds } from '../resources/coreum'; import { testnetCoinAmounts } from '../resources/tcoreum'; describe('utils', () => { @@ -36,6 +37,32 @@ describe('utils', () => { should.equal(mainnetUtils.isValidTransactionId('dalij43ta0ga2dadda02'), false); }); + it('should accept 32-byte (group module / smart contract) addresses', () => { + should.equal(mainnetUtils.isValidAddress(mainnetAddress.address32byte1), true); + should.equal(mainnetUtils.isValidAddress(`${mainnetAddress.address32byte1}?memoId=1`), true); + }); + + it('should reject 32-byte addresses with an invalid checksum', () => { + const corrupted = mainnetAddress.address32byte1.slice(0, -1) + 'q'; + should.equal(mainnetUtils.isValidAddress(corrupted), false); + }); + + it('should reject addresses with intermediate data lengths (not 38 or 58 chars)', () => { + const bech32Chars = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'; + const intermediateData = bech32Chars.repeat(2).slice(0, 48); + should.equal(mainnetAccountAddressRegex.test(`core1${intermediateData}`), false); + should.equal(testnetAccountAddressRegex.test(`testcore1${intermediateData}`), false); + }); + + it('testnet regex should accept both 20-byte and 32-byte address lengths', () => { + const data38 = 'qpzry9x8gf2tvdw0s3jn54khce6mua7lqpzry9'; + should.equal(testnetAccountAddressRegex.test(`testcore1${data38}`), true); + const data58 = 'qpzry9x8gf2tvdw0s3jn54khce6mua7lqpzry9x8gf2tvdw0s3jn54khce'; + should.equal(testnetAccountAddressRegex.test(`testcore1${data58}`), true); + const data39 = 'qpzry9x8gf2tvdw0s3jn54khce6mua7lqpzry9x'; + should.equal(testnetAccountAddressRegex.test(`testcore1${data39}`), false); + }); + it('validateAmount', function () { should.doesNotThrow(() => mainnetUtils.validateAmountData([mainnetCoinAmounts.amount1])); should.doesNotThrow(() => mainnetUtils.validateAmountData([mainnetCoinAmounts.amount2]));