Skip to content

Commit

Permalink
Merge pull request #4093 from BitGo/WIN-1228-fix-hash-address
Browse files Browse the repository at this point in the history
fix(sdk-coin-hash): use correct mainnet address format
  • Loading branch information
hitansh-madan authored Nov 28, 2023
2 parents d2e87d0 + 13129e3 commit 26e6642
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 87 deletions.
12 changes: 7 additions & 5 deletions modules/sdk-coin-hash/src/hash.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { CosmosCoin, CosmosKeyPair, GasAmountDetails } from '@bitgo/abstract-cosmos';
import { BaseCoin, BitGoBase, Environments } from '@bitgo/sdk-core';
import { BaseUnit, BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
import { AddressFormat, BaseCoin, BitGoBase, Environments } from '@bitgo/sdk-core';
import { BaseUnit, NetworkType, BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';

import { KeyPair, TransactionBuilderFactory } from './lib';
import utils from './lib/utils';
import { HashUtils } from './lib/utils';

export class Hash extends CosmosCoin {
protected readonly _utils: HashUtils;
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
super(bitgo, staticsCoin);
Expand All @@ -15,6 +16,7 @@ export class Hash extends CosmosCoin {
}

this._staticsCoin = staticsCoin;
this._utils = new HashUtils(NetworkType.MAINNET);
}

static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
Expand All @@ -33,7 +35,7 @@ export class Hash extends CosmosCoin {

/** @inheritDoc **/
isValidAddress(address: string): boolean {
return utils.isValidAddress(address) || utils.isValidValidatorAddress(address);
return this._utils.isValidAddress(address) || this._utils.isValidValidatorAddress(address);
}

/** @inheritDoc **/
Expand Down Expand Up @@ -61,6 +63,6 @@ export class Hash extends CosmosCoin {

/** @inheritDoc **/
getAddressFromPublicKey(publicKey: string): string {
return new KeyPair({ pub: publicKey }).getAddress();
return new KeyPair({ pub: publicKey }).getAddress(AddressFormat.mainnet);
}
}
12 changes: 9 additions & 3 deletions modules/sdk-coin-hash/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export const validDenoms = ['nhash', 'uhash', 'mhash', 'hash'];
export const accountAddressRegex = /^(tp|pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const validatorAddressRegex = /^(tpvaloper|pbvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const contractAddressRegex = /^(tp|pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']+)$/;
export const mainnetAccountAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const mainnetValidatorAddressRegex = /^(pbvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const mainnetContractAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']+)$/;
export const MAINNET_ADDRESS_PREFIX = 'pb';

export const testnetAccountAddressRegex = /^(tp)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const testnetValidatorAddressRegex = /^(tpvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']{38})$/;
export const testnetContractAddressRegex = /^(tp)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l']+)$/;
export const TESTNET_ADDRESS_PREFIX = 'tp';
12 changes: 7 additions & 5 deletions modules/sdk-coin-hash/src/lib/keyPair.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { KeyPairOptions } from '@bitgo/sdk-core';
import { AddressFormat, KeyPairOptions } from '@bitgo/sdk-core';
import { pubkeyToAddress } from '@cosmjs/amino';

import { CosmosKeyPair } from '@bitgo/abstract-cosmos';
import { CosmosKeyPair, PubKeyType } from '@bitgo/abstract-cosmos';
import { MAINNET_ADDRESS_PREFIX, TESTNET_ADDRESS_PREFIX } from './constants';

/**
* Provenance keys and address management.
Expand All @@ -12,14 +13,15 @@ export class KeyPair extends CosmosKeyPair {
}

/** @inheritdoc */
getAddress(): string {
getAddress(format: AddressFormat = AddressFormat.testnet): string {
const base64String = Buffer.from(this.getKeys().pub.slice(0, 66), 'hex').toString('base64');
const address_prefix = format === AddressFormat.mainnet ? MAINNET_ADDRESS_PREFIX : TESTNET_ADDRESS_PREFIX;
return pubkeyToAddress(
{
type: 'tendermint/PubKeySecp256k1',
type: PubKeyType.secp256k1,
value: base64String,
},
'tp'
address_prefix
);
}
}
29 changes: 22 additions & 7 deletions modules/sdk-coin-hash/src/lib/transactionBuilderFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '@bitgo/abstract-cosmos';
import { BaseTransactionBuilderFactory, InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import hashUtils from './utils';
import { HashUtils } from './utils';

export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
constructor(_coinConfig: Readonly<CoinConfig>) {
Expand All @@ -18,7 +18,7 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {

/** @inheritdoc */
from(raw: string): CosmosTransactionBuilder {
const tx = new CosmosTransaction(this._coinConfig, hashUtils);
const tx = new CosmosTransaction(this._coinConfig, new HashUtils(this._coinConfig.network.type));
tx.enrichTransactionDetailsFromRawTransaction(raw);
try {
switch (tx.type) {
Expand All @@ -42,26 +42,41 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {

/** @inheritdoc */
getTransferBuilder(tx?: CosmosTransaction): CosmosTransferBuilder {
return this.initializeBuilder(tx, new CosmosTransferBuilder(this._coinConfig, hashUtils));
return this.initializeBuilder(
tx,
new CosmosTransferBuilder(this._coinConfig, new HashUtils(this._coinConfig.network.type))
);
}

/** @inheritdoc */
getStakingActivateBuilder(tx?: CosmosTransaction): StakingActivateBuilder {
return this.initializeBuilder(tx, new StakingActivateBuilder(this._coinConfig, hashUtils));
return this.initializeBuilder(
tx,
new StakingActivateBuilder(this._coinConfig, new HashUtils(this._coinConfig.network.type))
);
}

/** @inheritdoc */
getStakingDeactivateBuilder(tx?: CosmosTransaction): StakingDeactivateBuilder {
return this.initializeBuilder(tx, new StakingDeactivateBuilder(this._coinConfig, hashUtils));
return this.initializeBuilder(
tx,
new StakingDeactivateBuilder(this._coinConfig, new HashUtils(this._coinConfig.network.type))
);
}

/** @inheritdoc */
getStakingWithdrawRewardsBuilder(tx?: CosmosTransaction): StakingWithdrawRewardsBuilder {
return this.initializeBuilder(tx, new StakingWithdrawRewardsBuilder(this._coinConfig, hashUtils));
return this.initializeBuilder(
tx,
new StakingWithdrawRewardsBuilder(this._coinConfig, new HashUtils(this._coinConfig.network.type))
);
}

getContractCallBuilder(tx?: CosmosTransaction): ContractCallBuilder {
return this.initializeBuilder(tx, new ContractCallBuilder(this._coinConfig, hashUtils));
return this.initializeBuilder(
tx,
new ContractCallBuilder(this._coinConfig, new HashUtils(this._coinConfig.network.type))
);
}

/** @inheritdoc */
Expand Down
22 changes: 18 additions & 4 deletions modules/sdk-coin-hash/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import { InvalidTransactionError } from '@bitgo/sdk-core';
import { Coin } from '@cosmjs/stargate';
import BigNumber from 'bignumber.js';

import { NetworkType } from '@bitgo/statics';
import { CosmosUtils } from '@bitgo/abstract-cosmos';
import * as constants from './constants';

export class HashUtils extends CosmosUtils {
private networkType: NetworkType;
constructor(networkType: NetworkType = NetworkType.MAINNET) {
super();
this.networkType = networkType;
}
/** @inheritdoc */
isValidAddress(address: string): boolean {
return this.isValidCosmosLikeAddressWithMemoId(address, constants.accountAddressRegex);
if (this.networkType === NetworkType.TESTNET) {
return this.isValidCosmosLikeAddressWithMemoId(address, constants.testnetAccountAddressRegex);
}
return this.isValidCosmosLikeAddressWithMemoId(address, constants.mainnetAccountAddressRegex);
}

/** @inheritdoc */
isValidValidatorAddress(address: string): boolean {
return constants.validatorAddressRegex.test(address);
if (this.networkType === NetworkType.TESTNET) {
return constants.testnetValidatorAddressRegex.test(address);
}
return constants.mainnetValidatorAddressRegex.test(address);
}

/** @inheritdoc */
isValidContractAddress(address: string): boolean {
return constants.contractAddressRegex.test(address);
if (this.networkType === NetworkType.TESTNET) {
return constants.testnetContractAddressRegex.test(address);
}
return constants.mainnetContractAddressRegex.test(address);
}

/** @inheritdoc */
Expand Down
13 changes: 11 additions & 2 deletions modules/sdk-coin-hash/src/thash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
*
* @format
*/
import { BaseCoin, BitGoBase } from '@bitgo/sdk-core';
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
import { AddressFormat, BaseCoin, BitGoBase } from '@bitgo/sdk-core';
import { NetworkType, BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
import { Hash } from './hash';
import { HashUtils } from './lib/utils';
import { KeyPair } from './lib';

export class Thash extends Hash {
protected readonly _utils: HashUtils;
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
super(bitgo, staticsCoin);
Expand All @@ -17,9 +20,15 @@ export class Thash extends Hash {
}

this._staticsCoin = staticsCoin;
this._utils = new HashUtils(NetworkType.TESTNET);
}

static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
return new Thash(bitgo, staticsCoin);
}

/** @inheritDoc **/
getAddressFromPublicKey(publicKey: string): string {
return new KeyPair({ pub: publicKey }).getAddress(AddressFormat.testnet);
}
}
20 changes: 18 additions & 2 deletions modules/sdk-coin-hash/test/resources/hash.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Get the test data by running the scripts for the particular coin from coin-sandbox repo.

export const TEST_ACCOUNT = {
pubAddress: 'tp1496r8u4a48k6khknrhzd6c8cm3c64ewxy5p2rj',
pubAddress: 'pb1496r8u4a48k6khknrhzd6c8cm3c64ewxhlyxpc',
testnetPubAddress: 'tp1496r8u4a48k6khknrhzd6c8cm3c64ewxy5p2rj',
compressedPublicKey: '02f2501af39680be0afea7d3e5dbb399e0fa018f7c6de12287282a315c88f72b70',
compressedPublicKeyTwo: '03a0b91e3c7bfd399e46990a0ac60e0c75c53e83da944e65ce7d23f37302d253b4',
uncompressedPublicKey:
Expand Down Expand Up @@ -193,7 +194,22 @@ export const TEST_TX_WITH_MEMO = {
},
};

export const address = {
export const mainnetAddress = {
address1: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qr',
address2: 'pb16vmp7sz28pnvgz6f3zm6q93y39jsd33aazwg4u',
address3: 'pb2xvd4k9jg5h0d4dhzr4z0txtwe9p5zxf58xcmxd',
address4: 'pb1xvd4k9jg5h0d4dhzr4z0txtwe9p5zxf58xcmxd',
validatorAddress1: 'pbvaloper13905qnf0mc8f8h3dawsq0894ded0ct83f66l56',
validatorAddress2: 'pbvaloper1d7yum2cxwkhmmuxa096prlv5gawjxw0gc2sykq',
validatorAddress3: 'pbvaloder17yx96jtu0r24jp8gyxc8y8pj0lgvcz964w2gyg',
validatorAddress4: 'pbvaloper2v549f7d8f7junfga7yg04uz4zx0lwpqdl2f897',
noMemoIdAddress: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qr',
validMemoIdAddress: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qr?memoId=2',
invalidMemoIdAddress: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qr?memoId=xyz',
multipleMemoIdAddress: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qr?memoId=3&memoId=12',
};

export const testnetAddress = {
address1: 'tp1umned7wx7le70ttvrcem3fsyhn343asr2k2pwe',
address2: 'tp1ytxha7lg002rzd4jxmahrdjzkd62mx99klgjcc',
address3: 'txp1x96r8u4a48k6khknrhzd6c8cm3c64ewxy5prj',
Expand Down
Loading

0 comments on commit 26e6642

Please sign in to comment.