Skip to content

Commit dde5f1c

Browse files
authored
Update balance precheck to handle large values (#329)
* Update balance precheck to handle large values Signed-off-by: Nana-EC <[email protected]>
1 parent 3461308 commit dde5f1c

File tree

3 files changed

+94
-5
lines changed

3 files changed

+94
-5
lines changed

packages/relay/src/lib/clients/sdkClient.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ export class SDKClient {
120120
.setAccountId(AccountId.fromString(account)), this.clientMain, callerName);
121121
}
122122

123+
async getAccountBalanceInTinyBar(account: string, callerName: string): Promise<BigNumber> {
124+
const balance = await this.getAccountBalance(account, callerName);
125+
return balance.hbars.to(HbarUnit.Tinybar);
126+
}
127+
123128
async getAccountBalanceInWeiBar(account: string, callerName: string): Promise<BigNumber> {
124129
const balance = await this.getAccountBalance(account, callerName);
125130
return SDKClient.HbarToWeiBar(balance);

packages/relay/src/lib/precheck.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { predefined } from './errors';
2323
import { MirrorNodeClient, SDKClient } from './clients';
2424
import {EthImpl} from "./eth";
2525
import {Logger} from "pino";
26+
import constants from './constants';
2627

2728
export class Precheck {
2829
private mirrorNodeClient: MirrorNodeClient;
@@ -107,12 +108,12 @@ export class Precheck {
107108

108109
try {
109110
const { account }: any = await this.mirrorNodeClient.getAccount(tx.from!);
110-
const accountBalance = await this.sdkClient.getAccountBalanceInWeiBar(account, callerName);
111+
const tinybars = await this.sdkClient.getAccountBalanceInTinyBar(account, callerName);
111112

112-
result.passes = ethers.ethers.BigNumber.from(accountBalance.toString()).gte(txTotalValue);
113+
result.passes = ethers.ethers.BigNumber.from(tinybars.toString()).mul(constants.TINYBAR_TO_WEIBAR_COEF).gte(txTotalValue);
113114

114115
if (!result.passes) {
115-
this.logger.trace('Failed balance precheck for sendRawTransaction(transaction=%s, totalValue=%s, accountBalance=%s)', transaction, txTotalValue, accountBalance);
116+
this.logger.trace('Failed balance precheck for sendRawTransaction(transaction=%s, totalValue=%s, accountTinyBarBalance=%s)', transaction, txTotalValue, tinybars);
116117
}
117118
} catch (error: any) {
118119
this.logger.trace('Error on balance precheck for sendRawTransaction(transaction=%s, totalValue=%s, error=%s)', transaction, txTotalValue, error.message);

packages/relay/tests/lib/precheck.spec.ts

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import { expect } from 'chai';
2222
import { Registry } from 'prom-client';
23+
import { BigNumber } from 'ethers';
24+
import { Hbar, HbarUnit } from '@hashgraph/sdk';
2325
const registry = new Registry();
2426

2527
import sinon from 'sinon';
@@ -29,13 +31,15 @@ import {MirrorNodeClient, SDKClient} from "../../src/lib/clients";
2931
import axios from "axios";
3032
import MockAdapter from "axios-mock-adapter";
3133
import constants from '../../src/lib/constants';
34+
import { predefined } from './../../src/lib/errors';
3235
const logger = pino();
3336

3437
describe('Precheck', async function() {
3538

3639
const txWithMatchingChainId = '0x02f87482012a0485a7a358200085a7a3582000832dc6c09400000000000000000000000000000000000003f78502540be40080c001a006f4cd8e6f84b76a05a5c1542a08682c928108ef7163d9c1bf1f3b636b1cd1fba032097cbf2dda17a2dcc40f62c97964d9d930cdce2e8a9df9a8ba023cda28e4ad';
3740
const txWithNonMatchingChainId = '0xf86a0385a7a3582000832dc6c09400000000000000000000000000000000000003f78502540be400801ca06750e92db52fa708e27f94f27e0cfb7f5800f9b657180bb2e94c1520cfb1fb6da01bec6045068b6db38b55017bb8b50166699384bc1791fd8331febab0cf629a2a';
3841
const defaultGasPrice = 720_000_000_000;
42+
let sdkInstance;
3943

4044
let precheck: Precheck;
4145
let mock: MockAdapter;
@@ -56,10 +60,15 @@ describe('Precheck', async function() {
5660

5761
// @ts-ignore
5862
const mirrorNodeInstance = new MirrorNodeClient(process.env.MIRROR_NODE_URL, logger.child({ name: `mirror-node` }), registry, instance);
59-
const sdkInstance = sinon.createStubInstance(SDKClient);
63+
sdkInstance = sinon.createStubInstance(SDKClient);
6064
precheck = new Precheck(mirrorNodeInstance, sdkInstance, logger, '0x12a');
6165
});
6266

67+
this.beforeEach(() => {
68+
// reset mock
69+
mock.reset();
70+
});
71+
6372
describe('chainId', async function() {
6473
it('should return true for matching chainId', async function() {
6574
const result = precheck.chainId(txWithMatchingChainId);
@@ -96,5 +105,79 @@ describe('Precheck', async function() {
96105
expect(result.error).to.exist;
97106
expect(result.passes).to.eq(false);
98107
});
99-
})
108+
});
109+
110+
describe('balance', async function() {
111+
// sending 2 hbars
112+
const transaction = '0x02f876820128078459682f0086018a4c7747008252089443cb701defe8fc6ed04d7bddf949618e3c575fe1881bc16d674ec8000080c001a0b8c604e08c15a7acc8c898a1bbcc41befcd0d120b64041d1086381c7fc2a5339a062eabec286592a7283c90ce90d97f9f8cf9f6c0cef4998022660e7573c046a46';
113+
const mirrorAccountsPath = 'accounts/0xF8A44f9a4E4c452D25F5aE0F5d7970Ac9522a3C8';
114+
const accountId = '0.1.2';
115+
116+
it('should return false for 1 hbar', async function() {
117+
mock.onGet(mirrorAccountsPath).reply(200, {
118+
account: accountId
119+
});
120+
121+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(1, HbarUnit.Hbar).to(HbarUnit.Tinybar));
122+
const result = await precheck.balance(transaction, 'sendRawTransaction');
123+
expect(result).to.exist;
124+
expect(result.error.message).to.eq(predefined.INSUFFICIENT_ACCOUNT_BALANCE.message);
125+
expect(result.passes).to.eq(false);
126+
});
127+
128+
it('should return true for 10 hbar', async function() {
129+
mock.onGet(mirrorAccountsPath).reply(200, {
130+
account: accountId
131+
});
132+
133+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(10, HbarUnit.Hbar).to(HbarUnit.Tinybar));
134+
const result = await precheck.balance(transaction, 'sendRawTransaction');
135+
expect(result).to.exist;
136+
expect(result.passes).to.eq(true);
137+
});
138+
139+
it('should return true for 100 hbar', async function() {
140+
mock.onGet(mirrorAccountsPath).reply(200, {
141+
account: accountId
142+
});
143+
144+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(100, HbarUnit.Hbar).to(HbarUnit.Tinybar));
145+
const result = await precheck.balance(transaction, 'sendRawTransaction');
146+
expect(result).to.exist;
147+
expect(result.passes).to.eq(true);
148+
});
149+
150+
it('should return true for 10000 hbar', async function() {
151+
mock.onGet(mirrorAccountsPath).reply(200, {
152+
account: accountId
153+
});
154+
155+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(10_000, HbarUnit.Hbar).to(HbarUnit.Tinybar));
156+
const result = await precheck.balance(transaction, 'sendRawTransaction');
157+
expect(result).to.exist;
158+
expect(result.passes).to.eq(true);
159+
});
160+
161+
it('should return true for 100000 hbar', async function() {
162+
mock.onGet(mirrorAccountsPath).reply(200, {
163+
account: accountId
164+
});
165+
166+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(100_000, HbarUnit.Hbar).to(HbarUnit.Tinybar));
167+
const result = await precheck.balance(transaction, 'sendRawTransaction');
168+
expect(result).to.exist;
169+
expect(result.passes).to.eq(true);
170+
});
171+
172+
it('should return true for 50_000_000_000 hbar', async function() {
173+
mock.onGet(mirrorAccountsPath).reply(200, {
174+
account: accountId
175+
});
176+
177+
sdkInstance.getAccountBalanceInTinyBar.returns(Hbar.from(50_000_000_000, HbarUnit.Hbar).to(HbarUnit.Tinybar));
178+
const result = await precheck.balance(transaction, 'sendRawTransaction');
179+
expect(result).to.exist;
180+
expect(result.passes).to.eq(true);
181+
});
182+
});
100183
});

0 commit comments

Comments
 (0)