Skip to content
This repository has been archived by the owner on Apr 11, 2023. It is now read-only.

Commit

Permalink
feat: bring over buildQuoteTx logic from platform-shared (#71)
Browse files Browse the repository at this point in the history
* wip - bring over buildQuoteTx logic

* add tests for ZrxSwapper utils and buildQuoteTx

* refactor ZrxSwapper to take ChainAdapterManager instead of individual adapter

* refactor buildQuoteTx to a helper function; modify test

* refactor buildQuoteTx tests; add comments

* refactor utils directory

* fix linter

* add getDeps helper function for ZrxSwapper

* getDeps typed

* cleanup mock typing

* fix typing on tests; consolidate error handling for buildQuoteTx

* update error handling for buildQuoteTx

* PR changes/improvements

* fix linter

Co-authored-by: 0xdef1cafe <[email protected]>
  • Loading branch information
DaoDev44 and 0xdef1cafe authored Sep 29, 2021
1 parent 8b8c3a1 commit 4ec3365
Show file tree
Hide file tree
Showing 19 changed files with 4,369 additions and 117 deletions.
8 changes: 7 additions & 1 deletion packages/swapper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
},
"dependencies": {
"@shapeshiftoss/asset-service": "^1.0.0",
"@shapeshiftoss/chain-adapters": "^1.0.0",
"@shapeshiftoss/hdwallet-core": "^1.16.2-alpha.0",
"axios": "^0.21.4",
"bignumber.js": "^9.0.1"
"web3": "^1.5.2",
"bignumber.js": "^9.0.1",
"retry-axios": "^2.6.0"
},
"devDependencies": {
"web3-utils": "^1.5.2"
}
}
14 changes: 14 additions & 0 deletions packages/swapper/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export enum SwapperType {
Thorchain = 'Thorchain'
}

export class SwapError extends Error {}

