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
57 changes: 40 additions & 17 deletions packages/integration-test/test/node-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const provider = new providers.JsonRpcProvider('http://localhost:8545');
const wallet = Wallet.fromMnemonic(mnemonic).connect(provider);

// eslint-disable-next-line no-magic-numbers
jest.setTimeout(10000);
jest.setTimeout(30000);

const requestCreationHashBTC: Types.IRequestInfo = {
currency: 'BTC',
Expand Down Expand Up @@ -71,6 +71,29 @@ const wrongDecryptionProvider = new EthereumPrivateKeyDecryptionProvider({
method: Types.Encryption.METHOD.ECIES,
});

const waitForConfirmation = async (input: Request | Types.IRequestDataWithEvents) => {
// Create the promise to wait for confirmation.
const waitForConfirmationPromise = new Promise<Types.IRequestDataWithEvents>((resolve) =>
input.on('confirmed', resolve),
);

// In parallel, mine an empty block, because a confirmation needs to wait for two blocks
// (the block that persisted the action + another block).
const mineBlockPromise = provider.send('evm_mine', []);

// Set a time limit to wait for confirmation before throwing.
// Create the error object right away to conserve the context's stacktrace.
const timeoutError = new Error('waiting for confirmation took too long');
const timeout = setTimeout(() => {
throw timeoutError;
}, 5000);

// Return the confirmation result.
const promiseResults = await Promise.all([waitForConfirmationPromise, mineBlockPromise]);
clearTimeout(timeout);
return promiseResults[0];
};

describe('Request client using a request node', () => {
it('can create a request, change the amount and get data', async () => {
// Create a request
Expand All @@ -89,7 +112,7 @@ describe('Request client using a request node', () => {
expect(requestData.meta).toBeDefined();
expect(requestData.pending!.state).toBe(Types.RequestLogic.STATE.CREATED);

requestData = await request.waitForConfirmation();
requestData = await waitForConfirmation(request);
expect(requestData.state).toBe(Types.RequestLogic.STATE.CREATED);
expect(requestData.pending).toBeNull();

Expand All @@ -101,7 +124,7 @@ describe('Request client using a request node', () => {
expect(requestData.meta).toBeDefined();
expect(requestData.pending!.expectedAmount).toBe('800');

requestData = await new Promise((resolve) => requestData.on('confirmed', resolve));
requestData = await waitForConfirmation(requestData);
expect(requestData.expectedAmount).toBe('800');
expect(requestData.pending).toBeNull();
});
Expand Down Expand Up @@ -145,15 +168,15 @@ describe('Request client using a request node', () => {
expect(extension.events[0].name).toBe('create');
expect(extension.events[0].parameters).toEqual(paymentNetwork.parameters);

requestData = await request.waitForConfirmation();
requestData = await waitForConfirmation(request);
expect(requestData.state).toBe(Types.RequestLogic.STATE.CREATED);
expect(requestData.pending).toBeNull();

requestData = await request.declareSentPayment('100', 'bank transfer initiated', payerIdentity);
expect(requestData.balance).toBeDefined();
expect(requestData.balance!.balance).toBe('0');

requestData = await new Promise((resolve) => requestData.on('confirmed', resolve));
requestData = await waitForConfirmation(requestData);
expect(requestData.balance!.balance).toBe('0');

requestData = await request.declareReceivedPayment(
Expand All @@ -164,7 +187,7 @@ describe('Request client using a request node', () => {
expect(requestData.balance).toBeDefined();
expect(requestData.balance!.balance).toBe('0');

requestData = await new Promise((resolve) => requestData.on('confirmed', resolve));
requestData = await waitForConfirmation(requestData);
expect(requestData.balance!.balance).toBe('100');
});

Expand All @@ -187,7 +210,7 @@ describe('Request client using a request node', () => {
signer: payeeIdentity,
topics: topicsRequest1and2,
});
await request1.waitForConfirmation();
await waitForConfirmation(request1);
const timestampBeforeReduce = getCurrentTimestampInSecond();

// make sure that request 2 timestamp is greater than request 1 timestamp
Expand All @@ -209,15 +232,15 @@ describe('Request client using a request node', () => {
topics: topicsRequest1and2,
});

await request2.waitForConfirmation();
await waitForConfirmation(request2);

// reduce request 1
const requestDataReduce = await request1.reduceExpectedAmountRequest('10000000', payeeIdentity);
await new Promise((r) => requestDataReduce.on('confirmed', r));
await waitForConfirmation(requestDataReduce);

// cancel request 1
const requestDataCancel = await request1.cancel(payeeIdentity);
await new Promise((r) => requestDataCancel.on('confirmed', r));
await waitForConfirmation(requestDataCancel);

// get requests without boundaries
let requests = await requestNetwork.fromTopic(topicsRequest1and2[0]);
Expand Down Expand Up @@ -375,7 +398,7 @@ describe('Request client using a request node', () => {
expect(requestData.pending!.state).toBe(Types.RequestLogic.STATE.CREATED);
expect(requestData.meta!.transactionManagerMeta.encryptionMethod).toBe('ecies-aes256-gcm');

await new Promise((resolve) => request.on('confirmed', resolve));
await waitForConfirmation(request);

// Fetch the created request by its id
const fetchedRequest = await requestNetwork.fromRequestId(request.requestId);
Expand All @@ -395,7 +418,7 @@ describe('Request client using a request node', () => {
expect(fetchedRequestData.state).toBe(Types.RequestLogic.STATE.CREATED);

const acceptData = await request.accept(payerIdentity);
await new Promise((resolve) => acceptData.on('confirmed', resolve));
await waitForConfirmation(acceptData);

await fetchedRequest.refresh();
fetchedRequestData = fetchedRequest.getData();
Expand All @@ -405,7 +428,7 @@ describe('Request client using a request node', () => {
requestCreationHashBTC.expectedAmount,
payerIdentity,
);
await new Promise((resolve) => increaseData.on('confirmed', resolve));
await waitForConfirmation(increaseData);

await fetchedRequest.refresh();
expect(fetchedRequest.getData().expectedAmount).toEqual(
Expand All @@ -416,7 +439,7 @@ describe('Request client using a request node', () => {
Number(requestCreationHashBTC.expectedAmount) * 2,
payeeIdentity,
);
await new Promise((resolve) => reduceData.on('confirmed', resolve));
await waitForConfirmation(reduceData);

await fetchedRequest.refresh();
expect(fetchedRequest.getData().expectedAmount).toBe('0');
Expand All @@ -442,7 +465,7 @@ describe('Request client using a request node', () => {
},
[encryptionData.encryptionParams],
);
await encryptedRequest.waitForConfirmation();
await waitForConfirmation(encryptedRequest);

// Create a plain request
const plainRequest = await requestNetwork.createRequest({
Expand Down Expand Up @@ -533,12 +556,12 @@ describe('ERC20 localhost request creation and detection test', () => {
expect(requestData.meta).toBeDefined();
expect(requestData.pending!.state).toBe(Types.RequestLogic.STATE.CREATED);

requestData = await new Promise((resolve) => request.on('confirmed', resolve));
requestData = await waitForConfirmation(request);
expect(requestData.state).toBe(Types.RequestLogic.STATE.CREATED);
expect(requestData.pending).toBeNull();
});

it.only('can create ERC20 requests with any to erc20 proxy', async () => {
it('can create ERC20 requests with any to erc20 proxy', async () => {
const tokenContractAddress = '0x38cF23C52Bb4B13F051Aec09580a2dE845a7FA35';

const currencies: CurrencyInput[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Keyv, { Store } from 'keyv';

/**
* Class for storing confirmed transactions information
* When 'confirmed' event is receive from a 'persistTransaction', the event data are stored.
* When 'confirmed' event is received from a 'persistTransaction', the event data are stored.
* The client can call the getConfirmed entry point, to get the confirmed event.
*/
export default class ConfirmedTransactionStore {
Expand Down
2 changes: 1 addition & 1 deletion packages/request-node/src/request/persistTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default class PersistTransactionHandler {
clientRequest.body.topics,
);

// when the transaction is confirmed, store the information to be serve when requested
// when the transaction is confirmed, store the information to be served when requested
dataAccessResponse.on('confirmed', async (dataAccessConfirmedResponse) => {
await this.confirmedTransactionStore.addConfirmedTransaction(
transactionHash.value,
Expand Down
4 changes: 2 additions & 2 deletions packages/thegraph-data-access/src/data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import TypedEmitter from 'typed-emitter';
import { BigNumber } from 'ethers';

import { getCurrentTimestampInSecond, retry, SimpleLogger } from '@requestnetwork/utils';
import { Block } from '@requestnetwork/data-access';
import { Block, CombinedDataAccess } from '@requestnetwork/data-access';
import { DataAccessTypes, LogTypes, StorageTypes } from '@requestnetwork/types';

import { Transaction } from './queries';
import { SubgraphClient } from './subgraph-client';
import { CombinedDataAccess } from '@requestnetwork/data-access';
import { PendingStore } from './pending-store';
import { RequestInit } from 'graphql-request/dist/types.dom';

Expand Down Expand Up @@ -270,6 +269,7 @@ export class TheGraphDataWrite implements DataAccessTypes.IDataWrite {
};

storageResult.on('confirmed', () => {
this.logger.debug(`Looking for ${storageResult.id} in subgraph`);
retry(
async () => {
const response = await this.graphql.getTransactionsByHash(storageResult.id);
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const retry = <TParams extends unknown[], TReturn>(
maxExponentialBackoffDelay?: number;
} = {},
): ((...params: TParams) => Promise<TReturn>) => {
// If a context was passed in, bind it to to the target function
// If a context was passed in, bind it to the target function
if (context) {
target = target.bind(context);
}
Expand Down