Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/abstract-cosmos/src/lib/iface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export interface MessageData<CustomMessage = never> {
export interface FeeData {
amount: Coin[];
gasLimit: number;
feeGranter?: string;
}

export interface GasAmountDetails {
Expand Down
15 changes: 15 additions & 0 deletions modules/abstract-cosmos/src/lib/transactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ export abstract class CosmosTransactionBuilder<CustomMessage = never> extends Ba
return this;
}

/**
* Sets the fee granter address for this transaction.
* The fee granter is the address that will pay the transaction fees on behalf of the signer.
* @param {string} address - The address that will pay the transaction fees
* @returns {TransactionBuilder} this transaction builder
*/
feeGranter(address: string): this {
this.validateAddress({ address });
if (!this._gasBudget) {
throw new BuildTransactionError('Gas budget must be set before setting fee granter');
}
this._gasBudget.feeGranter = address;
return this;
}

/**
* Initialize the transaction builder fields using the decoded transaction data
* @param {CosmosTransaction} tx the transaction data
Expand Down
8 changes: 6 additions & 2 deletions modules/abstract-cosmos/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,14 @@ export class CosmosUtils<CustomMessage = never> implements BaseUtils {
* @returns {FeeData} fee data
*/
getGasBudgetFromDecodedTx(decodedTx: DecodedTxRaw): FeeData {
return {
const feeData: FeeData = {
amount: decodedTx.authInfo.fee?.amount as Coin[],
gasLimit: Number(decodedTx.authInfo.fee?.gasLimit),
};
if (decodedTx.authInfo.fee?.granter) {
feeData.feeGranter = decodedTx.authInfo.fee.granter;
}
return feeData;
}

/**
Expand Down Expand Up @@ -419,7 +423,7 @@ export class CosmosUtils<CustomMessage = never> implements BaseUtils {
[{ pubkey: encodedPublicKey, sequence }],
cosmosLikeTransaction.gasBudget.amount,
cosmosLikeTransaction.gasBudget.gasLimit,
undefined,
cosmosLikeTransaction.gasBudget.feeGranter || undefined,
undefined,
undefined
);
Expand Down
4 changes: 2 additions & 2 deletions modules/sdk-coin-hash/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { CosmosUtils } from '@bitgo/abstract-cosmos';

const cosmosUtils = new CosmosUtils();
export const validDenoms = ['nhash', 'uhash', 'mhash', 'hash', ...cosmosUtils.getTokenDenomsUsingCoinFamily('hash')];
export const mainnetAccountAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
export const mainnetAccountAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38,58})$/;
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 testnetAccountAddressRegex = /^(tp)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38,58})$/;
export const testnetValidatorAddressRegex = /^(tpvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/;
export const testnetContractAddressRegex = /^(tp)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/;
export const TESTNET_ADDRESS_PREFIX = 'tp';
2 changes: 2 additions & 0 deletions modules/sdk-coin-hash/test/resources/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ export const mainnetAddress = {
address2: 'pb16vmp7sz28pnvgz6f3zm6q93y39jsd33aazwg4u',
address3: 'pb2xvd4k9jg5h0d4dhzr4z0txtwe9p5zxf58xcmxd',
address4: 'pb1fmxzuzx5c4ja50vu94nt0aessnuedzmppde8qq',
groupPolicyAddress: 'pb1tazefwk2e372fy2jq08w6lztg9yrrvc490r2gp4vt8d0fchlrfqqt58ltq',
validatorAddress1: 'pbvaloper13905qnf0mc8f8h3dawsq0894ded0ct83f66l56',
validatorAddress2: 'pbvaloper1d7yum2cxwkhmmuxa096prlv5gawjxw0gc2sykq',
validatorAddress3: 'pbvaloder17yx96jtu0r24jp8gyxc8y8pj0lgvcz964w2gyg',
Expand All @@ -286,6 +287,7 @@ export const testnetAddress = {
address2: 'tp1ytxha7lg002rzd4jxmahrdjzkd62mx99klgjcc',
address3: 'txp1x96r8u4a48k6khknrhzd6c8cm3c64ewxy5prj',
address4: 'tp1umned7wx7le70ttvrcem3fsyhn343asr2k2pww',
groupPolicyAddress: 'tp1tazefwk2e372fy2jq08w6lztg9yrrvc490r2gp4vt8d0fchlrfqqyahg0u',
validatorAddress1: 'tpvaloper1tgq6cpu6hmsrvkvdu82j99tsxxw7qqajn843fe',
validatorAddress2: 'tpvaloper1tgq6cpu6hmsrvkvdu82j99tsxxw7qqajn843fe',
validatorAddress3: 'txvaloper1xxxxcpu6hmsrvkvdu82j99tsxxw7qqajn843fe',
Expand Down
2 changes: 2 additions & 0 deletions modules/sdk-coin-hash/test/unit/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ describe('HASH', function () {
should.equal(mainnetUtils.isValidAddress(''), false);
should.equal(mainnetUtils.isValidAddress(mainnetAddress.validMemoIdAddress), true);
should.equal(mainnetUtils.isValidAddress(mainnetAddress.multipleMemoIdAddress), false);
should.equal(mainnetUtils.isValidAddress(mainnetAddress.groupPolicyAddress), true);

should.equal(testnetUtils.isValidAddress(testnetAddress.address1), true);
should.equal(testnetUtils.isValidAddress(testnetAddress.address2), true);
Expand All @@ -114,6 +115,7 @@ describe('HASH', function () {
should.equal(testnetUtils.isValidAddress(''), false);
should.equal(testnetUtils.isValidAddress(testnetAddress.validMemoIdAddress), true);
should.equal(testnetUtils.isValidAddress(testnetAddress.multipleMemoIdAddress), false);
should.equal(testnetUtils.isValidAddress(testnetAddress.groupPolicyAddress), true);
});

it('should validate validator addresses correctly', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,22 @@ describe('Hash Token Transfer Builder', () => {
},
]);
});

it('should build a Transfer tx with fee granter', async function () {
const feeGranterAddress = testData.testnetAddress.address2;
const txBuilder = factory.getTransferBuilder();
txBuilder.sequence(testTx.sequence);
txBuilder.gasBudget(testTx.gasBudget);
txBuilder.feeGranter(feeGranterAddress);
txBuilder.messages([testTx.sendMessage.value]);
txBuilder.publicKey(toHex(fromBase64(testTx.pubKey)));

const tx = await txBuilder.build();
const json = await (await txBuilder.build()).toJson();
should.equal(tx.type, TransactionType.Send);
should.deepEqual(json.gasBudget.amount, testTx.gasBudget.amount);
should.deepEqual(json.gasBudget.gasLimit, testTx.gasBudget.gasLimit);
should.equal(json.gasBudget.feeGranter, feeGranterAddress);
should.deepEqual(json.sendMessages, [testTx.sendMessage]);
});
});
Loading