Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: impr ffee #2738

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/swap/src/helpers/orders/getBuyAmount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export const getBuyAmount = (
return {
tokenId,
quantity: asQuantity(
BigNumber(sell.quantity)
.dividedToIntegerBy(BigNumber(limit))
new BigNumber(sell.quantity)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From their docs, new is optional

x = new BigNumber(123.4567)                // '123.4567'
// 'new' is optional
y = BigNumber(x)                           // '123.4567'

But we can add them if you like them

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS complains after BN 9.1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, ok, I hadn't noticed anything but probably didn't do any install yet since 9.1 4 days ago

.dividedToIntegerBy(new BigNumber(limit))
.toString(),
),
}
Expand Down
387 changes: 387 additions & 0 deletions packages/swap/src/helpers/orders/getFrontendFee.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,387 @@
import {Balance} from '@yoroi/types'

import {getFrontendFee} from './getFrontendFee'
import {milkHoldersDiscountTiers} from '../../translators/constants'
import {Quantities} from '../../utils/quantities'
import {asQuantity} from '../../utils/asQuantity'

describe('getFrontendFee', () => {
const primaryTokenInfo: Balance.TokenInfo = {
id: '',
decimals: 6,
description: 'primary',
fingerprint: '',
image: '',
group: '',
icon: '',
kind: 'ft',
name: 'ttADA',
symbol: 'ttADA',
ticker: 'ttADA',
metadatas: {},
}

const notPrimaryTokenAmount: Balance.Amount = {
tokenId: 'not.primary.token',
quantity: '99',
}

describe('selling side is primary token', () => {
it('< 100 and whatever milk in balance', () => {
// arrange
const sellAmount: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_999_999),
}
// act
const fee = getFrontendFee({
sellAmount: sellAmount,
buyAmount: notPrimaryTokenAmount,
sellInPrimaryTokenValue: sellAmount,
milkBalance: '999999999999999999',
buyInPrimaryTokenValue: sellAmount,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: Quantities.zero,
})
})

it('>= 100 and milk in balance = 0', () => {
// arrange
const sellPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: sellPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
sellInPrimaryTokenValue: sellPrimaryAmountOver99,
milkBalance: Quantities.zero,
buyInPrimaryTokenValue: sellPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_050_000), // no milk, 100 ADA * 0.05% + 1 = 1.05 ADA
})
})

it('>= 100 and milk in balance >= 100', () => {
// arrange
const sellPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: sellPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
milkBalance: '499',
sellInPrimaryTokenValue: sellPrimaryAmountOver99,
buyInPrimaryTokenValue: sellPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_025_000), // hold 100-499 milk, 100 ADA * 0.025% + 1 = 1.025 ADA
})
})

it('>= 100 and milk in balance >= 500', () => {
// arrange
const sellPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: sellPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
milkBalance: '500',
sellInPrimaryTokenValue: sellPrimaryAmountOver99,
buyInPrimaryTokenValue: sellPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_020_000), // hold 500+ milk, 100 ADA * 0.020% + 1 = 1.02 ADA
})
})
})

describe('buying side is primary token', () => {
it('< 100 and whatever milk in balance', () => {
// arrange
const buyPrimaryTokenAmount: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_999_999),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryTokenAmount,
sellInPrimaryTokenValue: buyPrimaryTokenAmount,
milkBalance: '999999999999999999',
buyInPrimaryTokenValue: buyPrimaryTokenAmount,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: Quantities.zero,
})
})

it('>= 100 and milk in balance = 0', () => {
// arrange
const buyPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryAmountOver99,
sellInPrimaryTokenValue: buyPrimaryAmountOver99,
milkBalance: Quantities.zero,
buyInPrimaryTokenValue: buyPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_050_000), // no milk, 100 ADA * 0.05% + 1 = 1.05 ADA
})
})

it('>= 100 and milk in balance >= 100', () => {
// arrange
const buyPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryAmountOver99,
milkBalance: '499',
sellInPrimaryTokenValue: buyPrimaryAmountOver99,
buyInPrimaryTokenValue: buyPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_025_000), // hold 100-499 milk, 100 ADA * 0.025% + 1 = 1.025 ADA
})
})

