Skip to content

Commit

Permalink
fix: use bigint for bzz amounts (#259)
Browse files Browse the repository at this point in the history
Co-authored-by: Attila Gazso <agazso@gmail.com>
  • Loading branch information
AuHau and agazso authored Apr 15, 2021
1 parent e153aca commit 9da31c2
Show file tree
Hide file tree
Showing 11 changed files with 13,383 additions and 42 deletions.
13,274 changes: 13,253 additions & 21 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"elliptic": "^6.5.4",
"isomorphic-ws": "^4.0.1",
"js-sha3": "^0.8.0",
"json-bigint": "^1.0.0",
"tar-js": "^0.3.0",
"ws": "^7.4.1"
},
Expand All @@ -69,6 +70,7 @@
"@types/glob": "^7.1.3",
"@types/jest": "^26.0.21",
"@types/jest-environment-puppeteer": "^4.4.1",
"@types/json-bigint": "^1.0.0",
"@types/karma": "^5.0.1",
"@types/node": "^14.14.6",
"@types/puppeteer": "^5.4.2",
Expand Down
4 changes: 4 additions & 0 deletions src/modules/debug/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export async function getAllBalances(url: string): Promise<BalanceResponse> {
const response = await safeAxios<BalanceResponse>({
url: url + balancesEndpoint,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand All @@ -28,6 +29,7 @@ export async function getPeerBalance(url: string, address: string): Promise<Peer
const response = await safeAxios<PeerBalance>({
url: url + `${balancesEndpoint}/${address}`,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand All @@ -42,6 +44,7 @@ export async function getPastDueConsumptionBalances(url: string): Promise<Balanc
const response = await safeAxios<BalanceResponse>({
url: url + consumedEndpoint,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand All @@ -57,6 +60,7 @@ export async function getPastDueConsumptionPeerBalance(url: string, address: str
const response = await safeAxios<PeerBalance>({
url: url + `${consumedEndpoint}/${address}`,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand Down
3 changes: 3 additions & 0 deletions src/modules/debug/chequebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function getChequebookBalance(url: string): Promise<ChequebookBalan
const response = await safeAxios<ChequebookBalanceResponse>({
url: url + chequebookEndpoint + '/balance',
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand All @@ -50,6 +51,7 @@ export async function getLastCashoutAction(url: string, peer: string): Promise<L
const response = await safeAxios<LastCashoutActionResponse>({
url: url + chequebookEndpoint + `/cashout/${peer}`,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand Down Expand Up @@ -81,6 +83,7 @@ export async function getLastChequesForPeer(url: string, peer: string): Promise<
const response = await safeAxios<LastChequesForPeerResponse>({
url: url + chequebookEndpoint + `/cheque/${peer}`,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand Down
2 changes: 2 additions & 0 deletions src/modules/debug/settlements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export async function getSettlements(url: string, peer: string): Promise<Settlem
const response = await safeAxios<Settlements>({
url: url + `${settlementsEndpoint}/${peer}`,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand All @@ -27,6 +28,7 @@ export async function getAllSettlements(url: string): Promise<AllSettlements> {
const response = await safeAxios<AllSettlements>({
url: url + settlementsEndpoint,
responseType: 'json',
forceBigInt: true,
})

return response.data
Expand Down
18 changes: 18 additions & 0 deletions src/types/axios/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
declare module 'axios/lib/helpers/normalizeHeaderName' {
export default function (headers: Record<string, unknown>, header: string): void
}

declare module 'axios/lib/utils' {
import ArrayBufferView = NodeJS.ArrayBufferView

export function isFormData(data: unknown): boolean
export function isArrayBuffer(data: unknown): boolean
export function isBuffer(data: unknown): boolean
export function isStream(data: unknown): boolean
export function isFile(data: unknown): boolean
export function isBlob(data: unknown): boolean
export function isArrayBufferView(data: unknown): data is ArrayBufferView
export function isURLSearchParams(data: unknown): data is URLSearchParams
export function isObject(data: unknown): boolean
export function isUndefined(data: unknown): boolean
}
20 changes: 10 additions & 10 deletions src/types/debug.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export interface Settlements {
peer: string
received: number
sent: number
received: BigInt
sent: BigInt
}

export interface AllSettlements {
totalreceived: number
totalsent: number
totalreceived: BigInt
totalsent: BigInt
settlements: Settlements[]
}

Expand All @@ -28,20 +28,20 @@ export interface ChequebookAddressResponse {
}

export interface ChequebookBalanceResponse {
totalBalance: number
availableBalance: number
totalBalance: BigInt
availableBalance: BigInt
}

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

export interface LastCashoutActionResponse {
peer: string
chequebook: string
cumulativePayout: number
cumulativePayout: BigInt
beneficiary: string
transactionHash: string
result: CashoutResult
Expand All @@ -54,7 +54,7 @@ export interface CashoutResponse {
export interface Cheque {
beneficiary: string
chequebook: string
payout: number
payout: BigInt
}

export interface LastChequesForPeerResponse {
Expand All @@ -76,7 +76,7 @@ export interface WithdrawTokensResponse {

export interface PeerBalance {
peer: string
balance: number
balance: BigInt
}

export interface BalanceResponse {
Expand Down
82 changes: 81 additions & 1 deletion src/utils/safeAxios.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,93 @@
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import { BeeError, BeeRequestError, BeeResponseError } from './error'
import JsonBig from 'json-bigint'

import utils from 'axios/lib/utils'
import normalizeHeaderName from 'axios/lib/helpers/normalizeHeaderName'
axios.defaults.adapter = require('axios/lib/adapters/http') // https://stackoverflow.com/a/57320262

export async function safeAxios<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
/**
* Utility function from axios's implementation
* https://github.com/axios/axios/blob/d99d5faac29899eba68ce671e6b3cbc9832e9ad8/lib/defaults.js
*
* @param headers
* @param value
*/
function setContentTypeIfUnset(headers: Record<string, unknown>, value: string) {
if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
headers['Content-Type'] = value
}
}

/**
* Taken over from axios's implementation
* https://github.com/axios/axios/blob/d99d5faac29899eba68ce671e6b3cbc9832e9ad8/lib/defaults.js
*
* Unfortunately we can't use the default implementation as fallback one and override only the JSON serialization as the JSON.stringify
* is a last thing to do as all the previous cases (buffer, file etc.) are objects as well
* so they have to be ruled out first before trying JSON.stringify.
*
* @param data
* @param headers
*/
function jsonBigTransformRequest(data: unknown, headers: Record<string, unknown>): string | unknown {
normalizeHeaderName(headers, 'Accept')
normalizeHeaderName(headers, 'Content-Type')

if (
utils.isFormData(data) ||
utils.isArrayBuffer(data) ||
utils.isBuffer(data) ||
utils.isStream(data) ||
utils.isFile(data) ||
utils.isBlob(data)
) {
return data
}

if (utils.isArrayBufferView(data)) {
return data.buffer
}

if (utils.isURLSearchParams(data)) {
setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8')

return data.toString()
}

if (utils.isObject(data)) {
setContentTypeIfUnset(headers, 'application/json;charset=utf-8')
const JsonBigNative = JsonBig({ useNativeBigInt: true })

return JsonBigNative.stringify(data)
}

return data
}

function jsonBigTransformResponse(forceBigInt = false) {
return (data: unknown): unknown => {
if (typeof data === 'string') {
const JsonBigNative = JsonBig({ useNativeBigInt: true, alwaysParseAsBig: forceBigInt })

try {
data = JsonBigNative.parse(data)
} catch (e) {
/* Ignore */
}
}

return data
}
}

export async function safeAxios<T>(config: AxiosRequestConfig & { forceBigInt?: boolean }): Promise<AxiosResponse<T>> {
try {
const response = await axios({
maxContentLength: Infinity,
maxBodyLength: Infinity,
transformRequest: jsonBigTransformRequest,
transformResponse: jsonBigTransformResponse(config.forceBigInt),
...config,
})

Expand Down
8 changes: 4 additions & 4 deletions test/integration/modules/debug/balance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('balance', () => {
expect.arrayContaining([
expect.objectContaining({
peer: expect.any(String),
balance: expect.any(Number),
balance: expect.any(BigInt),
}),
]),
)
Expand All @@ -34,7 +34,7 @@ describe('balance', () => {
const peerBalance = await balance.getPeerBalance(beeDebugUrl(), peerOverlay)

expect(peerBalance.peer).toEqual(peerOverlay)
expect(typeof peerBalance.balance).toBe('number')
expect(typeof peerBalance.balance).toBe('bigint')
})
})

Expand All @@ -47,7 +47,7 @@ describe('balance', () => {
expect.arrayContaining([
expect.objectContaining({
peer: expect.any(String),
balance: expect.any(Number),
balance: expect.any(BigInt),
}),
]),
)
Expand All @@ -62,7 +62,7 @@ describe('balance', () => {
const peerBalance = await balance.getPastDueConsumptionPeerBalance(beeDebugUrl(), peerOverlay)

expect(peerBalance.peer).toEqual(peerOverlay)
expect(typeof peerBalance.balance).toBe('number')
expect(typeof peerBalance.balance).toBe('bigint')
})
})
})
4 changes: 2 additions & 2 deletions test/integration/modules/debug/chequebook.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ if (process.env.BEE_TEST_CHEQUEBOOK) {
test('balance', async () => {
const response = await getChequebookBalance(beeDebugUrl())

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

const TRANSACTION_TIMEOUT = 20 * 1000
Expand Down
8 changes: 4 additions & 4 deletions test/integration/modules/debug/settlements.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ describe('settlements', () => {
test('all settlements', async () => {
const response = await settlements.getAllSettlements(beeDebugUrl())

expect(typeof response.totalreceived).toBe('number')
expect(typeof response.totalsent).toBe('number')
expect(typeof response.totalreceived).toBe('bigint')
expect(typeof response.totalsent).toBe('bigint')
expect(Array.isArray(response.settlements)).toBeTruthy()

if (response.settlements.length > 0) {
Expand All @@ -25,8 +25,8 @@ describe('settlements', () => {
const peerSettlementResponse = await settlements.getSettlements(beeDebugUrl(), peerSettlement.peer)

expect(peerSettlementResponse.peer).toEqual(peerSettlement.peer)
expect(typeof peerSettlementResponse.received).toBe('number')
expect(typeof peerSettlementResponse.sent).toBe('number')
expect(typeof peerSettlementResponse.received).toBe('bigint')
expect(typeof peerSettlementResponse.sent).toBe('bigint')
}
})
})

0 comments on commit 9da31c2

Please sign in to comment.