Skip to content

Task 3-2: Integration Test - Token Transfer & Gas Estimation

Phase: 3 Priority: Medium Module: biconomy Depends on: task-1-1 Reference: docs/bountyhunter-blockchain-p2/details/feature-evm-integration/SPEC.md

Background

Luồng chuyển token (USER và ADMIN) và gas estimation chưa có integration test. Luồng USER type dùng BICONOMY_GASLESS_TOKEN queue trong khi ADMIN type kiểm tra số dư trước rồi đẩy vào ADMIN_TRANSFER_MONEY queue. Gas estimation trả về totalGasFee đồng bộ mà không cần queue. Cần đảm bảo các nhánh phân kỳ này hoạt động đúng và xử lý edge case số dư không đủ.

Tasks

Note: Mock ethers.js provider calls (getBalance, estimateGas) để tránh gọi RPC thật. Mock postWithRetry để capture webhook calls. Test USER vs ADMIN flow cần kiểm tra đúng queue name được sử dụng (BICONOMY_GASLESS_TOKEN vs ADMIN_TRANSFER_MONEY).

  • [ ] Test case 1 — USER type token transfer → BICONOMY_GASLESS_TOKEN queue:
    it('POST /biconomy/transfer-money with type=USER → pushed to BICONOMY_GASLESS_TOKEN queue', async () => {
      const res = await request(app.getHttpServer())
        .post('/biconomy/transfer-money')
        .send({ type: 'USER', amount: '100', ...userPayload });
    
      expect(res.status).toBe(201);
      const jobs = await gaslessTokenQueue.getJobs(['waiting', 'active']);
      expect(jobs).toHaveLength(1);
    });
    
  • [ ] Test case 2 — ADMIN type → balance check → ADMIN_TRANSFER_MONEY queue:
  • Mock balance đủ → job vào ADMIN_TRANSFER_MONEY
  • Mock balance không đủ → trả về INSUFFICIENT_BALANCE error
  • [ ] Test case 3 — Gas estimation:
    it('POST /biconomy/estimate-gas-transaction → returns totalGasFee', async () => {
      mockProvider.estimateGas.mockResolvedValue(BigNumber.from('21000'));
      mockProvider.getGasPrice.mockResolvedValue(BigNumber.from('5000000000'));
    
      const res = await request(app.getHttpServer())
        .post('/biconomy/estimate-gas-transaction')
        .send(validEstimatePayload);
    
      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('totalGasFee');
      expect(typeof res.body.totalGasFee).toBe('string');
    });
    
  • [ ] Test case 4 — Insufficient balance (INSUFFICIENT_BALANCE error):
    it('ADMIN transfer with insufficient balance → INSUFFICIENT_BALANCE error', async () => {
      mockGetBalance.mockResolvedValue(BigNumber.from('0'));
    
      const res = await request(app.getHttpServer())
        .post('/biconomy/transfer-money')
        .send({ type: 'ADMIN', amount: '1000', ...adminPayload });
    
      expect(res.body.code).toBe('INSUFFICIENT_BALANCE');
    });
    
  • [ ] Test case 5 — Processor hoàn thành token transfer → webhook callback với txHash

Verification / Acceptance Criteria

  • [ ] USER type → job trong BICONOMY_GASLESS_TOKEN queue (không phải ADMIN_TRANSFER_MONEY)
  • [ ] ADMIN type với balance đủ → job trong ADMIN_TRANSFER_MONEY queue
  • [ ] ADMIN type với balance 0 → response code INSUFFICIENT_BALANCE, không có job trong queue
  • [ ] Gas estimation trả về totalGasFee dạng string (không phải BigNumber object)
  • [ ] Tất cả test pass khi chạy npm run test
  • [ ] Không có lời gọi RPC thật (fully mocked)

Files to Modify

  • src/biconomy/tests/biconomy-token.integration.spec.ts (tạo mới)