From 1433e6b62e1fd75cd5477132aa59f3a764d9004a Mon Sep 17 00:00:00 2001 From: khaylebfortune <111098422+khaylebfortune@users.noreply.github.com> Date: Sat, 18 Jul 2026 07:31:47 +0000 Subject: [PATCH] fix: correct toContractAmount multiplier from 100 to 10,000,000 stroops The creditline client's toContractAmount() used a 2-decimal multiplier (100) instead of the 7-decimal stroop multiplier (10,000,000) used by the entire codebase, causing loan amounts in create_loan XDR to be 100,000x too small. - Change multiplier from 100 to 10_000_000 in toContractAmount() - Add unit test with 6 cases covering ,000, , /bin/bash.50, /bin/bash.01, rounding behavior, and zero Closes #61 --- .../contracts/clients/creditline.client.ts | 2 +- .../clients/creditline.client.spec.ts | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 test/unit/stellar/contracts/clients/creditline.client.spec.ts diff --git a/src/stellar/contracts/clients/creditline.client.ts b/src/stellar/contracts/clients/creditline.client.ts index ddd231d..f8df78b 100644 --- a/src/stellar/contracts/clients/creditline.client.ts +++ b/src/stellar/contracts/clients/creditline.client.ts @@ -109,6 +109,6 @@ export class CreditLineContractClient { } private toContractAmount(value: number): bigint { - return BigInt(Math.round(value * 100)); + return BigInt(Math.round(value * 10_000_000)); } } diff --git a/test/unit/stellar/contracts/clients/creditline.client.spec.ts b/test/unit/stellar/contracts/clients/creditline.client.spec.ts new file mode 100644 index 0000000..f776cc3 --- /dev/null +++ b/test/unit/stellar/contracts/clients/creditline.client.spec.ts @@ -0,0 +1,67 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ConfigService } from '@nestjs/config'; +import { CreditLineContractClient } from '../../../../../src/stellar/contracts/clients/creditline.client'; +import { SorobanService } from '../../../../../src/blockchain/soroban/soroban.service'; +import { CREDIT_LINE_CONTRACT_ID_KEY } from '../../../../../src/stellar/contracts/interfaces/creditline.interface'; + +describe('CreditLineContractClient', () => { + let client: CreditLineContractClient; + + const mockSorobanService = { + getServer: jest.fn(), + getNetworkPassphrase: jest.fn().mockReturnValue('Test SDF Network ; September 2015'), + }; + + const mockConfigService = { + get: jest.fn((key: string) => { + if (key === CREDIT_LINE_CONTRACT_ID_KEY || key === 'CREDITLINE_CONTRACT_ID') { + return 'CDLZFC3SYJYDZT7K3VJ4STDQ2G6FJFY5ODV2S4W3C5KQ5Y2V3K4X5Y6Z'; + } + return undefined; + }), + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + CreditLineContractClient, + { provide: SorobanService, useValue: mockSorobanService }, + { provide: ConfigService, useValue: mockConfigService }, + ], + }).compile(); + + client = module.get(CreditLineContractClient); + }); + + describe('toContractAmount', () => { + it('converts $1,000.00 to 10,000,000,000 stroops', () => { + const result = (client as any).toContractAmount(1000); + expect(result).toBe(10_000_000_000n); + }); + + it('converts $0.00 to 0 stroops', () => { + const result = (client as any).toContractAmount(0); + expect(result).toBe(0n); + }); + + it('converts $1.00 to 10,000,000 stroops', () => { + const result = (client as any).toContractAmount(1); + expect(result).toBe(10_000_000n); + }); + + it('converts $0.50 to 5,000,000 stroops', () => { + const result = (client as any).toContractAmount(0.5); + expect(result).toBe(5_000_000n); + }); + + it('converts $0.01 to 100,000 stroops', () => { + const result = (client as any).toContractAmount(0.01); + expect(result).toBe(100_000n); + }); + + it('rounds to nearest stroop', () => { + const result = (client as any).toContractAmount(0.12345678); + expect(result).toBe(1_234_568n); + }); + }); +});