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
3 changes: 3 additions & 0 deletions resources/mock-server/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Finder (MacOS) folder config
.DS_Store


.tmp/
35 changes: 35 additions & 0 deletions resources/mock-server/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "bun",
"request": "launch",
"name": "Debug Replay Server",
"program": "${workspaceFolder}/bin/server.ts",
"args": ["algod"], // Change to: algod, indexer, or kmd
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": false,
"env": {
"NODE_ENV": "development",
"LOG_LEVEL": "debug"
}
},
{
"type": "bun",
"request": "launch",
"name": "Debug Record",
"program": "${workspaceFolder}/bin/record.ts",
"args": ["algod", "record-new"], // Change client: algod, indexer, kmd | mode: record-new, record-overwrite
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"watchMode": false,
"env": {
"NODE_ENV": "development"
}
}
]
}
6 changes: 6 additions & 0 deletions resources/mock-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ To run:
bun run index.ts
```

## Debugging

To debug in VS Code/Cursor, install the [Bun extension](https://marketplace.visualstudio.com/items?itemName=oven.bun-vscode) (`oven.bun-vscode`), then press F5 to start the debugger.

---

This project was created using `bun init` in bun v1.2.15. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ NodeStatusResponse {
"catchpointVerifiedKvs": 0,
"catchupTime": 0n,
"lastCatchpoint": "",
"lastRound": 17n,
"lastRound": 57490072n,
"lastVersion": "https://github.com/algorandfoundation/specs/tree/953304de35264fc3ef91bcd05c123242015eeaed",
"nextVersion": "https://github.com/algorandfoundation/specs/tree/953304de35264fc3ef91bcd05c123242015eeaed",
"nextVersionRound": 18n,
"nextVersionRound": 57490073n,
"nextVersionSupported": true,
"stoppedAtUnsupportedRound": false,
"timeSinceLastRound": 152696395985404n,
"timeSinceLastRound": 998402345n,
"upgradeDelay": undefined,
"upgradeNextProtocolVoteBefore": undefined,
"upgradeNoVotes": undefined,
Expand All @@ -42,8 +42,8 @@ HealthCheck {
"dbAvailable": true,
"errors": undefined,
"isMigrating": false,
"message": "0",
"round": 0n,
"message": "57490591",
"round": 57490591n,
"version": "3.9.0",
}
`;
Expand Down
51 changes: 51 additions & 0 deletions resources/mock-server/__test__/record.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { describe, it, expect, afterEach } from "vitest";
import { record } from "../src/index";
import { Algodv2 } from "algosdk";
import fs from "fs";
import path from "path";

const TEST_RECORDINGS_DIR = path.resolve(__dirname, "../recordings-test");

