Skip to content

Commit

Permalink
Merge pull request #73 from terra-money/feat/simulate
Browse files Browse the repository at this point in the history
feat: simulate transaction return all data to the frontend
  • Loading branch information
emidev98 authored Jan 25, 2024
2 parents a03e575 + f9cd6a8 commit eeaf01b
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 4 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@terra-money/feather.js",
"version": "2.0.1",
"version": "2.0.2",
"description": "The JavaScript SDK for Terra and Feather chains",
"license": "MIT",
"author": "Terraform Labs, PTE.",
Expand Down
71 changes: 70 additions & 1 deletion src/client/lcd/api/TxAPI.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { LCDClient } from '../LCDClient';
import { APIRequester } from '../APIRequester';
import { MsgSend } from '../../../core';
import {
AuthInfo,
Coin,
Fee,
MsgSend,
MsgUndelegate,
Tx,
TxBody,
} from '../../../core';
import { TxAPI } from './TxAPI';
import { MnemonicKey } from '../../../key';
import { isTxError } from './TxAPI';
Expand Down Expand Up @@ -148,3 +156,64 @@ describe('TxAPI', () => {
});
});
});

describe('simulateTx', () => {
it('should simulate a transaction', async () => {
// Given the transaction that needs to be simulated
const mockTx = new Tx(
new TxBody([
new MsgUndelegate(
'mockDelegatorAddress',
'mockValidatorAddress',
new Coin('uluna', '1000000')
),
]),
new AuthInfo([], new Fee(50000000, [new Coin('uluna', '1000000')])),
['']
);
// We mock the data that will be returned from the blockchain API and set it up as a function that returns a promise
const mockResponseData = {
gas_info: {
gas_wanted: '2000',
gas_used: '1000',
},
result: {
data: 'data_mocked',
log: '[{"type":"message","attributes":[{"key":"action","value":"undelegate"}]}]',
events: [
{
type: 'message',
attributes: [{ key: 'action', value: 'undelegate' }],
},
],
},
};
lcd.apiRequesters['pisco-1'].post = jest.fn(
async () => Promise.resolve(mockResponseData) as any
);

// When simulating the transaction
const res = await lcd.tx.simulateTx(mockTx, 'pisco-1');

// Expect that the simulate endpoint have been executed,
// and assert the responses from the API.
expect(lcd.apiRequesters['pisco-1'].post).toHaveBeenCalledWith(
`/cosmos/tx/v1beta1/simulate`,
expect.any(Object)
);
expect(res.gas_info).toEqual({
gas_wanted: 2000,
gas_used: 1750,
});
expect(res.result).toEqual({
data: 'data_mocked',
log: '[{"type":"message","attributes":[{"key":"action","value":"undelegate"}]}]',
events: [
{
type: 'message',
attributes: [{ key: 'action', value: 'undelegate' }],
},
],
});
});
});
35 changes: 35 additions & 0 deletions src/client/lcd/api/TxAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,41 @@ export class TxAPI extends BaseAPI {
return new Dec(gasAdjustment).mul(simulateRes.gas_info.gas_used).toNumber();
}

public async simulateTx(
tx: Tx,
chainID: string,
options?: {
gasAdjustment?: Numeric.Input;
signers?: SignerData[];
}
): Promise<SimulateResponse> {
const gasAdjustment =
options?.gasAdjustment || this.lcd.config[chainID].gasAdjustment;

// append empty signatures if there's no signatures in tx
let simTx: Tx = tx;
if (tx.signatures.length <= 0) {
if (!(options && options.signers && options.signers.length > 0)) {
throw Error('cannot append signature');
}
const authInfo = new AuthInfo([], new Fee(0, new Coins()));
simTx = new Tx(tx.body, authInfo, []);
simTx.appendEmptySignatures(options.signers);
}

const simulateRes = await this.getReqFromChainID(chainID)
.post<SimulateResponse.Data>(`/cosmos/tx/v1beta1/simulate`, {
tx_bytes: this.encode(simTx, this.lcd.config[chainID].isClassic),
})
.then(d => SimulateResponse.fromData(d));

simulateRes.gas_info.gas_used = new Dec(gasAdjustment)
.mul(simulateRes.gas_info.gas_used)
.toNumber();

return simulateRes;
}

public async computeTax(): Promise<Coins> {
throw new Error('Tax was removed from network');
}
Expand Down

0 comments on commit eeaf01b

Please sign in to comment.