Skip to content

Commit

Permalink
feat: add check for sender account balance
Browse files Browse the repository at this point in the history
  • Loading branch information
kieranroneill committed May 7, 2024
1 parent ec62c7b commit 904096e
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 22 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"typescript-transform-paths": "^3.4.7"
},
"dependencies": {
"bignumber.js": "^9.1.2",
"bn.js": "^5.2.1",
"chalk": "^4.1.2",
"commander": "^12.0.0",
Expand Down
16 changes: 14 additions & 2 deletions src/action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { localnet } from '@app/configs';
import { ExitCodeEnum } from '@app/enums';

// helpers
import convertNearToYoctoNear from '@test/utils/convertNearToYoctoNear';
import createTestAccount from '@test/utils/createTestAccount';
import deployToken from '@test/utils/deployToken';

// types
import type { IActionResponse, IActionOptions, TNetworkIDs } from '@app/types';

// utils
import convertNEARToYoctoNEAR from '@app/utils/convertNEARToYoctoNEAR';
import createLogger from '@app/utils/createLogger';
import createNearConnection from '@app/utils/createNearConnection';

Expand Down Expand Up @@ -61,7 +61,7 @@ describe('when running the cli action', () => {
// create the token account
tokenAccount = await createTestAccount({
creatorAccount,
initialBalanceInAtomicUnits: convertNearToYoctoNear(new BN('10')),
initialBalanceInAtomicUnits: new BN(convertNEARToYoctoNEAR('10')),
newAccountID: tokenAccountID,
newAccountPublicKey: tokenPublicKey,
nearConnection,
Expand Down Expand Up @@ -168,6 +168,18 @@ describe('when running the cli action', () => {
expect(response.exitCode).toBe(ExitCodeEnum.FileReadError);
});

it('should fail if there is not enough funds in the account', async () => {
// arrange
// act
const response: IActionResponse = await action({
...defaultOptions,
accountId: account1AccountID,
});

// assert
expect(response.exitCode).toBe(ExitCodeEnum.InsufficientFundsError);
});

it('should record failed transfers', async () => {
// arrange
// act
Expand Down
30 changes: 29 additions & 1 deletion src/action.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import BN from 'bn.js';
import { Account, Contract, Near } from 'near-api-js';
import { PublicKey } from 'near-api-js/lib/utils';
import type { AccountBalance } from 'near-api-js/lib/account';
import type { PublicKey } from 'near-api-js/lib/utils';
import { existsSync } from 'node:fs';
import { readFile } from 'node:fs/promises';
import { extname } from 'node:path';

// configs
import { localnet, mainnet, testnet } from '@app/configs';

// constants
import {
GAS_FEE_IN_ATOMIC_UNITS,
STORAGE_FEE_IN_ATOMIC_UNITS,
} from '@app/constants';

// enums
import { ExitCodeEnum } from '@app/enums';

Expand All @@ -22,6 +29,7 @@ import type {

// utils
import accountAccessKey from '@app/utils/accountAccessKey';
import convertYoctoNEARToNEAR from '@app/utils/convertYoctoNEARToNEAR';
import createNearConnection from '@app/utils/createNearConnection';
import transferToAccount from '@app/utils/transferToAccount';
import validateAccountID from '@app/utils/validateAccountID';
Expand All @@ -38,12 +46,14 @@ export default async function action({
}: IActionOptions): Promise<IActionResponse> {
const completedTransfers: Record<string, string> = {};
const failedTransfers: Record<string, string> = {};
let accountBalance: AccountBalance;
let configuration: IConfiguration;
let contract: ITokenContract;
let nearConnection: Near;
let signer: Account;
let signerAccessKey: IAccessKeyResponse;
let signerPublicKey: PublicKey | null;
let totalFeesInAtomicUnits: BN;
let transactionID: string | null;
let transfers: Record<string, string>;

Expand Down Expand Up @@ -148,6 +158,24 @@ export default async function action({
};
}

accountBalance = await signer.getAccountBalance();
totalFeesInAtomicUnits = new BN(GAS_FEE_IN_ATOMIC_UNITS)
.add(new BN(STORAGE_FEE_IN_ATOMIC_UNITS))
.mul(new BN(Object.entries(transfers).length));

// if the signer does not have funds tio cover the fees, error
if (totalFeesInAtomicUnits.gt(new BN(accountBalance.available))) {
logger.error(
`there are insufficient funds in account "${signer.accountId}" to cover the fees, you need at least "${convertYoctoNEARToNEAR(totalFeesInAtomicUnits.toString())}", you have "${convertYoctoNEARToNEAR(accountBalance.available)}" available`
);

return {
completedTransfers,
exitCode: ExitCodeEnum.InsufficientFundsError,
failedTransfers,
};
}

logger.info(
`starting transfers for ${Object.entries(transfers).length} accounts`
);
Expand Down
2 changes: 1 addition & 1 deletion src/constants/Fees.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const GAS_FEE_IN_ATOMIC_UNITS = '30000000000000';
export const STORAGE_FEE_IN_STANDARD_UNITS = '0.00125';
export const STORAGE_FEE_IN_ATOMIC_UNITS = '1250000000000000000000';
1 change: 1 addition & 0 deletions src/enums/ExitCodeEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum ExitCodeEnum {
DirectoryWriteError,
FileReadError,
FileWriteError,
InsufficientFundsError,
}

export default ExitCodeEnum;
33 changes: 33 additions & 0 deletions src/utils/convertNEARToYoctoNEAR/convertNEARToYoctoNEAR.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// utils
import convertNEARToYoctoNEAR from './convertNEARToYoctoNEAR';

interface ITestParams {
expected: string;
standardUnit: string;
}

describe('convertNEARToYoctoNEAR()', () => {
it.each([
{
standardUnit: '0.00000000000001',
expected: '10000000000',
},
{
standardUnit: '1.000000000000001',
expected: '1000000000000001000000000',
},
{
standardUnit: '3.2',
expected: '3200000000000000000000000',
},
{
standardUnit: '3.200000000000000001',
expected: '3200000000000000001000000',
},
])(
`should convert the near unit of "$standardUnit" to yoctonear unit of "$expected"`,
({ expected, standardUnit }: ITestParams) => {
expect(convertNEARToYoctoNEAR(standardUnit)).toBe(expected);
}
);
});
17 changes: 17 additions & 0 deletions src/utils/convertNEARToYoctoNEAR/convertNEARToYoctoNEAR.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import BigNumber from 'bignumber.js';

Check failure on line 1 in src/utils/convertNEARToYoctoNEAR/convertNEARToYoctoNEAR.ts

View workflow job for this annotation

GitHub Actions / Build Package

Cannot find module 'bignumber.js' or its corresponding type declarations.
import { utils } from 'near-api-js';

/**
* Convenience function that converts a NEAR amount (standard unit) to the yoctoNEAR amount (atomic unit).
* @param {string} standardAmount - the NEAR amount to convert.
* @returns {string} the yoctoNEAR amount.
*/
export default function convertNEARToYoctoNEAR(standardAmount: string): string {
BigNumber.config({
ROUNDING_MODE: 0,
});

return new BigNumber(standardAmount)
.multipliedBy(new BigNumber('10').pow(utils.format.NEAR_NOMINATION_EXP))
.toFixed();
}
1 change: 1 addition & 0 deletions src/utils/convertNEARToYoctoNEAR/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './convertNEARToYoctoNEAR';
33 changes: 33 additions & 0 deletions src/utils/convertYoctoNEARToNEAR/convertYoctoNEARToNEAR.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// utils
import convertYoctoNEARToNEAR from './convertYoctoNEARToNEAR';

interface ITestParams {
atomicUnit: string;
expected: string;
}

describe('convertYoctoNEARToNEARtest()', () => {
it.each([
{
atomicUnit: '10000',
expected: '0.00000000000000000001',
},
{
atomicUnit: '1000000000000000000001000',
expected: '1.00000000000000000001',
},
{
atomicUnit: '3200000000000000000000000',
expected: '3.2',
},
{
atomicUnit: '3200000000000000000000001',
expected: '3.20000000000000000001',
},
])(
`should convert the yoctonear unit of "$atomicUnit" to near unit of "$expected"`,
({ atomicUnit, expected }: ITestParams) => {
expect(convertYoctoNEARToNEAR(atomicUnit)).toBe(expected);
}
);
});
17 changes: 17 additions & 0 deletions src/utils/convertYoctoNEARToNEAR/convertYoctoNEARToNEAR.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import BigNumber from 'bignumber.js';

Check failure on line 1 in src/utils/convertYoctoNEARToNEAR/convertYoctoNEARToNEAR.ts

View workflow job for this annotation

GitHub Actions / Build Package

Cannot find module 'bignumber.js' or its corresponding type declarations.
import { utils } from 'near-api-js';

/**
* Convenience function that converts a yoctoNEAR amount (atomic unit) to the NEAR amount (standard unit).
* @param {BigNumber} atomicAmount - the yoctoNEAR amount to convert.
* @returns {BigNumber} the NEAR amount.
*/
export default function convertYoctoNEARToNEAR(atomicAmount: string): string {
BigNumber.config({
ROUNDING_MODE: 0,
});

return new BigNumber(atomicAmount)
.dividedBy(new BigNumber(10).pow(utils.format.NEAR_NOMINATION_EXP))
.toFixed();
}
1 change: 1 addition & 0 deletions src/utils/convertYoctoNEARToNEAR/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './convertYoctoNEARToNEAR';
6 changes: 2 additions & 4 deletions src/utils/transferToAccount/transferToAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
GAS_FEE_IN_ATOMIC_UNITS,
MAX_RETRIES,
RETRY_DELAY_IN_MILLISECONDS,
STORAGE_FEE_IN_STANDARD_UNITS,
STORAGE_FEE_IN_ATOMIC_UNITS,
} from '@app/constants';

// types
Expand Down Expand Up @@ -54,9 +54,7 @@ export default async function transferToAccount({
registration_only: true,
},
gasFee,
new BN(
utils.format.parseNearAmount(STORAGE_FEE_IN_STANDARD_UNITS)!
)
new BN(STORAGE_FEE_IN_ATOMIC_UNITS!)
)
);
}
Expand Down
13 changes: 0 additions & 13 deletions test/helpers/convertNearToYoctoNear/convertNearToYoctoNear.ts

This file was deleted.

1 change: 0 additions & 1 deletion test/helpers/convertNearToYoctoNear/index.ts

This file was deleted.

5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3953,6 +3953,11 @@ big.js@^5.2.2:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==

bignumber.js@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==

bin-links@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.4.tgz#c3565832b8e287c85f109a02a17027d152a58a63"
Expand Down

0 comments on commit 904096e

Please sign in to comment.