Skip to content

Commit df02cdf

Browse files
committed
feat: add createManyConcurrentRequests.js script
1 parent 15cf931 commit df02cdf

File tree

3 files changed

+316
-2
lines changed

3 files changed

+316
-2
lines changed

package-lock.json

Lines changed: 148 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
"@requestnetwork/epk-signature": "0.9.5",
2020
"@requestnetwork/payment-processor": "0.52.0",
2121
"@requestnetwork/request-client.js": "0.54.0",
22+
"cli-progress": "^3.12.0",
2223
"dotenv": "16.3.1",
23-
"ethers": "5.7.2"
24+
"ethers": "5.7.2",
25+
"p-limit": "^6.2.0"
2426
},
2527
"devDependencies": {
2628
"husky": "8.0.3",
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
(async () => {
2+
const {
3+
RequestNetwork,
4+
Types,
5+
Utils,
6+
} = require("@requestnetwork/request-client.js");
7+
const {
8+
EthereumPrivateKeySignatureProvider,
9+
} = require("@requestnetwork/epk-signature");
10+
const { config } = require("dotenv");
11+
const { Wallet } = require("ethers");
12+
const pLimit = (await import("p-limit")).default; // Use dynamic import for ESM module
13+
const cliProgress = require("cli-progress");
14+
15+
// --- Configuration ---
16+
const TOTAL_REQUESTS = 100; // Total number of requests to create
17+
const CONCURRENCY_LIMIT = 10; // Number of requests to create concurrently
18+
// ---------------------
19+
20+
// Load environment variables from .env file
21+
config();
22+
23+
if (!process.env.PAYEE_PRIVATE_KEY) {
24+
console.error("Error: PAYEE_PRIVATE_KEY is not defined in the .env file.");
25+
process.exit(1);
26+
}
27+
28+
let aborted = false;
29+
let successfulRequests = 0;
30+
let failedRequests = 0;
31+
32+
// Setup Abort Handling (Ctrl+C)
33+
process.on("SIGINT", () => {
34+
console.log("\nAborting request creation...");
35+
aborted = true;
36+
});
37+
38+
// Setup Progress Bar
39+
const progressBar = new cliProgress.SingleBar(
40+
{},
41+
cliProgress.Presets.shades_classic,
42+
);
43+
44+
try {
45+
const epkSignatureProvider = new EthereumPrivateKeySignatureProvider({
46+
method: Types.Signature.METHOD.ECDSA,
47+
privateKey: process.env.PAYEE_PRIVATE_KEY, // Must include 0x prefix
48+
});
49+
50+
const requestClient = new RequestNetwork({
51+
nodeConnectionConfig: {
52+
baseURL: "http://localhost:3000/",
53+
},
54+
signatureProvider: epkSignatureProvider,
55+
});
56+
57+
// In this example, the payee is also the payer and payment recipient.
58+
const payeeIdentity = new Wallet(process.env.PAYEE_PRIVATE_KEY).address;
59+
const payerIdentity = payeeIdentity;
60+
const paymentRecipient = payeeIdentity;
61+
const feeRecipient = "0x0000000000000000000000000000000000000000";
62+
63+
const limit = pLimit(CONCURRENCY_LIMIT);
64+
const creationPromises = [];
65+
66+
console.log(
67+
`Attempting to create ${TOTAL_REQUESTS} requests with concurrency ${CONCURRENCY_LIMIT}...`,
68+
);
69+
progressBar.start(TOTAL_REQUESTS, 0);
70+
71+
for (let i = 0; i < TOTAL_REQUESTS; i++) {
72+
if (aborted) {
73+
console.log(`Skipping remaining requests due to abort signal.`);
74+
break; // Stop adding new tasks if aborted
75+
}
76+
77+
creationPromises.push(
78+
limit(async () => {
79+
// Double-check abort flag before starting the async operation
80+
if (aborted) {
81+
return;
82+
}
83+
84+
try {
85+
// Use a unique identifier or timestamp if content needs variation
86+
const uniqueContent = `Request #${i + 1} - ${Date.now()}`;
87+
88+
const requestCreateParameters = {
89+
requestInfo: {
90+
currency: {
91+
type: Types.RequestLogic.CURRENCY.ERC20,
92+
value: "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C",
93+
network: "sepolia",
94+
},
95+
expectedAmount: "1000000000000000000",
96+
payee: {
97+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
98+
value: payeeIdentity,
99+
},
100+
payer: {
101+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
102+
value: payerIdentity,
103+
},
104+
timestamp: Utils.getCurrentTimestampInSecond(),
105+
},
106+
paymentNetwork: {
107+
id: Types.Extension.PAYMENT_NETWORK_ID.ERC20_FEE_PROXY_CONTRACT,
108+
parameters: {
109+
paymentNetworkName: "sepolia",
110+
paymentAddress: paymentRecipient,
111+
feeAddress: feeRecipient,
112+
feeAmount: "0",
113+
},
114+
},
115+
contentData: {
116+
reason: `🍕 - ${uniqueContent}`,
117+
dueDate: "2023.06.16",
118+
},
119+
signer: {
120+
type: Types.Identity.TYPE.ETHEREUM_ADDRESS,
121+
value: payeeIdentity,
122+
},
123+
};
124+
125+
const request = await requestClient.createRequest(
126+
requestCreateParameters,
127+
);
128+
const requestData = await request.waitForConfirmation();
129+
successfulRequests++;
130+
} catch (error) {
131+
console.error(
132+
`\nFailed to create request: ${error.message || error}`,
133+
);
134+
failedRequests++;
135+
} finally {
136+
// Ensure progress bar updates even if aborted after starting the task
137+
if (!aborted) {
138+
progressBar.increment();
139+
}
140+
}
141+
}),
142+
);
143+
}
144+
145+
// Wait for all queued promises to settle
146+
await Promise.all(creationPromises);
147+
} catch (error) {
148+
console.error(`\nAn unexpected error occurred: ${error.message || error}`);
149+
aborted = true; // Stop progress bar on unexpected errors
150+
} finally {
151+
progressBar.stop();
152+
console.log("\n--- Request Creation Summary ---");
153+
console.log(`Total attempted: ${successfulRequests + failedRequests}`);
154+
console.log(`Successful: ${successfulRequests}`);
155+
console.log(`Failed: ${failedRequests}`);
156+
if (aborted && successfulRequests + failedRequests < TOTAL_REQUESTS) {
157+
console.log(
158+
`Process aborted. ${
159+
TOTAL_REQUESTS - (successfulRequests + failedRequests)
160+
} requests were not attempted.`,
161+
);
162+
}
163+
console.log("------------------------------");
164+
}
165+
})();

0 commit comments

Comments
 (0)