Skip to content

Commit

Permalink
feat: payment detection error does not throw (#163)
Browse files Browse the repository at this point in the history
  • Loading branch information
vrolland committed Mar 12, 2020
1 parent 515aa0f commit f49640b
Show file tree
Hide file tree
Showing 13 changed files with 317 additions and 164 deletions.
22 changes: 22 additions & 0 deletions packages/payment-detection/src/balance-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { PaymentTypes } from '@requestnetwork/types';

/**
* Creates the object IBalanceWithEvents from the error code and error message
*
* @param message error message
* @param code error code
* @returns The object IBalanceWithEvents to return
*/
export default function getBalanceErrorObject(
message: string,
code?: PaymentTypes.BALANCE_ERROR_CODE,
): PaymentTypes.IBalanceWithEvents {
return {
balance: null,
error: {
code: code || PaymentTypes.BALANCE_ERROR_CODE.UNKNOWN,
message,
},
events: [],
};
}
64 changes: 36 additions & 28 deletions packages/payment-detection/src/btc/address-based.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ExtensionTypes, PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';

import getBalanceErrorObject from '../balance-error';
import DefaultBitcoinDetectionProvider from './default-bitcoin-detection-provider';
const bigNumber: any = require('bn.js');

Expand Down Expand Up @@ -79,42 +80,49 @@ export default class PaymentNetworkBTCAddressBased {
networkId: number,
): Promise<PaymentTypes.BTCBalanceWithEvents> {
if (!request.extensions[paymentNetworkId]) {
throw new Error(`The request do not have the extension : ̀${paymentNetworkId}`);
return getBalanceErrorObject(
`The request does not have the extension: ${paymentNetworkId}`,
PaymentTypes.BALANCE_ERROR_CODE.WRONG_EXTENSION,
);
}
const paymentAddress = request.extensions[paymentNetworkId].values.paymentAddress;
const refundAddress = request.extensions[paymentNetworkId].values.refundAddress;

let payments: PaymentTypes.BTCBalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
networkId,
);
}
try {
let payments: PaymentTypes.BTCBalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
networkId,
);
}

let refunds: PaymentTypes.BTCBalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
networkId,
);
}
let refunds: PaymentTypes.BTCBalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
networkId,
);
}

const balance: string = new bigNumber(new bigNumber(payments.balance || 0))
.sub(new bigNumber(refunds.balance || 0))
.toString();
const balance: string = new bigNumber(new bigNumber(payments.balance || 0))
.sub(new bigNumber(refunds.balance || 0))
.toString();

const events: PaymentTypes.BTCPaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));
const events: PaymentTypes.BTCPaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));

return {
balance,
events,
};
return {
balance,
events,
};
} catch (error) {
return getBalanceErrorObject(error.message);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ export default class DefaultBitcoinDetectionProvider
},
elem: PaymentTypes.BTCBalanceWithEvents,
) => {
if (!accumulator[elem.balance]) {
accumulator[elem.balance] = { count: 0, value: elem };
if (elem.balance !== null) {
if (!accumulator[elem.balance]) {
accumulator[elem.balance] = { count: 0, value: elem };
}
accumulator[elem.balance].count++;
}
accumulator[elem.balance].count++;
return accumulator;
},
{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default class PaymentNetworkBTCAddressBased
/**
* Gets the balance and the payment/refund events
*
* @param the request to check
* @param request request to check
* @returns the balance and the payment/refund events
*/
public async getBalance(
Expand Down
78 changes: 42 additions & 36 deletions packages/payment-detection/src/erc20/address-based.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
PaymentTypes,
RequestLogicTypes,
} from '@requestnetwork/types';
import getBalanceErrorObject from '../balance-error';
import Erc20InfoRetriever from './address-based-info-retriever';

const bigNumber: any = require('bn.js');
Expand Down Expand Up @@ -78,54 +79,59 @@ export default class PaymentNetworkERC20AddressBased
request.currency.network = 'mainnet';
}
if (!supportedNetworks.includes(request.currency.network)) {
throw new Error(
return getBalanceErrorObject(
`Payment network ${
request.currency.network
} not supported by ERC20 payment detection. Supported networks: ${supportedNetworks.join(
', ',
)}`,
PaymentTypes.BALANCE_ERROR_CODE.NETWORK_NOT_SUPPORTED,
);
}
const paymentAddress =
request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED].values
.paymentAddress;
const refundAddress =
request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED].values
.refundAddress;
try {
const paymentAddress =
request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED].values
.paymentAddress;
const refundAddress =
request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED].values
.refundAddress;

let payments: PaymentTypes.ERC20BalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
request.currency.network,
request.currency.value,
);
}
let payments: PaymentTypes.ERC20BalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
request.currency.network,
request.currency.value,
);
}

let refunds: PaymentTypes.ERC20BalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
request.currency.network,
request.currency.value,
);
}
let refunds: PaymentTypes.ERC20BalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
request.currency.network,
request.currency.value,
);
}

