diff --git a/common/changes/@cityofzion/bs-swap/CU-86a6647tx_2025-01-14-19-54.json b/common/changes/@cityofzion/bs-swap/CU-86a6647tx_2025-01-14-19-54.json new file mode 100644 index 0000000..4657e5d --- /dev/null +++ b/common/changes/@cityofzion/bs-swap/CU-86a6647tx_2025-01-14-19-54.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@cityofzion/bs-swap", + "comment": "Add round up to min and apply decimals correctly", + "type": "patch" + } + ], + "packageName": "@cityofzion/bs-swap" +} \ No newline at end of file diff --git a/packages/bs-swap/src/__tests__/SimpleSwapApi.spec.ts b/packages/bs-swap/src/__tests__/SimpleSwapApi.spec.ts index 5e52bf8..079deef 100644 --- a/packages/bs-swap/src/__tests__/SimpleSwapApi.spec.ts +++ b/packages/bs-swap/src/__tests__/SimpleSwapApi.spec.ts @@ -12,7 +12,7 @@ describe('SimpleSwapApi', () => { name: 'Gas', imageUrl: 'https://static.simpleswap.io/images/currencies-logo/gasn3.svg', hash: '0xd2a4cff31913016155e38e474a2c06d08be276cf', - decimals: undefined, + decimals: 8, hasExtraId: false, validationExtra: null, validationAddress: '^(N)[A-Za-z0-9]{33}$', diff --git a/packages/bs-swap/src/__tests__/SimpleSwapService.spec.ts b/packages/bs-swap/src/__tests__/SimpleSwapService.spec.ts index 1303782..6ead6d1 100644 --- a/packages/bs-swap/src/__tests__/SimpleSwapService.spec.ts +++ b/packages/bs-swap/src/__tests__/SimpleSwapService.spec.ts @@ -323,6 +323,49 @@ describe('SimpleSwapService', () => { expect(amountToUseMinMax).toEqual({ loading: false, value: expect.objectContaining({ min: expect.any(String) }) }) }, 10000) + it('Should be able to set the correct min and max amount with Gas (8 decimals)', async () => { + await simpleSwapService.init() + + const gasToken = availableTokensToUse.value!.find(({ id }) => id === 'gasn3:neo3')! + + await simpleSwapService.setTokenToUse(gasToken) + + const account = blockchainServicesByName.neo3.generateAccountFromKey(process.env.TEST_PRIVATE_KEY) + + await simpleSwapService.setAccountToUse(account) + + await simpleSwapService.setTokenToReceive(availableTokensToReceive.value![0]) + + const min = amountToUseMinMax.value!.min + + expect(amountToUseMinMax).toEqual({ + loading: false, + value: expect.objectContaining({ min: expect.any(String), max: null }), + }) + expect(min).toContain('.') + expect(min.split('.').at(1)!.length).toBe(8) + }, 10000) + + it('Should be able to set the correct min and max amount with Neo (0 decimals)', async () => { + await simpleSwapService.init() + + const neoToken = availableTokensToUse.value!.find(({ id }) => id === 'neo3:neo3')! + + await simpleSwapService.setTokenToUse(neoToken) + + const account = blockchainServicesByName.neo3.generateAccountFromKey(process.env.TEST_PRIVATE_KEY) + + await simpleSwapService.setAccountToUse(account) + + await simpleSwapService.setTokenToReceive(availableTokensToReceive.value![0]) + + expect(amountToUseMinMax).toEqual({ + loading: false, + value: expect.objectContaining({ min: expect.any(String), max: null }), + }) + expect(amountToUseMinMax.value!.min).not.toContain('.') + }, 10000) + it('Should be able to set an invalid address', async () => { await simpleSwapService.init() const tokenUse = availableTokensToUse.value![0] diff --git a/packages/bs-swap/src/services/SimpleSwapService.ts b/packages/bs-swap/src/services/SimpleSwapService.ts index 4e6d615..3dff3a3 100644 --- a/packages/bs-swap/src/services/SimpleSwapService.ts +++ b/packages/bs-swap/src/services/SimpleSwapService.ts @@ -240,17 +240,18 @@ export class SimpleSwapService implements SwapSe let range: SwapServiceMinMaxAmount | null = this.#amountToUseMinMax.value try { if ((shouldRecalculateAmountToUseMinMax || range === null) && this.#tokenToReceive.value) { - const apiRange = await this.#api.getRange(this.#tokenToUse.value, this.#tokenToReceive.value) + const { decimals } = this.#tokenToUse.value + const rangeResponse = await this.#api.getRange(this.#tokenToUse.value, this.#tokenToReceive.value) - // Add 1% because the SimpleSwap sends us a smaller minimum - const rangeMin = (+apiRange.min * 1.01).toString() + // Add 1% because the SimpleSwap sends us a smaller minimum than the required + const minWithOnePercent = formatNumber((Number(rangeResponse.min) * 1.01).toString(), decimals) + + // Add the smallest number to round up because the SimpleSwap doesn't have the decimals, and we need to apply the decimals here + const smallestNumberToRoundUp = decimals ? `0.${'1'.padStart(decimals, '0')}` : '1' range = { - min: this.#tokenToUse.value.decimals ? formatNumber(rangeMin, this.#tokenToUse.value.decimals) : rangeMin, - max: - this.#tokenToUse.value.decimals && apiRange.max - ? formatNumber(apiRange.max, this.#tokenToUse.value.decimals) - : apiRange.max, + min: (Number(minWithOnePercent) + Number(smallestNumberToRoundUp)).toString(), + max: rangeResponse.max ? formatNumber(rangeResponse.max, decimals) : rangeResponse.max, } } @@ -258,9 +259,7 @@ export class SimpleSwapService implements SwapSe if (shouldRecalculateAmountToUse && range) { this.#amountToUse = { - value: this.#tokenToUse.value.decimals - ? formatNumber(range.min, this.#tokenToUse.value.decimals) - : range.min, + value: range.min ? formatNumber(range.min, this.#tokenToUse.value.decimals) : range.min, } } } catch (error: any) { @@ -361,8 +360,7 @@ export class SimpleSwapService implements SwapSe async setAmountToUse(amount: string | null): Promise { this.#amountToUse = { - value: - this.#tokenToUse.value?.decimals && amount ? formatNumber(amount, this.#tokenToUse.value.decimals) : amount, + value: this.#tokenToUse.value && amount ? formatNumber(amount, this.#tokenToUse.value.decimals) : amount, } debounce(this.#recalculateValues.bind(this), 1000)(['amountToReceive'])