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

feat: bring over buildQuoteTx logic from platform-shared #71

Merged
merged 16 commits into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from 9 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
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>

/**
* 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: ({} as unknown) as Web3,
adapterManager: ({} as unknown) as 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
35 changes: 28 additions & 7 deletions packages/swapper/src/swappers/zrx/ZrxSwapper.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import Web3 from 'web3'
import { HDWallet } from '@shapeshiftoss/hdwallet-core'
import { ChainAdapterManager } from '@shapeshiftoss/chain-adapters'
import { ChainTypes, NetworkTypes, ContractTypes } 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()
}))
Expand Down Expand Up @@ -70,14 +78,20 @@ const setupQuote = () => {
}

describe('ZrxSwapper', () => {
const input = ({} as unknown) as GetQuoteInput
const wallet = ({} as unknown) as HDWallet
const web3 = ({} as unknown) as Web3
const adapterManager = ({} as unknown) as 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 @@ -87,18 +101,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()
})
})
31 changes: 30 additions & 1 deletion packages/swapper/src/swappers/zrx/ZrxSwapper.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,46 @@
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'
import { getDeps } from '../zrx/utils/helpers/helpers'

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'
adapterManager: ChainAdapterManager
web3: Web3

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

private getDeps() {
return getDeps.call(this)
}

getType() {
return SwapperType.Zrx
}

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

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