const balance: string = new bigNumber(payments.balance || 0)
.sub(new bigNumber(refunds.balance || 0))
.toString();
const balance: string = new bigNumber(payments.balance || 0)
.sub(new bigNumber(refunds.balance || 0))
.toString();

const events: PaymentTypes.ERC20PaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));
const events: PaymentTypes.ERC20PaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));

return {
balance,
events,
};
return {
balance,
events,
};
} catch (error) {
return getBalanceErrorObject(error.message);
}
}

/**
Expand Down
106 changes: 64 additions & 42 deletions packages/payment-detection/src/erc20/proxy-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@ import {
RequestLogicTypes,
} from '@requestnetwork/types';
import Utils from '@requestnetwork/utils';
import getBalanceErrorObject from '../balance-error';
import PaymentReferenceCalculator from '../payment-reference-calculator';
import ProxyInfoRetriever from './proxy-info-retriever';

const bigNumber: any = require('bn.js');

// tslint:disable:max-classes-per-file
/** Exception when network not supported */
class NetworkNotSupported extends Error {}
/** Exception when version not supported */
class VersionNotSupported extends Error {}

interface IProxyContractByVersionByNetwork {
[version: string]: {
[network: string]: { address: string; creationBlockNumber: number };
Expand Down Expand Up @@ -108,48 +115,61 @@ export default class PaymentNetworkERC20ProxyContract implements PaymentTypes.IP
const paymentNetwork = request.extensions[paymentNetworkId];

if (!paymentNetwork) {
throw new Error(`The request do not have the extension: ${paymentNetworkId}`);
}

const paymentAddress = paymentNetwork.values.paymentAddress;
const refundAddress = paymentNetwork.values.refundAddress;
const salt = paymentNetwork.values.salt;

let payments: PaymentTypes.IBalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
request,
salt,
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
paymentNetwork.version,
return getBalanceErrorObject(
`The request does not have the extension : ${paymentNetworkId}`,
PaymentTypes.BALANCE_ERROR_CODE.WRONG_EXTENSION,
);
}

let refunds: PaymentTypes.IBalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
request,
salt,
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
paymentNetwork.version,
);
try {
const paymentAddress = paymentNetwork.values.paymentAddress;
const refundAddress = paymentNetwork.values.refundAddress;
const salt = paymentNetwork.values.salt;

let payments: PaymentTypes.IBalanceWithEvents = { balance: '0', events: [] };
if (paymentAddress) {
payments = await this.extractBalanceAndEvents(
request,
salt,
paymentAddress,
PaymentTypes.EVENTS_NAMES.PAYMENT,
paymentNetwork.version,
);
}

let refunds: PaymentTypes.IBalanceWithEvents = { balance: '0', events: [] };
if (refundAddress) {
refunds = await this.extractBalanceAndEvents(
request,
salt,
refundAddress,
PaymentTypes.EVENTS_NAMES.REFUND,
paymentNetwork.version,
);
}

const balance: string = new bigNumber(payments.balance || 0)
.sub(new bigNumber(refunds.balance || 0))
.toString();

const events: PaymentTypes.ERC20PaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));

return {
balance,
events,
};
} catch (error) {
let code: PaymentTypes.BALANCE_ERROR_CODE | undefined;
if (error instanceof NetworkNotSupported) {
code = PaymentTypes.BALANCE_ERROR_CODE.NETWORK_NOT_SUPPORTED;
}
if (error instanceof VersionNotSupported) {
code = PaymentTypes.BALANCE_ERROR_CODE.VERSION_NOT_SUPPORTED;
}
return getBalanceErrorObject(error.message, code);
}

const balance: string = new bigNumber(payments.balance || 0)
.sub(new bigNumber(refunds.balance || 0))
.toString();

const events: PaymentTypes.ERC20PaymentNetworkEvent[] = [
...payments.events,
...refunds.events,
].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));

return {
balance,
events,
};
}

/**
Expand All @@ -172,11 +192,13 @@ export default class PaymentNetworkERC20ProxyContract implements PaymentTypes.IP
const network = request.currency.network;

if (!network) {
throw new Error(`Payment network not supported by ERC20 payment detection`);
throw new NetworkNotSupported(`Payment network not supported by ERC20 payment detection`);
}

if (!PROXY_CONTRACT_ADDRESS_BY_VERSION_BY_NETWORK[paymentNetworkVersion]) {
throw new Error(`Payment network version not supported: ${paymentNetworkVersion}`);
throw new VersionNotSupported(
`Payment network version not supported: ${paymentNetworkVersion}`,
);
}

const proxyContractAddress: string | undefined =
Expand All @@ -186,7 +208,7 @@ export default class PaymentNetworkERC20ProxyContract implements PaymentTypes.IP
.creationBlockNumber;

if (!proxyContractAddress) {
throw new Error(
throw new NetworkNotSupported(
`Network not supported for this payment network: ${request.currency.network}`,
);
}
Expand Down
Loading

0 comments on commit f49640b

Please sign in to comment.