it('>= 100 and milk in balance >= 500', () => {
// arrange
const buyPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryAmountOver99,
milkBalance: '500',
sellInPrimaryTokenValue: buyPrimaryAmountOver99,
buyInPrimaryTokenValue: buyPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_020_000), // hold 500+ milk, 100 ADA * 0.020% + 1= 1.02 ADA
})
})
})
it('should calc 0 fee if no tier', () => {
// arrange
const buyPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryAmountOver99,
milkBalance: '999999999999999',
sellInPrimaryTokenValue: buyPrimaryAmountOver99,
buyInPrimaryTokenValue: buyPrimaryAmountOver99,
primaryTokenInfo,
discountTiers: [],
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: Quantities.zero,
})
})

it('should fallback - coverage only', () => {
// arrange
const buyPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: notPrimaryTokenAmount,
buyAmount: buyPrimaryAmountOver99,
milkBalance: '999999999999999',
sellInPrimaryTokenValue: buyPrimaryAmountOver99,
buyInPrimaryTokenValue: buyPrimaryAmountOver99,
primaryTokenInfo,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: Quantities.zero,
})
})

// TODO: check with openswap
describe('neither sell nor buy are primary token, it should use the value in ADA (paired)', () => {
it('< 100 and whatever milk in balance', () => {
// arrange
const sellNotPrimaryAmount: Balance.Amount = {
tokenId: 'not.primary.token',
quantity: asQuantity(99_999_999),
}
const sellValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_999_999),
}
const buyValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_999_998),
}
// act
const fee = getFrontendFee({
sellAmount: sellNotPrimaryAmount,
buyAmount: notPrimaryTokenAmount,
sellInPrimaryTokenValue: sellValueInPrimaryToken,
milkBalance: '999999999999999999',
buyInPrimaryTokenValue: buyValueInPrimaryToken,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: Quantities.zero,
})
})

it('>= 100 and milk in balance = 0', () => {
// arrange
const sellNotPrimaryAmountOver99: Balance.Amount = {
tokenId: 'not.primary.token',
quantity: asQuantity(100_000_000),
}
const sellValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
const buyValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_999_998),
}
// act
const fee = getFrontendFee({
sellAmount: sellNotPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
sellInPrimaryTokenValue: sellValueInPrimaryToken,
milkBalance: Quantities.zero,
buyInPrimaryTokenValue: buyValueInPrimaryToken,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_050_000), // no milk, 100 ADA * 0.05% + 1 = 1.05 ADA
})
})

it('>= 100 and milk in balance >= 100 (buy side higher)', () => {
// arrange
const sellNotPrimaryAmountOver99: Balance.Amount = {
tokenId: 'not.primary.token',
quantity: asQuantity(100_000_000),
}
const sellValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(99_000_000),
}
const buyValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: sellNotPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
milkBalance: '499',
sellInPrimaryTokenValue: sellValueInPrimaryToken,
buyInPrimaryTokenValue: buyValueInPrimaryToken,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_025_000), // hold 100-499 milk, 100 ADA * 0.025% + 1= 1.025 ADA
})
})

it('>= 100 and milk in balance >= 500 (50/50)', () => {
// arrange
const sellNotPrimaryAmountOver99: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
const sellValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
const buyValueInPrimaryToken: Balance.Amount = {
tokenId: primaryTokenInfo.id,
quantity: asQuantity(100_000_000),
}
// act
const fee = getFrontendFee({
sellAmount: sellNotPrimaryAmountOver99,
buyAmount: notPrimaryTokenAmount,
milkBalance: '500',
sellInPrimaryTokenValue: sellValueInPrimaryToken,
buyInPrimaryTokenValue: buyValueInPrimaryToken,
primaryTokenInfo,
discountTiers: milkHoldersDiscountTiers,
})
// assert
expect(fee).toEqual({
tokenId: primaryTokenInfo.id,
quantity: asQuantity(1_020_000), // hold 500+ milk, 100 ADA * 0.020% + 1 = 1.02 ADA
})
})
})
})
Loading