describe("Recording Tests", () => {
afterEach(async () => {
// Clean up test recordings directory completely
if (fs.existsSync(TEST_RECORDINGS_DIR)) {
fs.rmSync(TEST_RECORDINGS_DIR, { recursive: true, force: true });
}
});

it("should record in record-new mode", async () => {
// Create test recordings directory
fs.mkdirSync(TEST_RECORDINGS_DIR, { recursive: true });

// Create recording with record-new using TestNet
await record(
"algod",
async () => {
const algod = new Algodv2(
"a".repeat(64),
"https://testnet-api.4160.nodely.dev",
443
);
await algod.status().do();
},
"record-new",
TEST_RECORDINGS_DIR
);

// Verify HAR file was created
const harFiles = fs.readdirSync(TEST_RECORDINGS_DIR, { recursive: true });
const harFileName = harFiles.find((f) =>
f.toString().endsWith("recording.har")
);
expect(harFileName).toBeDefined();

const harPath = path.join(TEST_RECORDINGS_DIR, harFileName!.toString());
expect(fs.existsSync(harPath)).toBe(true);

// Verify HAR file has entries
const content = fs.readFileSync(harPath, "utf-8");
const har = JSON.parse(content);
expect(har.log.entries.length).toBeGreaterThan(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { startServer, type ServerInstance } from "../src/server";
import { Algodv2, Indexer, Kmd } from "algosdk";

const PollyError = "PollyError";
const NON_EXISTENT_ADDRESS = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ";

describe("Algod Mock Server", () => {
let algodServer: ServerInstance;
Expand All @@ -24,7 +25,7 @@ describe("Algod Mock Server", () => {

it("should fail with unrecorded endpoint", async () => {
try {
await algodClient.genesis().do();
await algodClient.accountInformation(NON_EXISTENT_ADDRESS).do();
} catch (error: any) {
expect(Buffer.from(error.response.body).toString()).toContain(PollyError);
return;
Expand Down
13 changes: 10 additions & 3 deletions resources/mock-server/bin/server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import type { Client } from "../src/index.ts";
import { startServer } from "../src/server.ts";

const client = process.argv[2];
const server = await startServer(client as Client);
const client = process.argv[2] as Client;
const recordingsDir = process.argv[3];

await server.listen;
console.log(`Starting ${client} mock server in replay mode...`);
if (recordingsDir) {
console.log(`Recordings directory: ${recordingsDir}`);
}

const server = await startServer(client, recordingsDir);

console.log(`✓ Server listening on port ${server.port}`);
9 changes: 0 additions & 9 deletions resources/mock-server/bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"name": "pollyjs-server",
"dependencies": {
"@pollyjs/adapter-fetch": "^6.0.7",
"@pollyjs/adapter-node-http": "^6.0.6",
"@pollyjs/core": "^6.0.6",
"@pollyjs/persister-fs": "^6.0.6",
"algosdk": "^3.5.2",
Expand Down Expand Up @@ -94,8 +93,6 @@

"@pollyjs/adapter-fetch": ["@pollyjs/[email protected]", "", { "dependencies": { "@pollyjs/adapter": "^6.0.6", "@pollyjs/utils": "^6.0.6", "to-arraybuffer": "^1.0.1" } }, "sha512-kv44DROx/2qzlcgS71EccGr2/I5nK40Xt92paGNI+1/Kmz290bw/ykt8cvXDg4O4xCc9Fh/jXeAkS7qwGpCx2g=="],

"@pollyjs/adapter-node-http": ["@pollyjs/[email protected]", "", { "dependencies": { "@pollyjs/adapter": "^6.0.6", "@pollyjs/utils": "^6.0.6", "lodash-es": "^4.17.21", "nock": "^13.2.1" } }, "sha512-jdJG7oncmSHZAtVMmRgOxh5A56b7G8H9ULlk/ZaVJ+jNrlFXhLmPpx8OQoSF4Cuq2ugdiWmwmAjFXHStcpY3Mw=="],

"@pollyjs/core": ["@pollyjs/[email protected]", "", { "dependencies": { "@pollyjs/utils": "^6.0.6", "@sindresorhus/fnv1a": "^2.0.1", "blueimp-md5": "^2.19.0", "fast-json-stable-stringify": "^2.1.0", "is-absolute-url": "^3.0.3", "lodash-es": "^4.17.21", "loglevel": "^1.8.0", "route-recognizer": "^0.3.4", "slugify": "^1.6.3" } }, "sha512-1ZZcmojW8iSFmvHGeLlvuudM3WiDV842FsVvtPAo3HoAYE6jCNveLHJ+X4qvonL4enj1SyTF3hXA107UkQFQrA=="],

"@pollyjs/node-server": ["@pollyjs/[email protected]", "", { "dependencies": { "@pollyjs/utils": "^6.0.6", "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", "fs-extra": "^10.0.0", "http-graceful-shutdown": "^3.1.5", "morgan": "^1.10.0", "nocache": "^3.0.1" } }, "sha512-nkP1+hdNoVOlrRz9R84haXVsaSmo8Xmq7uYK9GeUMSLQy4Fs55ZZ9o2KI6vRA8F6ZqJSbC31xxwwIoTkjyP7Vg=="],
Expand Down Expand Up @@ -352,8 +349,6 @@

"json-schema-traverse": ["[email protected]", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],

"json-stringify-safe": ["[email protected]", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="],

"jsonfile": ["[email protected]", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],

"light-my-request": ["[email protected]", "", { "dependencies": { "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A=="],
Expand Down Expand Up @@ -390,8 +385,6 @@

"nocache": ["[email protected]", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="],

"nock": ["[email protected]", "", { "dependencies": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" } }, "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ=="],

"object-assign": ["[email protected]", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],

"object-inspect": ["[email protected]", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
Expand Down Expand Up @@ -426,8 +419,6 @@

"process-warning": ["[email protected]", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],

"propagate": ["[email protected]", "", {}, "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag=="],

"proxy-addr": ["[email protected]", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],

"pump": ["[email protected]", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
Expand Down
18 changes: 18 additions & 0 deletions resources/mock-server/mock-server.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"folders": [
{
"name": "mock-server",
"path": "."
}
],
// Workspace-specific VS Code settings
"settings": {
// Path to the TypeScript language server to use for IntelliSense and type checking
// Points to the workspace's local typescript package instead of VS Code's built-in version
"typescript.tsdk": "node_modules/typescript/lib",

// When true, VS Code will prompt to use the workspace TypeScript version
// This ensures consistency between CLI builds and editor type checking
"typescript.enablePromptUseWorkspaceTsdk": true
}
}
Loading