From 2f7a765b8b84eef978ab06940455523ce5293a20 Mon Sep 17 00:00:00 2001 From: jsy1218 <91580504+jsy1218@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:24:26 -0700 Subject: [PATCH] Add fee-on-transfer token fees fields (#83) * Token construct supports FOT fees * Fix code style issues with Prettier * delete .idea folders --------- Co-authored-by: Siyu Jiang Co-authored-by: Lint Action --- src/entities/token.test.ts | 9 +++++++++ src/entities/token.ts | 22 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/entities/token.test.ts b/src/entities/token.test.ts index e3c36f1d..58a8e196 100644 --- a/src/entities/token.test.ts +++ b/src/entities/token.test.ts @@ -1,4 +1,5 @@ import { Token } from './token' +import { BigNumber } from '@ethersproject/bignumber' describe('Token', () => { const ADDRESS_ONE = '0x0000000000000000000000000000000000000001' @@ -20,6 +21,14 @@ describe('Token', () => { it('fails with non-integer decimals', () => { expect(() => new Token(3, ADDRESS_ONE, 1.5).address).toThrow('DECIMALS') }) + it('fails with negative FOT fees', () => { + expect( + () => new Token(3, ADDRESS_ONE, 18, undefined, undefined, undefined, BigNumber.from(-1), undefined) + ).toThrow('NON-NEGATIVE FOT FEES') + expect( + () => new Token(3, ADDRESS_ONE, 18, undefined, undefined, undefined, undefined, BigNumber.from(-1)) + ).toThrow('NON-NEGATIVE FOT FEES') + }) }) describe('#constructor with bypassChecksum = true', () => { diff --git a/src/entities/token.ts b/src/entities/token.ts index 590f0290..3c1d8581 100644 --- a/src/entities/token.ts +++ b/src/entities/token.ts @@ -1,3 +1,4 @@ +import { BigNumber } from '@ethersproject/bignumber' import invariant from 'tiny-invariant' import { checkValidAddress, validateAndParseAddress } from '../utils/validateAndParseAddress' import { BaseCurrency } from './baseCurrency' @@ -15,6 +16,13 @@ export class Token extends BaseCurrency { */ public readonly address: string + /** + * Relevant for fee-on-transfer (FOT) token taxes, + * Not every ERC20 token is FOT token, so this field is optional + */ + public readonly buyFeeBps?: BigNumber + public readonly sellFeeBps?: BigNumber + /** * * @param chainId {@link BaseCurrency#chainId} @@ -23,6 +31,8 @@ export class Token extends BaseCurrency { * @param symbol {@link BaseCurrency#symbol} * @param name {@link BaseCurrency#name} * @param bypassChecksum If true it only checks for length === 42, startsWith 0x and contains only hex characters + * @param buyFeeBps Buy fee tax for FOT tokens, in basis points + * @param sellFeeBps Sell fee tax for FOT tokens, in basis points */ public constructor( chainId: number, @@ -30,7 +40,9 @@ export class Token extends BaseCurrency { decimals: number, symbol?: string, name?: string, - bypassChecksum?: boolean + bypassChecksum?: boolean, + buyFeeBps?: BigNumber, + sellFeeBps?: BigNumber ) { super(chainId, decimals, symbol, name) if (bypassChecksum) { @@ -38,6 +50,14 @@ export class Token extends BaseCurrency { } else { this.address = validateAndParseAddress(address) } + if (buyFeeBps) { + invariant(buyFeeBps.gte(BigNumber.from(0)), 'NON-NEGATIVE FOT FEES') + } + if (sellFeeBps) { + invariant(sellFeeBps.gte(BigNumber.from(0)), 'NON-NEGATIVE FOT FEES') + } + this.buyFeeBps = buyFeeBps + this.sellFeeBps = sellFeeBps } /**