Skip to content

Commit 27a6550

Browse files
committed
feat(sdk-coin-cronos): add SDK support for Cronos
TICKET: COIN-4022
1 parent b9c637e commit 27a6550

File tree

15 files changed

+1117
-29
lines changed

15 files changed

+1117
-29
lines changed

modules/sdk-coin-cronos/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@
4343
"@bitgo/abstract-cosmos": "^11.7.2",
4444
"@bitgo/sdk-core": "^33.1.0",
4545
"@bitgo/statics": "^52.1.0",
46-
"@cosmjs/stargate": "^0.29.5"
46+
"@cosmjs/stargate": "^0.29.5",
47+
"@cosmjs/amino": "^0.29.5",
48+
"@cosmjs/encoding": "^0.29.5",
49+
"@cosmjs/stargate": "^0.29.5",
50+
"bignumber.js": "^9.1.1"
4751
},
4852
"devDependencies": {
4953
"@bitgo/sdk-api": "^1.62.2",
Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
import { BaseCoin, BitGoBase } from '@bitgo/sdk-core';
2-
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
1+
import { BaseCoin, BitGoBase, Environments } from '@bitgo/sdk-core';
2+
import { BaseUnit, BaseCoin as StaticsBaseCoin, coins } from '@bitgo/statics';
33
import { CosmosCoin, CosmosKeyPair, GasAmountDetails } from '@bitgo/abstract-cosmos';
4-
import { TransactionBuilderFactory } from './lib';
4+
import { KeyPair, TransactionBuilderFactory } from './lib';
5+
import { GAS_AMOUNT, GAS_LIMIT } from './lib/constants';
6+
import { Utils } from './lib/utils';
57

8+
/**
9+
*
10+
* Full Name: Cronos
11+
* Website: https://cronos-pos.org/
12+
* Docs: https://docs.cronos-pos.org/
13+
* GitHub : https://github.com/crypto-org-chain/chain-main
14+
*/
615
export class Cronos extends CosmosCoin {
16+
protected readonly _utils: Utils;
717
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
818

919
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
@@ -14,6 +24,7 @@ export class Cronos extends CosmosCoin {
1424
}
1525

1626
this._staticsCoin = staticsCoin;
27+
this._utils = new Utils();
1728
}
1829

1930
static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
@@ -27,36 +38,39 @@ export class Cronos extends CosmosCoin {
2738

2839
/** @inheritDoc **/
2940
getBuilder(): TransactionBuilderFactory {
30-
throw new Error('Method not implemented.');
41+
return new TransactionBuilderFactory(coins.get(this.getChain()));
3142
}
3243

3344
/** @inheritDoc **/
3445
isValidAddress(address: string): boolean {
35-
throw new Error('Method not implemented.');
46+
return this._utils.isValidAddress(address) || this._utils.isValidValidatorAddress(address);
3647
}
3748

3849
/** @inheritDoc **/
3950
getDenomination(): string {
40-
throw new Error('Method not implemented');
51+
return BaseUnit.CRONOS;
4152
}
4253

4354
/** @inheritDoc **/
4455
getGasAmountDetails(): GasAmountDetails {
45-
throw new Error('Method not implemented');
56+
return {
57+
gasAmount: GAS_AMOUNT,
58+
gasLimit: GAS_LIMIT,
59+
};
4660
}
4761

4862
/** @inheritDoc **/
4963
getKeyPair(publicKey: string): CosmosKeyPair {
50-
throw new Error('Method not implemented');
64+
return new KeyPair({ pub: publicKey });
5165
}
5266

5367
/** @inheritDoc **/
5468
protected getPublicNodeUrl(): string {
55-
throw new Error('Method not implemented');
69+
return Environments[this.bitgo.getEnv()].cronosNodeUrl;
5670
}
5771

5872
/** @inheritDoc **/
5973
getAddressFromPublicKey(pubKey: string): string {
60-
throw new Error('Method not implemented');
74+
return new KeyPair({ pub: pubKey }).getAddress();
6175
}
6276
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const validDenoms = ['cro', 'tcro', 'basecro', 'basetcro'];
2+
3+
export const mainnetAccountAddressRegex = /^(cro)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
4+
export const mainnetValidatorAddressRegex = /^(crocncl)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
5+
export const mainnetContractAddressRegex = /^(cro)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/;
6+
export const MAINNET_ADDRESS_PREFIX = 'cro';
7+
8+
export const testnetAccountAddressRegex = /^(tcro)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
9+
export const testnetValidatorAddressRegex = /^(tcrocncl)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
10+
export const testnetContractAddressRegex = /^(tcro)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/;
11+
export const TESTNET_ADDRESS_PREFIX = 'tcro';
12+
13+
export const GAS_AMOUNT = '30000';
14+
export const GAS_LIMIT = 500000;
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import { KeyPairOptions } from '@bitgo/sdk-core';
1+
import { AddressFormat, KeyPairOptions } from '@bitgo/sdk-core';
2+
import { pubkeyToAddress } from '@cosmjs/amino';
3+
24
import { CosmosKeyPair } from '@bitgo/abstract-cosmos';
5+
import { MAINNET_ADDRESS_PREFIX, TESTNET_ADDRESS_PREFIX } from './constants';
36

47
/**
58
* Cronos keys and address management.
@@ -10,7 +13,15 @@ export class KeyPair extends CosmosKeyPair {
1013
}
1114

1215
/** @inheritdoc */
13-
getAddress(): string {
14-
throw new Error('Method not implemented.');
16+
getAddress(format: AddressFormat = AddressFormat.mainnet): string {
17+
const base64String = Buffer.from(this.getKeys().pub.slice(0, 66), 'hex').toString('base64');
18+
const address_prefix = format === AddressFormat.testnet ? TESTNET_ADDRESS_PREFIX : MAINNET_ADDRESS_PREFIX;
19+
return pubkeyToAddress(
20+
{
21+
type: 'tendermint/PubKeySecp256k1',
22+
value: base64String,
23+
},
24+
address_prefix
25+
);
1526
}
1627
}

modules/sdk-coin-cronos/src/lib/transactionBuilderFactory.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@bitgo/abstract-cosmos';
1111
import { BaseTransactionBuilderFactory, InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
1212
import { BaseCoin as CoinConfig } from '@bitgo/statics';
13-
import utils from './utils';
13+
import { Utils } from './utils';
1414

1515
export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
1616
constructor(_coinConfig: Readonly<CoinConfig>) {
@@ -19,7 +19,7 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
1919

2020
/** @inheritdoc */
2121
from(raw: string): CosmosTransactionBuilder {
22-
const tx = new CosmosTransaction(this._coinConfig, utils);
22+
const tx = new CosmosTransaction(this._coinConfig, new Utils(this._coinConfig.network.type));
2323
tx.enrichTransactionDetailsFromRawTransaction(raw);
2424
try {
2525
switch (tx.type) {
@@ -45,27 +45,45 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
4545

4646
/** @inheritdoc */
4747
getTransferBuilder(tx?: CosmosTransaction): CosmosTransferBuilder {
48-
return this.initializeBuilder(tx, new CosmosTransferBuilder(this._coinConfig, utils));
48+
return this.initializeBuilder(
49+
tx,
50+
new CosmosTransferBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
51+
);
4952
}
5053
/** @inheritdoc */
5154
getStakingActivateBuilder(tx?: CosmosTransaction): StakingActivateBuilder {
52-
return this.initializeBuilder(tx, new StakingActivateBuilder(this._coinConfig, utils));
55+
return this.initializeBuilder(
56+
tx,
57+
new StakingActivateBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
58+
);
5359
}
5460
/** @inheritdoc */
5561
getStakingDeactivateBuilder(tx?: CosmosTransaction): StakingDeactivateBuilder {
56-
return this.initializeBuilder(tx, new StakingDeactivateBuilder(this._coinConfig, utils));
62+
return this.initializeBuilder(
63+
tx,
64+
new StakingDeactivateBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
65+
);
5766
}
5867
/** @inheritdoc */
5968
getStakingWithdrawRewardsBuilder(tx?: CosmosTransaction): StakingWithdrawRewardsBuilder {
60-
return this.initializeBuilder(tx, new StakingWithdrawRewardsBuilder(this._coinConfig, utils));
69+
return this.initializeBuilder(
70+
tx,
71+
new StakingWithdrawRewardsBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
72+
);
6173
}
6274

6375
getContractCallBuilder(tx?: CosmosTransaction): ContractCallBuilder {
64-
return this.initializeBuilder(tx, new ContractCallBuilder(this._coinConfig, utils));
76+
return this.initializeBuilder(
77+
tx,
78+
new ContractCallBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
79+
);
6580
}
6681

6782
getStakingRedelegateBuilder(tx?: CosmosTransaction): StakingRedelegateBuilder {
68-
return this.initializeBuilder(tx, new StakingRedelegateBuilder(this._coinConfig, utils));
83+
return this.initializeBuilder(
84+
tx,
85+
new StakingRedelegateBuilder(this._coinConfig, new Utils(this._coinConfig.network.type))
86+
);
6987
}
7088

7189
/** @inheritdoc */

modules/sdk-coin-cronos/src/lib/utils.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,50 @@
11
import { CosmosUtils } from '@bitgo/abstract-cosmos';
2+
import { InvalidTransactionError } from '@bitgo/sdk-core';
23
import { Coin } from '@cosmjs/stargate';
4+
import BigNumber from 'bignumber.js';
5+
import * as constants from './constants';
6+
import { NetworkType } from '@bitgo/statics';
37

48
export class Utils extends CosmosUtils {
9+
private networkType: NetworkType;
10+
constructor(networkType: NetworkType = NetworkType.MAINNET) {
11+
super();
12+
this.networkType = networkType;
13+
}
14+
515
/** @inheritdoc */
616
isValidAddress(address: string): boolean {
7-
throw new Error('Method not implemented.');
17+
if (this.networkType === NetworkType.TESTNET) {
18+
return this.isValidCosmosLikeAddressWithMemoId(address, constants.testnetAccountAddressRegex);
19+
}
20+
return this.isValidCosmosLikeAddressWithMemoId(address, constants.mainnetAccountAddressRegex);
821
}
922

1023
/** @inheritdoc */
1124
isValidValidatorAddress(address: string): boolean {
12-
throw new Error('Method not implemented.');
25+
if (this.networkType === NetworkType.TESTNET) {
26+
return this.isValidBech32AddressMatchingRegex(address, constants.testnetValidatorAddressRegex);
27+
}
28+
return this.isValidBech32AddressMatchingRegex(address, constants.mainnetValidatorAddressRegex);
1329
}
1430

1531
/** @inheritdoc */
1632
isValidContractAddress(address: string): boolean {
17-
throw new Error('Method not implemented.');
33+
if (this.networkType === NetworkType.TESTNET) {
34+
return this.isValidBech32AddressMatchingRegex(address, constants.testnetContractAddressRegex);
35+
}
36+
return this.isValidBech32AddressMatchingRegex(address, constants.mainnetContractAddressRegex);
1837
}
1938

2039
/** @inheritdoc */
2140
validateAmount(amount: Coin): void {
22-
throw new Error('Method not implemented.');
41+
const amountBig = BigNumber(amount.amount);
42+
if (amountBig.isLessThanOrEqualTo(0)) {
43+
throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid amount: ' + amount.amount);
44+
}
45+
if (!constants.validDenoms.find((denom) => denom === amount.denom)) {
46+
throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid denom: ' + amount.denom);
47+
}
2348
}
2449
}
2550

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { BaseCoin, BitGoBase } from '@bitgo/sdk-core';
2-
import { BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
1+
import { AddressFormat, BaseCoin, BitGoBase } from '@bitgo/sdk-core';
2+
import { BaseCoin as StaticsBaseCoin, NetworkType } from '@bitgo/statics';
33
import { Cronos } from './cronos';
4+
import { Utils } from './lib/utils';
5+
import { KeyPair } from './lib/keyPair';
46

57
export class Tcronos extends Cronos {
8+
protected readonly _utils: Utils;
69
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
710
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
811
super(bitgo, staticsCoin);
@@ -12,9 +15,15 @@ export class Tcronos extends Cronos {
1215
}
1316

1417
this._staticsCoin = staticsCoin;
18+
this._utils = new Utils(NetworkType.TESTNET);
1519
}
1620

1721
static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
1822
return new Tcronos(bitgo, staticsCoin);
1923
}
24+
25+
/** @inheritDoc **/
26+
getAddressFromPublicKey(publicKey: string): string {
27+
return new KeyPair({ pub: publicKey }).getAddress(AddressFormat.testnet);
28+
}
2029
}

0 commit comments

Comments
 (0)