export interface FeeData {
fee?: string
gas?: string
Expand Down Expand Up @@ -84,10 +86,22 @@ export interface GetQuoteInput {
minimum?: string
}

export type BuildQuoteTxArgs = {
input: GetQuoteInput
wallet: HDWallet
}

export interface Swapper {
/** Returns the swapper type */
getType(): SwapperType

/**
* Get a Quote along with an unsigned transaction that can be signed and broadcast to execute the swap
* @param input
* @param wallet
**/
buildQuoteTx(args: BuildQuoteTxArgs): Promise<Quote | undefined>

/**
* Get a basic quote (rate) for a trading pair
* @param input
Expand Down
13 changes: 10 additions & 3 deletions packages/swapper/src/manager/SwapperManager.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import Web3 from 'web3'
import { SwapperType } from '../api'
import { ThorchainSwapper, ZrxSwapper } from '../swappers'
import { SwapperManager } from './SwapperManager'
import { ChainAdapterManager } from '@shapeshiftoss/chain-adapters'

describe('SwapperManager', () => {
const zrxSwapperDeps = {
web3: <Web3>{},
adapterManager: <ChainAdapterManager>{}
}

describe('constructor', () => {
it('should return an instance', () => {
const manager = new SwapperManager()
Expand All @@ -22,7 +29,7 @@ describe('SwapperManager', () => {
const manager = new SwapperManager()
manager
.addSwapper(SwapperType.Thorchain, new ThorchainSwapper())
.addSwapper(SwapperType.Zrx, new ZrxSwapper())
.addSwapper(SwapperType.Zrx, new ZrxSwapper(zrxSwapperDeps))
expect(manager.getSwapper(SwapperType.Zrx)).toBeInstanceOf(ZrxSwapper)
})

Expand All @@ -31,7 +38,7 @@ describe('SwapperManager', () => {
expect(() => {
swapper
.addSwapper(SwapperType.Thorchain, new ThorchainSwapper())
.addSwapper(SwapperType.Thorchain, new ZrxSwapper())
.addSwapper(SwapperType.Thorchain, new ZrxSwapper(zrxSwapperDeps))
}).toThrow('already exists')
})
})
Expand All @@ -47,7 +54,7 @@ describe('SwapperManager', () => {
const swapper = new SwapperManager()
swapper
.addSwapper(SwapperType.Thorchain, new ThorchainSwapper())
.addSwapper(SwapperType.Zrx, new ZrxSwapper())
.addSwapper(SwapperType.Zrx, new ZrxSwapper(zrxSwapperDeps))

expect(swapper.getSwapper(SwapperType.Thorchain)).toBeInstanceOf(ThorchainSwapper)
expect(swapper.getSwapper(SwapperType.Zrx)).toBeInstanceOf(ZrxSwapper)
Expand Down
4 changes: 4 additions & 0 deletions packages/swapper/src/swappers/thorchain/ThorchainSwapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export class ThorchainSwapper implements Swapper {
return undefined
}

async buildQuoteTx() {
return undefined
}

getAvailableAssets(assets: Asset[]): Asset[] {
console.info(assets)
throw new Error('Method not implemented.')
Expand Down
50 changes: 36 additions & 14 deletions packages/swapper/src/swappers/zrx/ZrxSwapper.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { ChainTypes, NetworkTypes, ContractTypes } from '@shapeshiftoss/asset-service'
import Web3 from 'web3'
import { HDWallet } from '@shapeshiftoss/hdwallet-core'
import { ChainAdapterManager } from '@shapeshiftoss/chain-adapters'
import { ChainTypes, NetworkTypes, ContractTypes, Asset } from '@shapeshiftoss/asset-service'
import { ZrxSwapper } from '..'
import { SwapperType, ZrxError } from '../..'
import { DEFAULT_SLIPPAGE } from './constants'
import { GetQuoteInput, SwapperType, ZrxError } from '../..'
import { DEFAULT_SLIPPAGE } from './utils/constants'
import { buildQuoteTx } from '../zrx/buildQuoteTx/buildQuoteTx'
import { getZrxQuote } from './getQuote/getQuote'

jest.mock('../zrx/buildQuoteTx/buildQuoteTx', () => ({
buildQuoteTx: jest.fn()
}))

jest.mock('./getQuote/getQuote', () => ({
getZrxQuote: jest.fn()
}))

const BTC = {
const BTC = ({
name: 'bitcoin',
chain: ChainTypes.Bitcoin,
network: NetworkTypes.MAINNET,
Expand All @@ -23,8 +31,9 @@ const BTC = {
sendSupport: false,
receiveSupport: false,
symbol: 'BTC'
}
const WETH = {
// TODO: remove the type casts from test files when we unify `ChainTypes` and `ChainIdentifier`
} as unknown) as Asset
const WETH = ({
name: 'WETH',
chain: ChainTypes.Ethereum,
network: NetworkTypes.MAINNET,
Expand All @@ -40,8 +49,8 @@ const WETH = {
sendSupport: true,
receiveSupport: true,
symbol: 'WETH'
}
const FOX = {
} as unknown) as Asset
const FOX = ({
name: 'Fox',
chain: ChainTypes.Ethereum,
network: NetworkTypes.MAINNET,
Expand All @@ -57,7 +66,7 @@ const FOX = {
explorerTxLink: 'https://etherscan.io/tx/',
receiveSupport: true,
symbol: 'FOX'
}
} as unknown) as Asset

const setupQuote = () => {
const sellAmount = '1000000000000000000'
Expand All @@ -74,14 +83,20 @@ const setupQuote = () => {
}

describe('ZrxSwapper', () => {
const input = <GetQuoteInput>{}
const wallet = <HDWallet>{}
const web3 = <Web3>{}
const adapterManager = <ChainAdapterManager>{}
const zrxSwapperDeps = { web3, adapterManager }

it('calls getZrxQuote on getQuote', async () => {
const { quoteInput } = setupQuote()
const swapper = new ZrxSwapper()
const swapper = new ZrxSwapper(zrxSwapperDeps)
await swapper.getQuote(quoteInput)
expect(getZrxQuote).toHaveBeenCalled()
})
it('returns Zrx type', () => {
const swapper = new ZrxSwapper()
const swapper = new ZrxSwapper(zrxSwapperDeps)
const type = swapper.getType()
expect(type).toBe(SwapperType.Zrx)
})
Expand All @@ -91,18 +106,25 @@ describe('ZrxSwapper', () => {
expect(error.message).toBe(`ZrxError:${message}`)
})
it('available assets filters out all non-ethereum assets', () => {
const swapper = new ZrxSwapper()
const swapper = new ZrxSwapper(zrxSwapperDeps)
const availableAssets = swapper.getAvailableAssets([BTC, FOX, WETH])
expect(availableAssets).toStrictEqual([FOX, WETH])
})
it('canTradePair fails on non-eth chains', () => {
const swapper = new ZrxSwapper()
const swapper = new ZrxSwapper(zrxSwapperDeps)
const canTradePair = swapper.canTradePair(BTC, WETH)
expect(canTradePair).toBeFalsy()
})
it('canTradePair succeeds on eth chains', () => {
const swapper = new ZrxSwapper()
const swapper = new ZrxSwapper(zrxSwapperDeps)
const canTradePair = swapper.canTradePair(FOX, WETH)
expect(canTradePair).toBeTruthy()
})
it('calls buildQuoteTx on swapper.buildQuoteTx', async () => {
const swapper = new ZrxSwapper(zrxSwapperDeps)
const args = { input, wallet }

await swapper.buildQuoteTx(args)
expect(buildQuoteTx).toHaveBeenCalled()
})
})
24 changes: 23 additions & 1 deletion packages/swapper/src/swappers/zrx/ZrxSwapper.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import Web3 from 'web3'
import { Asset, ChainTypes } from '@shapeshiftoss/asset-service'
import { GetQuoteInput, Quote, Swapper, SwapperType } from '../../api'
import { ChainAdapterManager } from '@shapeshiftoss/chain-adapters'
import { BuildQuoteTxArgs, GetQuoteInput, Quote, Swapper, SwapperType } from '../../api'

import { buildQuoteTx } from './buildQuoteTx/buildQuoteTx'
import { getZrxQuote } from './getQuote/getQuote'

export type ZrxSwapperDeps = {
adapterManager: ChainAdapterManager
web3: Web3
}

export class ZrxError extends Error {
constructor(message: string) {
super(message)
this.message = `ZrxError:${message}`
}
}

export class ZrxSwapper implements Swapper {
public static swapperName = 'ZrxSwapper'
deps: ZrxSwapperDeps

constructor(deps: ZrxSwapperDeps) {
this.deps = deps
}

getType() {
return SwapperType.Zrx
}

async buildQuoteTx({ input, wallet }: BuildQuoteTxArgs): Promise<Quote> {
return buildQuoteTx(this.deps, { input, wallet })
}

async getQuote(input: GetQuoteInput): Promise<Quote> {
return getZrxQuote(input)
}
Expand Down
Loading

0 comments on commit 4ec3365

Please sign in to comment.