Skip to content

Commit

Permalink
commit initial framework
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahZinsmeister committed May 30, 2019
0 parents commit a56aa05
Show file tree
Hide file tree
Showing 23 changed files with 5,738 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended", "prettier", "prettier/@typescript-eslint"]
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist/
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 120
}
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: node_js
node_js:
- '10'
cache:
directories:
- node_modules
install: yarn
script:
- yarn check:all
- yarn test
- yarn build
after_script:
- yarn coverage
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Uniswap SDK

[![Build Status](https://travis-ci.org/Uniswap/uniswap-sdk.svg?branch=master)](https://travis-ci.org/Uniswap/uniswap-sdk)
[![Coverage Status](https://coveralls.io/repos/github/Uniswap/uniswap-sdk/badge.svg?branch=master)](https://coveralls.io/github/Uniswap/uniswap-sdk?branch=master)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node'
}
48 changes: 48 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@uniswap/sdk",
"version": "1.0.0-beta.0",
"description": "An SDK for building applications on top of the Uniswap exchange protocol.",
"keywords": [
"Uniswap",
"Ethereum",
"SDK"
],
"main": "./dist/index.js",
"scripts": {
"lint:base": "yarn eslint './src/**/*.ts'",
"format:base": "yarn prettier './src/**/*.ts'",
"fix:lint": "yarn lint:base --fix",
"fix:format": "yarn format:base --write",
"fix:all": "yarn fix:lint && yarn fix:format",
"check:lint": "yarn lint:base",
"check:format": "yarn format:base --check",
"check:all": "yarn check:lint && yarn check:format",
"prebuild": "rm -rf dist/",
"build": "tsc",
"watch": "yarn prebuild && tsc --watch",
"test": "jest",
"coverage": "jest --coverage --coverageReporters=text-lcov | coveralls"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Uniswap/uniswap-sdk.git"
},
"author": "Noah Zinsmeister <noahwz@gmail.com>",
"license": "GPL-3.0-or-later",
"devDependencies": {
"@types/jest": "^24.0.13",
"@typescript-eslint/eslint-plugin": "^1.9.0",
"@typescript-eslint/parser": "^1.9.0",
"coveralls": "^3.0.3",
"eslint": "^5.16.0",
"eslint-config-prettier": "^4.3.0",
"jest": "^24.8.0",
"prettier": "^1.17.1",
"ts-jest": "^24.0.2",
"typescript": "^3.4.5"
},
"dependencies": {
"bignumber.js": "^9.0.0",
"ethers": "^4.0.28"
}
}
119 changes: 119 additions & 0 deletions src/__tests__/computation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import BigNumber from 'bignumber.js'

import { BigNumberish, TokenReserves } from '../types'
import { TRADE_TYPE } from '../constants'
import { getMarketRate } from '../computation'

function constructTokenReserves(
decimals: number,
ethReserveAmount: BigNumberish,
tokenReserveAmount: BigNumberish
): TokenReserves {
return {
token: { decimals },
ethReserve: { token: { decimals: 18 }, amount: ethReserveAmount },
tokenReserve: { token: { decimals }, amount: tokenReserveAmount }
}
}

function testMarketRates(
inputTokenReserves: TokenReserves | null,
outputTokenReserves: TokenReserves | null,
tradeType: TRADE_TYPE,
expectedMarketRate: string,
expectedMarketRateInverted: string
): void {
describe('regular', (): void => {
test('not inverted', (): void => {
const marketRate: BigNumber = getMarketRate(inputTokenReserves, outputTokenReserves, tradeType, false)
expect(marketRate.toFixed(18)).toBe(expectedMarketRate)
})

test('inverted', (): void => {
const marketRateInverted: BigNumber = getMarketRate(inputTokenReserves, outputTokenReserves, tradeType, true)
expect(marketRateInverted.toFixed(18)).toBe(expectedMarketRateInverted)
})
})

describe('manually inverted', (): void => {
const tradeTypeInverted =
tradeType === TRADE_TYPE.TOKEN_TO_TOKEN
? TRADE_TYPE.TOKEN_TO_TOKEN
: tradeType === TRADE_TYPE.ETH_TO_TOKEN
? TRADE_TYPE.TOKEN_TO_ETH
: TRADE_TYPE.ETH_TO_TOKEN

test('not inverted', (): void => {
const manuallyInvertedMarketRate: BigNumber = getMarketRate(
outputTokenReserves,
inputTokenReserves,
tradeTypeInverted,
false
)

expect(manuallyInvertedMarketRate.toFixed(18)).toBe(expectedMarketRateInverted)
})

test('inverted', (): void => {
const manuallyInvertedInvertedMarketRate: BigNumber = getMarketRate(
outputTokenReserves,
inputTokenReserves,
tradeTypeInverted,
true
)

expect(manuallyInvertedInvertedMarketRate.toFixed(18)).toBe(expectedMarketRate)
})
})
}

describe('getMarketRate', (): void => {
describe('dummy ETH/DAI and DAI/ETH', (): void => {
const tokenReserves: TokenReserves = constructTokenReserves(
18,
'4039700561005906883487',
'1094055210563660633471343'
)
const expectedMarketRate = '0.003692410147130181'
const expectedMarketRateInverted = '270.825818409480102284'

testMarketRates(null, tokenReserves, TRADE_TYPE.ETH_TO_TOKEN, expectedMarketRate, expectedMarketRateInverted)
testMarketRates(tokenReserves, null, TRADE_TYPE.TOKEN_TO_ETH, expectedMarketRateInverted, expectedMarketRate)
})

describe('dummy ETH/USDC and USDC/ETH', (): void => {
const tokenReserves: TokenReserves = constructTokenReserves(6, '1076592291503763426634', '292657693901')
const expectedMarketRate = '0.003678674143683891'
const expectedMarketRateInverted = '271.837069808684359442'

testMarketRates(null, tokenReserves, TRADE_TYPE.ETH_TO_TOKEN, expectedMarketRate, expectedMarketRateInverted)
testMarketRates(tokenReserves, null, TRADE_TYPE.TOKEN_TO_ETH, expectedMarketRateInverted, expectedMarketRate)
})

describe('dummy DAI/USDC and USDC/DAI', (): void => {
const DAITokenReserves: TokenReserves = constructTokenReserves(
18,
'4039700561005906883487',
'1094055210563660633471343'
)
const USDCTokenReserves: TokenReserves = constructTokenReserves(6, '1076592291503763426634', '292657693901')
const expectedMarketRate = '0.996279935624983178'
const expectedMarketRateInverted = '1.003733954927721499'

testMarketRates(
DAITokenReserves,
USDCTokenReserves,
TRADE_TYPE.TOKEN_TO_TOKEN,
expectedMarketRate,
expectedMarketRateInverted
)

testMarketRates(
USDCTokenReserves,
DAITokenReserves,
TRADE_TYPE.TOKEN_TO_TOKEN,
expectedMarketRateInverted,
expectedMarketRate
)
})
})
37 changes: 37 additions & 0 deletions src/__tests__/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TokenReserves, Token } from '../types'
import { ETH as _ETH } from '../constants'
import { getTokenReserves } from '../data'

const ETH: Token = {
chainId: 1,
address: _ETH,
decimals: 18
}

const DAI: Token = {
chainId: 1,
address: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359',
decimals: 18
}

const DAI_EXCHANGE: Token = {
chainId: 1,
address: '0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14',
decimals: 18
}

describe('getTokenReserves', (): void => {
test('DAI', async (done: jest.DoneCallback): Promise<void> => {
jest.setTimeout(20000) // 20 seconds
const tokenReserves: TokenReserves = await getTokenReserves(DAI.address as string)

expect(tokenReserves.token).toEqual(DAI)
expect(tokenReserves.exchange).toEqual(DAI_EXCHANGE)
expect(tokenReserves.ethReserve.token).toEqual(ETH)
expect(tokenReserves.ethReserve.amount).toBeTruthy()
expect(tokenReserves.tokenReserve.token).toEqual(DAI)
expect(tokenReserves.tokenReserve.amount).toBeTruthy()

done()
})
})
43 changes: 43 additions & 0 deletions src/__tests__/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { FlexibleFormat, FormatSignificantOptions, FormatFixedOptions } from '../types'
import { formatSignificant, formatFixed } from '../format'
import { FIXED_UNDERFLOW_BEHAVIOR } from '../constants'

function constructFormatSignificantOptions(
significantDigits: number,
forceIntegerSignificance: boolean = false,
format: FlexibleFormat = false
): FormatSignificantOptions {
return {
significantDigits,
forceIntegerSignificance,
format
}
}

function constructFormatFixedOptions(
decimalPlaces: number,
dropTrailingZeros: boolean = true,
format: FlexibleFormat = false,
underflowBehavior: FIXED_UNDERFLOW_BEHAVIOR = FIXED_UNDERFLOW_BEHAVIOR.ONE_DIGIT
): FormatFixedOptions {
return {
decimalPlaces,
dropTrailingZeros,
format,
underflowBehavior
}
}

describe('formatSignificant', (): void => {
test('regular', (): void => {
const formatted = formatSignificant('1.234', constructFormatSignificantOptions(2))
expect(formatted).toBe('1.2')
})
})

describe('formatFixed', (): void => {
test('regular', (): void => {
const formatted = formatFixed('1.234', constructFormatFixedOptions(1))
expect(formatted).toBe('1.2')
})
})
89 changes: 89 additions & 0 deletions src/__tests__/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import BigNumber from 'bignumber.js'

import { BigNumberish } from '../../types'
import { normalizeBigNumberish } from '../../utils'
import { ethers } from 'ethers'

interface TestCase {
input: BigNumberish
expectedOutput: BigNumber
}
function constructTestCase(input: BigNumberish, expectedOutput: BigNumber): TestCase {
return { input, expectedOutput }
}

function testSuccesses(expectedSuccesses: TestCase[]): void {
test('failures', (): void => {
expectedSuccesses.forEach(
({ input, expectedOutput }: TestCase): void => {
const output: BigNumber = normalizeBigNumberish(input)
expect(output.isEqualTo(expectedOutput)).toBe(true)
}
)
})
}

function testFailures(expectedFailures: BigNumberish[]): void {
test('failures', (): void => {
expectedFailures.forEach(
(expectedFailure: BigNumberish): void => {
expect(
(): void => {
normalizeBigNumberish(expectedFailure)
}
).toThrow()
}
)
})
}

describe('normalizeBigNumberish', (): void => {
describe('string', (): void => {
const expectedSuccesses: TestCase[] = [
constructTestCase('0', new BigNumber('0')),
constructTestCase('1', new BigNumber('1')),
constructTestCase('1.234', new BigNumber('1.234'))
]
const expectedFailures: string[] = ['.', ',', 'a', '0.0.']

testSuccesses(expectedSuccesses)
testFailures(expectedFailures)
})

describe('number', (): void => {
const expectedSuccesses: TestCase[] = [
constructTestCase(0, new BigNumber(0)),
constructTestCase(1, new BigNumber(1)),
constructTestCase(1.234, new BigNumber(1.234))
]
const expectedFailures: number[] = [NaN, Infinity]

testSuccesses(expectedSuccesses)
testFailures(expectedFailures)
})

describe('BigNumber', (): void => {
const expectedSuccesses: TestCase[] = [
constructTestCase(new BigNumber(0), new BigNumber(0)),
constructTestCase(new BigNumber(1), new BigNumber(1)),
constructTestCase(new BigNumber('1.234'), new BigNumber('1.234'))
]
const expectedFailures: BigNumber[] = [new BigNumber(NaN)]

testSuccesses(expectedSuccesses)
testFailures(expectedFailures)
})

describe('ethers.utils.BigNumber', (): void => {
const expectedSuccesses: TestCase[] = [
constructTestCase(ethers.constants.Zero, new BigNumber(0)),
constructTestCase(ethers.constants.One, new BigNumber(1)),
constructTestCase(ethers.utils.bigNumberify('1234'), new BigNumber('1234')),
constructTestCase(ethers.utils.parseUnits('1.234', 3), new BigNumber('1234'))
]
const expectedFailures: ethers.utils.BigNumber[] = []

testSuccesses(expectedSuccesses)
testFailures(expectedFailures)
})
})
Loading

0 comments on commit a56aa05

Please sign in to comment.