Skip to content

Commit

Permalink
feat: tests, fix auth
Browse files Browse the repository at this point in the history
Tests for all components.
Fixes for authorisation.
Address checksum validatin refactoring
  • Loading branch information
kyzia551 committed Feb 13, 2019
1 parent 141701d commit 2a5f15d
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 75 deletions.
91 changes: 88 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"semantic-release-prepare": "ts-node tools/semantic-release-prepare",
"precommit": "lint-staged",
"travis-deploy-once": "travis-deploy-once",
"prepush": "npm run test:prod && npm run build",
"commitmsg": "commitlint -E HUSKY_GIT_PARAMS"
},
"lint-staged": {
Expand Down Expand Up @@ -70,7 +71,8 @@
}
},
"collectCoverageFrom": [
"src/*.{js,ts}"
"src/*.{js,ts}",
"src/services/*.{js,ts}"
]
},
"prettier": {
Expand All @@ -84,7 +86,7 @@
},
"dependencies": {
"axios": "^0.18.0",
"keccak": "^2.0.0",
"ethereumjs-util": "^6.1.0",
"web3": "^1.0.0-beta.46"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default {
{ file: pkg.module, format: 'es', sourcemap: true },
],
// Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash')
external: [],
external: ['web3'],
watch: {
include: 'src/**',
},
Expand Down
4 changes: 2 additions & 2 deletions src/aave-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import LoanRequest from './services/LoanRequest'
export class Marketplace implements Marketplace {
public request: LoanAPIInstance

constructor(token: string) {
this.request = new LoanRequest(token)
constructor(token: string, apiUrl?: string) {
this.request = new LoanRequest(token, apiUrl)
}
}
24 changes: 5 additions & 19 deletions src/services/BaseService.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
import axios, { AxiosError, AxiosInstance } from 'axios'
import keccak from 'keccak'
import { isValidChecksumAddress } from 'ethereumjs-util'

import { BaseResponse } from '../types'

export default class BaseService {
protected readonly api: AxiosInstance

constructor(token: string) {
constructor(token: string, apiUrl?: string) {
this.api = axios.create({
baseURL: 'https://our-api-endpoint.com',
headers: { Authorisation: token }
baseURL: apiUrl || 'https://api.aave.com',
headers: { Authorization: `Bearer ${token}` }
})
}

protected static checkAddressChecksum(address: string): void {
const tempAddress = address.toLowerCase().replace('0x', '')
const hash = keccak('keccak256')
.update(address)
.digest('hex')
let checksummedAddress = '0x'

for (let i = 0; i < tempAddress.length; i += 1) {
if (parseInt(String(hash[i]), 16) >= 8) {
checksummedAddress += tempAddress[i].toUpperCase()
} else {
checksummedAddress += tempAddress[i]
}
}

if (address !== checksummedAddress) {
if (!isValidChecksumAddress(address)) {
throw `For security reason address ${address} should have correct checksum`
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/services/LoanRequest.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {
LoanTransactionResponse,
LoanMetadataResponse,
LoanRequestModel,
LoanRequestResponse,
LoanAddressesByBorrowerResponse,
LoansAddressesResponse,
LoanAPIInstance,
BaseResponse
BaseResponse,
BaseLoanModel
} from '../types'

import BaseService from './BaseService'

export default class LoanRequest extends BaseService implements LoanAPIInstance {
constructor(token: string) {
super(token)
constructor(token: string, apiUrl?: string) {
super(token, apiUrl)
}

private async apiRequest(
Expand All @@ -34,7 +34,7 @@ export default class LoanRequest extends BaseService implements LoanAPIInstance
}
}

public async create(creatorWalletAddress: string, params: LoanRequestModel): Promise<LoanTransactionResponse> {
public async create(creatorWalletAddress: string, params: BaseLoanModel): Promise<LoanTransactionResponse> {
BaseService.checkAddressChecksum(creatorWalletAddress)

return await this.apiRequest(`/request/create/${creatorWalletAddress}`, 'loan request creation', '', 'post', params)
Expand Down
13 changes: 8 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ export interface LoanMetadata {
durationRange: { min: number; max: number }
}

export interface LoanRequestModel {
loanAddress?: string
export interface BaseLoanModel {
moe: string
loanAmount: number
collateralType: string
collateralAmount: number
mpr: number
collateralType: string
moe: string
duration: number
}

export interface LoanRequestModel extends BaseLoanModel {
loanAddress?: string
state?: string
borrower?: string
fundedAmount?: number
Expand Down Expand Up @@ -64,7 +67,7 @@ export interface LoanAddressesByBorrowerResponse extends BaseResponse {
}

export interface LoanAPIInstance {
create(creatorWalletAddress: string, params: LoanRequestModel): Promise<LoanTransactionResponse>
create(creatorWalletAddress: string, params: BaseLoanModel): Promise<LoanTransactionResponse>
placeCollateral(loanAddress: string, borrowerAddress: string): Promise<LoanTransactionResponse>
fund(loanAddress: string, lenderAddress: string, amount: number): Promise<LoanTransactionResponse>
payback(loanAddress: string, borrowerAddress: string): Promise<LoanTransactionResponse>
Expand Down
32 changes: 0 additions & 32 deletions src/types/keccak/index.d.ts

This file was deleted.

40 changes: 40 additions & 0 deletions test/BaseService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import BaseService from '../src/services/BaseService'
/**
* BaseService test
*/
describe('LoanRequest test', () => {
const service = new BaseService('86C019FF04C4')

it('LoanRequest is instantiable', () => {
expect(service).toBeInstanceOf(BaseService)
})

it('should check valid eth addresses without errors', () => {
expect(BaseService['checkAddressChecksum']('0x71f4CF5Cfb74a9D3c9060aC4c25070F989cFC39C')).toBeUndefined()
})

it('should throw error on checking invalid eth address', () => {
expect(() => BaseService['checkAddressChecksum']('0x71f4CF5Cfb74a9D3c9060aC4c25070F989cFC39c')).toThrow()
})
const axiosErrorMock = (status: number) => ({
message: '',
name: '',
config: {},
response: { status, data: null, headers: null, statusText: '', config: {} }
})
it('should return correct error codes', () => {
for (const status of [401, 404, 500, 504]) {
expect(BaseService['errorHandler'](axiosErrorMock(status), 'type').code).toBe(status)
}
})

it('should return 500 code on unknown status', () => {
expect(BaseService['errorHandler'](axiosErrorMock(343), 'type').code).toBe(500)
})

it('should return 504 code if no response', () => {
expect(BaseService['errorHandler']({ message: '', name: '', config: {}, response: undefined }, 'type').code).toBe(
504
)
})
})
Loading

0 comments on commit 2a5f15d

Please sign in to comment.