Skip to content
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
4 changes: 3 additions & 1 deletion packages/integration-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
"clean": "shx rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo",
"lint": "eslint \"test/**/*.ts\"",
"test": "run-s test:node test:layers",
"test:scheduled": "run-s test:erc20 test:erc777 test:btc ",
"test:scheduled": "run-s test:erc20 test:any test:erc777 test:eth test:btc ",
"test:layers": "jest test/layers.test.ts --forceExit",
"test:node": "jest test/node-client.test.ts --forceExit",
"test:any": "jest test/scheduled/any*.test.ts --forceExit",
"test:eth": "jest test/scheduled/eth*.test.ts --forceExit",
"test:erc20": "jest test/scheduled/erc20*.test.ts --forceExit",
"test:erc777": "jest test/scheduled/erc777*.test.ts --forceExit",
"test:btc": "jest test/scheduled/btc.test.ts --forceExit"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { PaymentNetworkFactory } from '@requestnetwork/payment-detection';
import { CurrencyTypes, PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';
import { CurrencyManager } from '@requestnetwork/currency';

import { mockAdvancedLogic } from './mocks';
import { createMockConversionErc20Request } from '../utils';

const pnFactory = new PaymentNetworkFactory(mockAdvancedLogic, CurrencyManager.getDefault());

const paidEURRequest = {
network: 'matic' as CurrencyTypes.EvmChainName,
requestId: '0117d7a59a48e5031b3c56c92621453149e4a4462dba6eaeb3271a995c4201448b',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: '5ddb1c1645ac2daf',
tokenAddress: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', // DAI on matic
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '0',
currency: {
type: RequestLogicTypes.CURRENCY.ISO4217,
value: 'EUR',
},
};

describe('Any to ERC20 Fee Proxy detection test-suite', () => {
it('can getBalance on a matic request with TheGraph', async () => {
const mockRequest = createMockConversionErc20Request(paidEURRequest);
const paymentDetector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(paymentDetector).toBeDefined();

const balance = await paymentDetector!.getBalance(mockRequest);

expect(balance.balance).toBe('10');
expect(balance.events).toHaveLength(1);
expect(balance.events[0].name).toBe('payment');
const params = balance.events[0].parameters as PaymentTypes.IERC20FeePaymentEventParameters;
expect(params?.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('10');
expect(balance.events[0].timestamp).toBe(1679579206);
});

it('cannot trick getBalance with a payment denominated in the wrong currency', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was failing 😱

const mockRequest = createMockConversionErc20Request({
...paidEURRequest,
currency: {
type: RequestLogicTypes.CURRENCY.ISO4217,
value: 'JPY',
},
});
const paymentDetector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(paymentDetector).toBeDefined();

const balance = await paymentDetector!.getBalance(mockRequest);

expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { PaymentNetworkFactory } from '@requestnetwork/payment-detection';
import { CurrencyTypes, PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';
import { CurrencyManager } from '@requestnetwork/currency';

import { mockAdvancedLogic } from './mocks';
import { createMockConversionEthTokenRequest } from '../utils';

const pnFactory = new PaymentNetworkFactory(mockAdvancedLogic, CurrencyManager.getDefault());

const paidEURRequest = {
network: 'matic' as CurrencyTypes.EvmChainName,
requestId: '01814304b39265cbf0c2abb4f3c7e8432d1e2c8779be6022e545d25f95144360e0',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: 'b3f2e478374bff64',
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '0',
currency: {
type: RequestLogicTypes.CURRENCY.ISO4217,
value: 'EUR',
},
};

describe('Any to ETH Fee Proxy detection test-suite (with a TheGraph Retriever)', () => {
it('can getBalance on a matic request', async () => {
const mockRequest = createMockConversionEthTokenRequest(paidEURRequest);

const detector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(detector).not.toBeNull();
const balance = await detector!.getBalance(mockRequest);

expect(balance.balance).toBe('500'); // 5 EUR
expect(balance.events).toHaveLength(1);
expect(balance.events[0].name).toBe('payment');
const params = balance.events[0].parameters as PaymentTypes.ETHPaymentNetworkEventParameters;
expect(params?.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('500');
expect(balance.events[0].timestamp).toBe(1679673909);
});

it('cannot trick getBalance with a payment denominated in the wrong currency', async () => {
const mockRequest = createMockConversionEthTokenRequest({
...paidEURRequest,
currency: {
type: RequestLogicTypes.CURRENCY.ISO4217,
value: 'USD',
},
});

const detector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(detector).not.toBeNull();
const balance = await detector!.getBalance(mockRequest);

expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
});
});
97 changes: 50 additions & 47 deletions packages/integration-test/test/scheduled/erc20-fee-proxy.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Erc20PaymentNetwork } from '@requestnetwork/payment-detection';
import { PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';
import { CurrencyManager } from '@requestnetwork/currency';
import { PaymentNetworkFactory } from '@requestnetwork/payment-detection';
import { CurrencyTypes, PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';
import { Types, Utils } from '@requestnetwork/request-client.js';

import { mockAdvancedLogic } from './mocks';
import { Types, Utils } from '@requestnetwork/request-client.js';
import {
erc20requestCreationHash,
localErc20PaymentNetworkParams,
Expand All @@ -14,13 +14,26 @@ import {
} from './fixtures';
import { createMockErc20FeeRequest } from '../utils';

const erc20FeeProxy = new Erc20PaymentNetwork.ERC20FeeProxyPaymentDetector({
advancedLogic: mockAdvancedLogic,
currencyManager: CurrencyManager.getDefault(),
getSubgraphClient: jest.fn(),
});

describe('ERC20 Fee Proxy detection test-suite', () => {
const pnFactory = new PaymentNetworkFactory(mockAdvancedLogic, CurrencyManager.getDefault());

const paidRequest = {
network: 'matic' as CurrencyTypes.EvmChainName,
requestId: '014bcd076791fb915af457df1d3f26c81ff66f7e278e4a18f0e48a1705572a6306',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: '8c5ea6f8b4a14fe0',
tokenAddress: '0x282d8efce846a88b159800bd4130ad77443fa1a1', // OCEAN
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '1000000000000000',
};

describe('ERC20 Fee Proxy detection test-suite (with a TheGraph Retriever)', () => {
const getFeeProxyDetector = (
request: RequestLogicTypes.IRequest,
): PaymentTypes.IPaymentNetwork => {
const erc20FeeProxy = pnFactory.getPaymentNetworkFromRequest(request);
expect(erc20FeeProxy).toBeDefined();
return erc20FeeProxy!;
};
it('can getBalance on a mainnet request', async () => {
const mockRequest = createMockErc20FeeRequest({
network: 'mainnet',
Expand All @@ -32,6 +45,7 @@ describe('ERC20 Fee Proxy detection test-suite', () => {
feeAmount: '10',
});

const erc20FeeProxy = getFeeProxyDetector(mockRequest);
const balance = await erc20FeeProxy.getBalance(mockRequest);

expect(balance.balance).toBe('1000000000000000000');
Expand All @@ -41,51 +55,35 @@ describe('ERC20 Fee Proxy detection test-suite', () => {
expect(params?.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('1000000000000000000');
expect(balance.events[0].timestamp).toBe(1599070058);
}, 10000);
});

it('can getBalance on a rinkeby request', async () => {
const mockRequest = createMockErc20FeeRequest({
network: 'rinkeby',
requestId: '0188791633ff0ec72a7dbdefb886d2db6cccfa98287320839c2f173c7a4e3ce7e1',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: '0ee84db293a752c6',
tokenAddress: '0xFab46E002BbF0b4509813474841E0716E6730136', // FAU
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '1000000000000000',
});
it('can getBalance on a matic request', async () => {
const mockRequest = createMockErc20FeeRequest(paidRequest);

const erc20FeeProxy = getFeeProxyDetector(mockRequest);
const balance = await erc20FeeProxy.getBalance(mockRequest);

expect(balance.balance).toBe('1000000000000000000000');
expect(balance.balance).toBe('1000000000000000000');
expect(balance.events).toHaveLength(1);
expect(balance.events[0].name).toBe('payment');
const params = balance.events[0].parameters as PaymentTypes.IERC20FeePaymentEventParameters;
expect(params?.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('1000000000000000000000');
expect(balance.events[0].timestamp).toBe(1599013969);
}, 10000);
expect(params.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('1000000000000000000');
expect(balance.events[0].timestamp).toBe(1621953168);
});

it('can getBalance on a matic request, with TheGraph', async () => {
it('getBalance = 0 if a payment is made with another token', async () => {
const mockRequest = createMockErc20FeeRequest({
network: 'matic',
requestId: '014bcd076791fb915af457df1d3f26c81ff66f7e278e4a18f0e48a1705572a6306',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: '8c5ea6f8b4a14fe0',
tokenAddress: '0x282d8efce846a88b159800bd4130ad77443fa1a1', // FAU
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '1000000000000000',
...paidRequest,
tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // The request is paid with another token
});

const erc20FeeProxy = getFeeProxyDetector(mockRequest);
const balance = await erc20FeeProxy.getBalance(mockRequest);

expect(balance.balance).toBe('1000000000000000000');
expect(balance.events).toHaveLength(1);
expect(balance.events[0].name).toBe('payment');
const params = balance.events[0].parameters as PaymentTypes.IERC20FeePaymentEventParameters;
expect(params.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('1000000000000000000');
expect(balance.events[0].timestamp).toBe(1621953168);
}, 15000);
expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
});

it('can getBalance for a payment declared by the payee', async () => {
// Create a request
Expand All @@ -99,15 +97,17 @@ describe('ERC20 Fee Proxy detection test-suite', () => {
let requestData = await request.declareReceivedPayment('1', 'OK', payeeIdentity, '0x1234');
const declarationTimestamp = Utils.getCurrentTimestampInSecond();
requestData = await new Promise((resolve): any => requestData.on('confirmed', resolve));

const balance = await erc20FeeProxy.getBalance({
const updatedRequest: RequestLogicTypes.IRequest = {
...requestData,
currency: {
network: 'private',
type: RequestLogicTypes.CURRENCY.ERC20,
value: privateErc20Address,
},
});
};

const erc20FeeProxy = getFeeProxyDetector(updatedRequest);
const balance = await erc20FeeProxy.getBalance(updatedRequest);

expect(balance.balance).toBe('1');
expect(balance.events).toHaveLength(1);
Expand All @@ -131,14 +131,17 @@ describe('ERC20 Fee Proxy detection test-suite', () => {
payerIdentity,
);
requestData = await new Promise((resolve): any => requestData.on('confirmed', resolve));
const balance = await erc20FeeProxy.getBalance({
const updatedRequest: RequestLogicTypes.IRequest = {
...requestData,
currency: {
network: 'private',
type: RequestLogicTypes.CURRENCY.ERC20,
value: privateErc20Address,
},
});
};

const erc20FeeProxy = getFeeProxyDetector(updatedRequest);
const balance = await erc20FeeProxy.getBalance(updatedRequest);
expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
}, 15000);
Expand Down
54 changes: 52 additions & 2 deletions packages/integration-test/test/scheduled/eth-input-data.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { EthInputDataPaymentDetector } from '@requestnetwork/payment-detection';
import { RequestLogicTypes } from '@requestnetwork/types';
import {
EthInputDataPaymentDetector,
PaymentNetworkFactory,
} from '@requestnetwork/payment-detection';
import { PaymentTypes, RequestLogicTypes } from '@requestnetwork/types';
import { CurrencyManager } from '@requestnetwork/currency';

import { mockAdvancedLogic } from './mocks';
Expand All @@ -12,6 +15,7 @@ import {
privateErc20Address,
requestNetwork,
} from './fixtures';
import { createMockNativeTokenRequest } from '../utils';

const ethInputContract = new EthInputDataPaymentDetector({
advancedLogic: mockAdvancedLogic,
Expand Down Expand Up @@ -78,4 +82,50 @@ describe('ETH Fee proxy detection test-suite', () => {
expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
});
describe('with a TheGraph Retriever', () => {
it('getBalance of ETHFeeProxy request', async () => {
const pnFactory = new PaymentNetworkFactory(mockAdvancedLogic, CurrencyManager.getDefault());
const mockRequest = createMockNativeTokenRequest({
network: 'matic',
requestId: '01b3b6fe1ac1031f96d1c44714766be12fd3ef7047d2b7c04f9bd4b7ea928edc64',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: '4b297a41ff3b247a',
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '0',
nativeTokenCode: 'MATIC',
});

const detector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(detector).not.toBeNull();
const balance = await detector!.getBalance(mockRequest);

expect(balance.balance).toBe('5000000000000000000'); // 5 MATIC
expect(balance.events).toHaveLength(1);
expect(balance.events[0].name).toBe('payment');
const params = balance.events[0].parameters as PaymentTypes.ETHPaymentNetworkEventParameters;
expect(params?.to).toBe('0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93');
expect(balance.events[0].amount).toBe('5000000000000000000');
expect(balance.events[0].timestamp).toBe(1679673933);
});
it('getBalance=0 for an ETHFeeProxy request paid with conversion', async () => {
const pnFactory = new PaymentNetworkFactory(mockAdvancedLogic, CurrencyManager.getDefault());
const mockRequest = createMockNativeTokenRequest({
network: 'matic',
requestId: '01814304b39265cbf0c2abb4f3c7e8432d1e2c8779be6022e545d25f95144360e0',
paymentAddress: '0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93',
salt: 'b3f2e478374bff64',
feeAddress: '0x35d0e078755cd84d3e0656caab417dee1d7939c7',
feeAmount: '0',
nativeTokenCode: 'MATIC',
});

const detector = pnFactory.getPaymentNetworkFromRequest(mockRequest);
expect(detector).not.toBeNull();
const balance = await detector!.getBalance(mockRequest);

// No payment, although there is a MATIC payment with conversion for the same reference & payment address
expect(balance.balance).toBe('0');
expect(balance.events).toHaveLength(0);
});
});
});
Loading