Skip to content

Commit

Permalink
feat: chequebook api (#97)
Browse files Browse the repository at this point in the history
* feat: chequebook api

* chore: fix linter issues

* test: add debug logging

* fix: checkbookaddress response property name

* fix: chequebookaddress response property name

* test: conditionally enable chequebook tests

* chore: fix linter issues

* test: added log when BEE_CHEQUEBOOK_URL is not provided

* fix: export interfaces

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>

Co-authored-by: Vojtech Simetka <vojtech@simetka.cz>
  • Loading branch information
agazso and vojtechsimetka committed Feb 3, 2021
1 parent 892ce1b commit f7b77f4
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
env:
REPLICA: 5
BEE_URL: 'http://bee-0.localhost'
BEE_CHEQUEBOOK_URL: 'http://bee-0-debug.localhost'

runs-on: ubuntu-latest

Expand Down
178 changes: 178 additions & 0 deletions src/modules/debug/chequebook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { safeAxios } from '../../utils/safeAxios'

const chequebookEndpoint = '/chequebook'

interface ChequebookAddressResponse {
// see this issue regarding the naming https://github.com/ethersphere/bee/issues/1078
chequebookaddress: string
}

/**
* Get the address of the chequebook contract used
*
* @param url Bee debug url
*/
export async function getChequebookAddress(url: string): Promise<ChequebookAddressResponse> {
const response = await safeAxios<ChequebookAddressResponse>({
url: url + chequebookEndpoint + '/address',
responseType: 'json',
})

return response.data
}

interface ChequebookBalanceResponse {
totalBalance: number
availableBalance: number
}

/**
* Get the balance of the chequebook
*
* @param url Bee debug url
*/
export async function getChequeubookBalance(url: string): Promise<ChequebookBalanceResponse> {
const response = await safeAxios<ChequebookBalanceResponse>({
url: url + chequebookEndpoint + '/balance',
responseType: 'json',
})

return response.data
}

export interface CashoutResult {
recipient: string
lastPayout: number
bounced: boolean
}

export interface LastCashoutActionResponse {
peer: string
chequebook: string
cumulativePayout: number
beneficiary: string
transactionHash: string
result: CashoutResult
}

/**
* Get last cashout action for the peer
*
* @param url Bee debug url
* @param peer Swarm address of peer
*/
export async function getLastCashoutAction(url: string, peer: string): Promise<LastCashoutActionResponse> {
const response = await safeAxios<LastCashoutActionResponse>({
url: url + chequebookEndpoint + `/cashout/${peer}`,
responseType: 'json',
})

return response.data
}

export interface CashoutResponse {
transactionHash: string
}

/**
* Cashout the last cheque for the peer
*
* @param url Bee debug url
* @param peer Swarm address of peer
*/
export async function cashoutLastCheque(url: string, peer: string): Promise<CashoutResponse> {
const response = await safeAxios<LastCashoutActionResponse>({
method: 'post',
url: url + chequebookEndpoint + `/cashout/${peer}`,
responseType: 'json',
})

return response.data
}

export interface Cheque {
beneficiary: string
chequebook: string
payout: number
}

export interface LastChequesForPeerResponse {
peer: string
lastreceived: Cheque
lastsent: Cheque
}

/**
* Get last cheques for the peer
*
* @param url Bee debug url
* @param peer Swarm address of peer
*/
export async function getLastChequesForPeer(url: string, peer: string): Promise<LastChequesForPeerResponse> {
const response = await safeAxios<LastChequesForPeerResponse>({
url: url + chequebookEndpoint + `/cheque/${peer}`,
responseType: 'json',
})

return response.data
}

export interface LastChequesResponse {
lastcheques: LastChequesForPeerResponse[]
}

/**
* Get last cheques for all peers
*
* @param url Bee debug url
*/
export async function getLastCheques(url: string): Promise<LastChequesResponse> {
const response = await safeAxios<LastChequesResponse>({
url: url + chequebookEndpoint + '/cheque',
responseType: 'json',
})

return response.data
}

export interface DepositTokensResponse {
transactionHash: string
}

/**
* Deposit tokens from overlay address into chequebook
*
* @param url Bee debug url
* @param amount Amount of tokens to deposit
*/
export async function depositTokens(url: string, amount: number): Promise<DepositTokensResponse> {
const response = await safeAxios<DepositTokensResponse>({
method: 'post',
url: url + chequebookEndpoint + '/deposit',
responseType: 'json',
params: { amount },
})

return response.data
}

export interface WithdrawTokensResponse {
transactionHash: string
}

/**
* Withdraw tokens from the chequebook to the overlay address
*
* @param url Bee debug url
* @param amount Amount of tokens to withdraw
*/
export async function withdrawTokens(url: string, amount: number): Promise<WithdrawTokensResponse> {
const response = await safeAxios<WithdrawTokensResponse>({
method: 'post',
url: url + chequebookEndpoint + '/withdraw',
responseType: 'json',
params: { amount },
})

return response.data
}
62 changes: 62 additions & 0 deletions test/modules/debug/chequebook.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
depositTokens,
getChequebookAddress,
getChequeubookBalance,
getLastCheques,
withdrawTokens,
} from '../../../src/modules/debug/chequebook'
import { isHexString } from '../../../src/utils/hex'
import { beeChequebookUrl, sleep } from '../../utils'

const url = beeChequebookUrl()

if (url) {
describe('swap enabled chequebook', () => {
test('address', async () => {
const response = await getChequebookAddress(url)

expect(isHexString(response.chequebookaddress)).toBeTruthy()
})

test('balance', async () => {
const response = await getChequeubookBalance(url)

expect(typeof response.availableBalance).toBe('number')
expect(typeof response.totalBalance).toBe('number')
})

const TRANSACTION_TIMEOUT = 20 * 1000

test(
'withdraw and deposit',
async () => {
const withdrawResponse = await withdrawTokens(url, 10)
expect(typeof withdrawResponse.transactionHash).toBe('string')

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

const depositResponse = await depositTokens(url, 10)

expect(typeof depositResponse.transactionHash).toBe('string')
},
2 * TRANSACTION_TIMEOUT,
)

test('get last cheques for all peers', async () => {
const response = await getLastCheques(url)

expect(Array.isArray(response.lastcheques)).toBeTruthy()
})
})
} else {
test('swap disabled chequebook', () => {
// eslint-disable-next-line no-console
console.log(`
Chequebook tests are disabled because BEE_CHEQUEBOOK_URL is not set.
If you want to test chequebook functionality set the environment
variable to point to a Bee node with swap-enable.
`)
})
}
4 changes: 4 additions & 0 deletions test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export function beePeerUrl(): string {
return process.env.BEE_PEER_URL || 'http://bee-1.localhost'
}

export function beeChequebookUrl(): string {
return process.env.BEE_CHEQUEBOOK_URL || ''
}

/**
* Returns a url for testing the Bee Debug API
*/
Expand Down
6 changes: 6 additions & 0 deletions test/utils/hex.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ describe('hex', () => {

expect(result).toBeFalsy()
})
test('chequebookaddress', () => {
const input = '0x20d7855b548C71b69dA434D46187C336BDcef00F'
const result = isHexString(input)

expect(result).toBeTruthy()
})
})

const testBytes = new Uint8Array([
Expand Down

0 comments on commit f7b77f4

Please sign in to comment.