From fff94d907157d0cd4f6e490c450cdc58cefeec31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferenc=20S=C3=A1rai?= Date: Thu, 5 Mar 2026 10:28:29 +0100 Subject: [PATCH] fix(rpc): ensure 0x prefix for recipient in sendBzzTransaction and add tests (#722) * fix(rpc): ensure 0x prefixed recipient in sendBzzTransaction and add tests * fix(tests): move rpc spec to tests/unit after rebase to master --- src/utils/rpc.ts | 2 +- tests/unit/rpc.spec.ts | 71 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/unit/rpc.spec.ts diff --git a/src/utils/rpc.ts b/src/utils/rpc.ts index 8afdff6..67ee665 100644 --- a/src/utils/rpc.ts +++ b/src/utils/rpc.ts @@ -117,7 +117,7 @@ export async function sendBzzTransaction( const feeData = await signer.provider.getFeeData() const gasPrice = feeData.gasPrice || BigInt(0) const bzz = new Contract(BZZ_TOKEN_ADDRESS, bzzABI, signer) - const transaction = await bzz.transfer(to, value, { gasPrice }) + const transaction = await bzz.transfer(to.toChecksum(), value, { gasPrice }) const receipt = await transaction.wait(1) if (!receipt) { diff --git a/tests/unit/rpc.spec.ts b/tests/unit/rpc.spec.ts new file mode 100644 index 0000000..4adba10 --- /dev/null +++ b/tests/unit/rpc.spec.ts @@ -0,0 +1,71 @@ +import { BZZ } from '@ethersphere/bee-js' + +import { sendBzzTransaction } from '../../src/utils/rpc' + +interface MockProvider { + getFeeData: jest.Mock + getNetwork: jest.Mock +} + +const mockWait = jest.fn() +const mockTransfer = jest.fn() +const mockGetFeeData = jest.fn() +const mockGetNetwork = jest.fn() +const mockProvider: MockProvider = { + getFeeData: mockGetFeeData, + getNetwork: mockGetNetwork, +} + +const value = BZZ.fromDecimalString('1') +const privateKey = 'FFFF000000000000000000000000000000000000000000000000000000000000' +const jsonRpcProvider = 'http://mock-json-rpc-provider' + +jest.mock('../../src/utils/chain', () => { + const actual = jest.requireActual('../../src/utils/chain') + + return { + ...actual, + newGnosisProvider: jest.fn(() => mockProvider), + } +}) + +jest.mock('ethers', () => { + const actual = jest.requireActual('ethers') + + class Contract { + transfer = mockTransfer + balanceOf = { staticCall: jest.fn() } + } + + class Wallet { + provider: MockProvider + + constructor(_privateKey: string, provider: MockProvider) { + this.provider = provider + } + } + + return { + ...actual, + Contract, + Wallet, + } +}) + +describe('sendBzzTransaction', () => { + const addresses = ['52908400098527886e0f7030069857d2e4169ee7', '0x52908400098527886e0f7030069857d2e4169ee7'] + + beforeEach(() => { + jest.clearAllMocks() + mockWait.mockResolvedValue({ status: 1 }) + mockTransfer.mockResolvedValue({ wait: mockWait }) + mockGetFeeData.mockResolvedValue({ gasPrice: BigInt(1) }) + mockGetNetwork.mockResolvedValue({ chainId: BigInt(100) }) + }) + + it.each(addresses)('sendBzzTransaction to address: %s', async (address: string) => { + await sendBzzTransaction(privateKey, address, value, jsonRpcProvider) + const to = mockTransfer.mock.calls[0][0] as string + expect(to.startsWith('0x')).toBe(true) + }) +})