Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: gas price for deposit and withdraw tokens #336

Merged
merged 2 commits into from
Jun 1, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 17 additions & 11 deletions src/bee-debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import type {
LastChequesResponse,
LastChequesForPeerResponse,
LastCashoutActionResponse,
DepositTokensResponse,
WithdrawTokensResponse,
Settlements,
AllSettlements,
RemovePeerResponse,
Expand All @@ -27,7 +25,7 @@ import type {
ChainState,
} from './types'
import { assertBeeUrl, stripLastSlash } from './utils/url'
import { assertAddress, assertInteger, assertNonNegativeInteger } from './utils/type'
import { assertAddress, assertNonNegativeInteger } from './utils/type'
import { CashoutOptions } from './types'

/**
Expand Down Expand Up @@ -190,26 +188,34 @@ export class BeeDebug {
* Deposit tokens from overlay address into chequebook
*
* @param amount Amount of tokens to deposit (must be positive integer)
* @param gasPrice Gas Price in WEI for the transaction call
* @return string Hash of the transaction
*/
async depositTokens(amount: number | bigint): Promise<DepositTokensResponse> {
assertInteger(amount)
async depositTokens(amount: number | bigint, gasPrice?: bigint): Promise<string> {
assertNonNegativeInteger(amount)

if (amount < 0) throw new TypeError('must be positive number')
if (gasPrice) {
assertNonNegativeInteger(gasPrice)
}

return chequebook.depositTokens(this.url, amount)
return chequebook.depositTokens(this.url, amount, gasPrice)
}

/**
* Withdraw tokens from the chequebook to the overlay address
*
* @param amount Amount of tokens to withdraw (must be positive integer)
* @param gasPrice Gas Price in WEI for the transaction call
* @return string Hash of the transaction
*/
async withdrawTokens(amount: number | bigint): Promise<WithdrawTokensResponse> {
assertInteger(amount)
async withdrawTokens(amount: number | bigint, gasPrice?: bigint): Promise<string> {
assertNonNegativeInteger(amount)

if (amount < 0) throw new TypeError('must be positive number')
if (gasPrice) {
assertNonNegativeInteger(gasPrice)
}

return chequebook.withdrawTokens(this.url, amount)
return chequebook.withdrawTokens(this.url, amount, gasPrice)
}

/*
Expand Down
44 changes: 30 additions & 14 deletions src/modules/debug/chequebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import type {
ChequebookAddressResponse,
ChequebookBalanceResponse,
LastCashoutActionResponse,
CashoutResponse,
TransactionResponse,
LastChequesForPeerResponse,
LastChequesResponse,
DepositTokensResponse,
WithdrawTokensResponse,
} from '../../types'
import { CashoutOptions } from '../../types'

Expand Down Expand Up @@ -76,7 +74,7 @@ export async function cashoutLastCheque(url: string, peer: string, options?: Cas
headers['gas-limit'] = options.gasLimit.toString()
}

const response = await safeAxios<CashoutResponse>({
const response = await safeAxios<TransactionResponse>({
method: 'post',
url: url + chequebookEndpoint + `/cashout/${peer}`,
responseType: 'json',
Expand Down Expand Up @@ -119,33 +117,51 @@ export async function getLastCheques(url: string): Promise<LastChequesResponse>
/**
* Deposit tokens from overlay address into chequebook
*
* @param url Bee debug url
* @param amount Amount of tokens to deposit
* @param url Bee debug url
* @param amount Amount of tokens to deposit
* @param gasPrice Gas Price in WEI for the transaction call
* @return string Hash of the transaction
*/
export async function depositTokens(url: string, amount: number | bigint): Promise<DepositTokensResponse> {
const response = await safeAxios<DepositTokensResponse>({
export async function depositTokens(url: string, amount: number | bigint, gasPrice?: bigint): Promise<string> {
const headers: Record<string, string> = {}

if (gasPrice) {
headers['gas-price'] = gasPrice.toString()
}

const response = await safeAxios<TransactionResponse>({
method: 'post',
url: url + chequebookEndpoint + '/deposit',
responseType: 'json',
params: { amount: amount.toString(10) },
headers,
})

return response.data
return response.data.transactionHash
}

/**
* Withdraw tokens from the chequebook to the overlay address
*
* @param url Bee debug url
* @param amount Amount of tokens to withdraw
* @param url Bee debug url
* @param amount Amount of tokens to withdraw
* @param gasPrice Gas Price in WEI for the transaction call
* @return string Hash of the transaction
*/
export async function withdrawTokens(url: string, amount: number | bigint): Promise<WithdrawTokensResponse> {
const response = await safeAxios<WithdrawTokensResponse>({
export async function withdrawTokens(url: string, amount: number | bigint, gasPrice?: bigint): Promise<string> {
const headers: Record<string, string> = {}

if (gasPrice) {
headers['gas-price'] = gasPrice.toString()
}

const response = await safeAxios<TransactionResponse>({
method: 'post',
url: url + chequebookEndpoint + '/withdraw',
responseType: 'json',
params: { amount: amount.toString(10) },
headers,
})

return response.data
return response.data.transactionHash
}
9 changes: 1 addition & 8 deletions src/types/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface LastCashoutActionResponse {
result: CashoutResult | null
}

export interface CashoutResponse {
export interface TransactionResponse {
transactionHash: string
}

Expand All @@ -76,13 +76,6 @@ export interface LastChequesForPeerResponse {
export interface LastChequesResponse {
lastcheques: LastChequesForPeerResponse[]
}
export interface DepositTokensResponse {
transactionHash: string
}

export interface WithdrawTokensResponse {
transactionHash: string
}

export interface PeerBalance {
peer: string
Expand Down
12 changes: 7 additions & 5 deletions test/integration/modules/debug/chequebook.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
withdrawTokens,
} from '../../../../src/modules/debug/chequebook'
import { isPrefixedHexString } from '../../../../src/utils/hex'
import { beeDebugUrl, sleep } from '../../../utils'
import { beeDebugUrl, commonMatchers, sleep } from '../../../utils'

if (process.env.BEE_TEST_CHEQUEBOOK) {
commonMatchers()

describe('swap enabled chequebook', () => {
test('address', async () => {
const response = await getChequebookAddress(beeDebugUrl())
Expand All @@ -19,23 +21,23 @@ if (process.env.BEE_TEST_CHEQUEBOOK) {
test('balance', async () => {
const response = await getChequebookBalance(beeDebugUrl())

expect(typeof response.availableBalance).toBe('bigint')
expect(typeof response.totalBalance).toBe('bigint')
expect(response.availableBalance).toBeType('bigint')
expect(response.totalBalance).toBeType('bigint')
})

const TRANSACTION_TIMEOUT = 20 * 1000

const withDrawDepositTest = (amount: number | bigint) => async () => {
const withdrawResponse = await withdrawTokens(beeDebugUrl(), amount)
expect(typeof withdrawResponse.transactionHash).toBe('string')
expect(withdrawResponse).toBeType('string')

// TODO avoid sleep in tests
// See https://github.com/ethersphere/bee/issues/1191
await sleep(TRANSACTION_TIMEOUT)

const depositResponse = await depositTokens(beeDebugUrl(), amount)

expect(typeof depositResponse.transactionHash).toBe('string')
expect(depositResponse).toBeType('string')

// TODO avoid sleep in tests
// See https://github.com/ethersphere/bee/issues/1191
Expand Down
100 changes: 99 additions & 1 deletion test/unit/bee-debug-class.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { assertAllIsDone, cashoutLastChequeMock, MOCK_SERVER_URL } from './nock'
import { assertAllIsDone, cashoutLastChequeMock, depositTokensMock, MOCK_SERVER_URL, withdrawTokensMock } from './nock'
import { BeeArgumentError, BeeDebug } from '../../src'
import { testAddress } from '../utils'

Expand Down Expand Up @@ -103,4 +103,102 @@ describe('BeeDebug class', () => {
await expect(bee.cashoutLastCheque(testAddress, { gasLimit: BigInt('-1') })).rejects.toThrow(BeeArgumentError)
})
})

describe('withdrawTokens', () => {
const TRANSACTION_HASH = '36b7efd913ca4cf880b8eeac5093fa27b0825906c600685b6abdd6566e6cfe8f'
const CASHOUT_RESPONSE = {
transactionHash: TRANSACTION_HASH,
}

it('should not pass headers if no gas price is specified', async () => {
withdrawTokensMock('10').reply(201, CASHOUT_RESPONSE)

const bee = new BeeDebug(MOCK_SERVER_URL)
await expect(bee.withdrawTokens(BigInt('10'))).resolves.toEqual(TRANSACTION_HASH)
assertAllIsDone()
})

it('should pass headers if gas price is specified', async () => {
withdrawTokensMock('10', '100000000000').reply(201, CASHOUT_RESPONSE)

const bee = new BeeDebug(MOCK_SERVER_URL)
await expect(bee.withdrawTokens(BigInt('10'), BigInt('100000000000'))).resolves.toEqual(TRANSACTION_HASH)
assertAllIsDone()
})

it('should throw error if passed wrong amount', async () => {
const bee = new BeeDebug(MOCK_SERVER_URL)

// @ts-ignore: Input testing
await expect(bee.withdrawTokens(true)).rejects.toThrow(TypeError)

// @ts-ignore: Input testing
await expect(bee.withdrawTokens('asd')).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.withdrawTokens(null)).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.withdrawTokens()).rejects.toThrow(TypeError)

await expect(bee.withdrawTokens(BigInt('-1'))).rejects.toThrow(BeeArgumentError)
})

it('should throw error if passed wrong gas price input', async () => {
const bee = new BeeDebug(MOCK_SERVER_URL)

// @ts-ignore: Input testing
await expect(bee.withdrawTokens(BigInt('1'), true)).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.withdrawTokens(BigInt('1'), 'asd')).rejects.toThrow(TypeError)
await expect(bee.withdrawTokens(BigInt('1'), BigInt('-1'))).rejects.toThrow(BeeArgumentError)
})
})

describe('depositTokens', () => {
const TRANSACTION_HASH = '36b7efd913ca4cf880b8eeac5093fa27b0825906c600685b6abdd6566e6cfe8f'
const CASHOUT_RESPONSE = {
transactionHash: TRANSACTION_HASH,
}

it('should not pass headers if no gas price is specified', async () => {
depositTokensMock('10').reply(201, CASHOUT_RESPONSE)

const bee = new BeeDebug(MOCK_SERVER_URL)
await expect(bee.depositTokens(BigInt('10'))).resolves.toEqual(TRANSACTION_HASH)
assertAllIsDone()
})

it('should pass headers if gas price is specified', async () => {
depositTokensMock('10', '100000000000').reply(201, CASHOUT_RESPONSE)

const bee = new BeeDebug(MOCK_SERVER_URL)
await expect(bee.depositTokens(BigInt('10'), BigInt('100000000000'))).resolves.toEqual(TRANSACTION_HASH)
assertAllIsDone()
})

it('should throw error if passed wrong amount', async () => {
const bee = new BeeDebug(MOCK_SERVER_URL)

// @ts-ignore: Input testing
await expect(bee.depositTokens(true)).rejects.toThrow(TypeError)

// @ts-ignore: Input testing
await expect(bee.depositTokens('asd')).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.depositTokens(null)).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.depositTokens()).rejects.toThrow(TypeError)

await expect(bee.depositTokens(BigInt('-1'))).rejects.toThrow(BeeArgumentError)
})

it('should throw error if passed wrong gas price input', async () => {
const bee = new BeeDebug(MOCK_SERVER_URL)

// @ts-ignore: Input testing
await expect(bee.depositTokens(BigInt('1'), true)).rejects.toThrow(TypeError)
// @ts-ignore: Input testing
await expect(bee.depositTokens(BigInt('1'), 'asd')).rejects.toThrow(TypeError)
await expect(bee.depositTokens(BigInt('1'), BigInt('-1'))).rejects.toThrow(BeeArgumentError)
})
})
})
24 changes: 24 additions & 0 deletions test/unit/nock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,27 @@ export function cashoutLastChequeMock(peer: string, gasPrice?: string, gasLimit?
reqheaders: headers,
}).post(`${CHEQUEBOOK_ENDPOINT}/cashout/${peer}`)
}

export function depositTokensMock(amount: string, gasPrice?: string): nock.Interceptor {
const headers: Record<string, string> = {}

if (gasPrice) {
headers['gas-price'] = gasPrice
}

return nock(MOCK_SERVER_URL, {
reqheaders: headers,
}).post(`${CHEQUEBOOK_ENDPOINT}/deposit?amount=${amount}`)
}

export function withdrawTokensMock(amount: string, gasPrice?: string): nock.Interceptor {
const headers: Record<string, string> = {}

if (gasPrice) {
headers['gas-price'] = gasPrice
}

return nock(MOCK_SERVER_URL, {
reqheaders: headers,
}).post(`${CHEQUEBOOK_ENDPOINT}/withdraw?amount=${amount}`)
}