Skip to content

Commit

Permalink
format using biome
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisCarriere committed Nov 19, 2023
1 parent 8672b54 commit c2561f9
Show file tree
Hide file tree
Showing 22 changed files with 490 additions and 207 deletions.
5 changes: 2 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ WEBHOOK_URL=http://127.0.0.1:3000

# Substreams endpoint
SUBSTREAMS_API_TOKEN="<Substreams API Token @ https://pinax.network>"
SUBSTREAMS_ENDPOINT=https://polygon.substreams.pinax.network:9000
SUBSTREAMS_ENDPOINT=https://polygon.substreams.pinax.network:443

# Substreams package
MANIFEST=https://github.com/pinax-network/subtivity-substreams/releases/download/v0.3.0/subtivity-ethereum-v0.3.0.spkg
MODULE_NAME=map_block_stats
START_BLOCK=-1
FINAL_BLOCKS_ONLY=true
START_BLOCK=-1
50 changes: 50 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
},
"files.associations": {
"*.css": "tailwindcss"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": true
}
},
"[ignore]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
}
}
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,12 @@ WEBHOOK_URL=http://127.0.0.1:3000
# Substreams endpoint
SUBSTREAMS_API_TOKEN="<Substreams API Token @ https://pinax.network>"
SUBSTREAMS_ENDPOINT=https://polygon.substreams.pinax.network:9000
SUBSTREAMS_ENDPOINT=https://polygon.substreams.pinax.network:443
# Substreams package
MANIFEST=https://github.com/pinax-network/subtivity-substreams/releases/download/v0.3.0/subtivity-ethereum-v0.3.0.spkg
MODULE_NAME=map_block_stats
START_BLOCK=-1
FINAL_BLOCKS_ONLY=true
```

## Help
Expand Down Expand Up @@ -164,8 +163,7 @@ Options:
--metrics-labels [string...] To apply generic labels to all default metrics (ex: --labels foo=bar) (default: {}, env: METRICS_LABELS)
--collect-default-metrics <boolean> Collect default metrics (default: "false", env: COLLECT_DEFAULT_METRICS)
--headers [string...] Set headers that will be sent on every requests (ex: --headers X-HEADER=headerA) (default: {}, env: HEADERS)
--final-blocks-only <boolean> Only process blocks that have pass finality, to prevent any reorg and undo signal by staying further away from the chain HEAD (default: "false", env:
FINAL_BLOCKS_ONLY)
--final-blocks-only <boolean> Only process blocks that have pass finality, to prevent any reorg and undo signal by staying further away from the chain HEAD (default: "false", env: FINAL_BLOCKS_ONLY)
--verbose <boolean> Enable verbose logging (default: "false", env: VERBOSE)
--webhook-url <string> Webhook URL to send POST (env: WEBHOOK_URL)
--secret-key <string> TweetNaCl Secret-key to sign POST data payload (env: SECRET_KEY)
Expand Down
64 changes: 38 additions & 26 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,54 @@
#!/usr/bin/env node

import pkg from "../package.json" assert { type: "json" };
import { Option } from "commander";
import { commander, logger } from "substreams-sink";
import { keyPair } from "../src/signMessage.js";
import { action } from "../index.js";
import pkg from "../package.json" assert { type: "json" };
import { ping } from "../src/ping.js";
import { Option } from "commander";
import { keyPair } from "../src/signMessage.js";

export interface WebhookRunOptions extends commander.RunOptions {
webhookUrl: string;
secretKey: string;
disablePing: boolean;
webhookUrl: string;
secretKey: string;
disablePing: boolean;
}

// Run Webhook Sink
const program = commander.program(pkg);
const command = commander.run(program, pkg);
command.addOption(new Option("--webhook-url <string>", "Webhook URL to send POST").makeOptionMandatory().env("WEBHOOK_URL"))
command.addOption(new Option("--secret-key <string>", "TweetNaCl Secret-key to sign POST data payload").makeOptionMandatory().env("SECRET_KEY"))
command.addOption(new Option("--disable-ping", "Disable ping on init").env("DISABLE_PING").default(false))
command.addOption(
new Option("--webhook-url <string>", "Webhook URL to send POST").makeOptionMandatory().env("WEBHOOK_URL"),
);
command.addOption(
new Option("--secret-key <string>", "TweetNaCl Secret-key to sign POST data payload")
.makeOptionMandatory()
.env("SECRET_KEY"),
);
command.addOption(new Option("--disable-ping", "Disable ping on init").env("DISABLE_PING").default(false));
command.action(action);

program.command("keypair")
.description("Generate TweetNaCl keypair")
.action(() => {
const { publicKey, secretKey } = keyPair();
console.log(`PUBLIC_KEY=${publicKey}`);
console.log(`SECRET_KEY=${secretKey}`);
})
program
.command("keypair")
.description("Generate TweetNaCl keypair")
.action(() => {
const { publicKey, secretKey } = keyPair();
console.log(`PUBLIC_KEY=${publicKey}`);
console.log(`SECRET_KEY=${secretKey}`);
});

program.command("ping")
.description("Ping Webhook URL")
.addOption(new Option("--webhook-url <string>", "Webhook URL to send POST").makeOptionMandatory().env("WEBHOOK_URL"))
.addOption(new Option("--secret-key <string>", "TweetNaCl Secret-key to sign POST data payload").makeOptionMandatory().env("SECRET_KEY"))
.action(async (options: any) => {
logger.settings.type = "hidden";
const response = await ping(options.webhookUrl, options.secretKey);
if (response) console.log("✅ OK");
else console.log("⁉️ ERROR");
})
program
.command("ping")
.description("Ping Webhook URL")
.addOption(new Option("--webhook-url <string>", "Webhook URL to send POST").makeOptionMandatory().env("WEBHOOK_URL"))
.addOption(
new Option("--secret-key <string>", "TweetNaCl Secret-key to sign POST data payload")
.makeOptionMandatory()
.env("SECRET_KEY"),
)
.action(async (options) => {
logger.settings.type = "hidden";
const response = await ping(options.webhookUrl, options.secretKey);
if (response) console.log("✅ OK");
else console.log("⁉️ ERROR");
});
program.parse();
16 changes: 16 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://biomejs.dev/schemas/1.3.3/schema.json",
"organizeImports": {
"enabled": true
},
"formatter": {
"indentStyle": "space",
"lineWidth": 120
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}
21 changes: 13 additions & 8 deletions examples/bun/http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import nacl from "tweetnacl";
import "dotenv/config";
import nacl from "tweetnacl";

const PORT = process.env.PORT ?? 3000;
const PUBLIC_KEY = process.env.PUBLIC_KEY ?? "a3cb7366ee8ca77225b4d41772e270e4e831d171d1de71d91707c42e7ba82cc9";

console.dir(`Listening on port http://localhost:${PORT}`)
console.dir(`Listening on port http://localhost:${PORT}`);
console.log(`Signature validation using ${PUBLIC_KEY}`);

export default {
Expand All @@ -15,17 +15,23 @@ export default {
const signature = request.headers.get("x-signature-ed25519");
const body = await request.text();

if (!timestamp) return new Response("missing required timestamp in headers", { status: 400 });
if (!signature) return new Response("missing required signature in headers", { status: 400 });
if (!timestamp)
return new Response("missing required timestamp in headers", {
status: 400,
});
if (!signature)
return new Response("missing required signature in headers", {
status: 400,
});
if (!body) return new Response("missing body", { status: 400 });

// validate signature using public key
const isVerified = nacl.sign.detached.verify(
Buffer.from(timestamp + body),
Buffer.from(signature, 'hex'),
Buffer.from(PUBLIC_KEY, 'hex')
Buffer.from(signature, "hex"),
Buffer.from(PUBLIC_KEY, "hex"),
);
console.log({isVerified, timestamp, signature});
console.log({ isVerified, timestamp, signature });
console.log(body);

if (!isVerified) {
Expand All @@ -34,4 +40,3 @@ export default {
return new Response("OK");
},
};

18 changes: 12 additions & 6 deletions examples/deno/http.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import nacl from "npm:tweetnacl";
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { encode } from "https://deno.land/std@0.190.0/encoding/hex.ts";
import "https://deno.land/std@0.190.0/dotenv/load.ts";
import { encode } from "https://deno.land/std@0.190.0/encoding/hex.ts";
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";

const PORT = Deno.env.get("PORT");
const PUBLIC_KEY = Deno.env.get("PUBLIC_KEY");
Expand All @@ -12,19 +12,25 @@ const handler = async (request: Request) => {
const signature = request.headers.get("x-signature-ed25519");
const body = await request.text();

if (!timestamp) return new Response("missing required timestamp in headers", { status: 400 });
if (!signature) return new Response("missing required signature in headers", { status: 400 });
if (!timestamp)
return new Response("missing required timestamp in headers", {
status: 400,
});
if (!signature)
return new Response("missing required signature in headers", {
status: 400,
});
if (!body) return new Response("missing body", { status: 400 });

// TO-DO: 🚨 FIX CODE BELOW 🚨
// validate signature using public key
const isVerified = nacl.sign.detached.verify(
new TextEncoder().encode(timestamp + body),
encode(signature),
encode(PUBLIC_KEY)
encode(PUBLIC_KEY),
);

console.dir({timestamp, signature, isVerified});
console.dir({ timestamp, signature, isVerified });
console.dir(body);
if (!isVerified) {
return new Response("invalid request signature", { status: 401 });
Expand Down
1 change: 1 addition & 0 deletions examples/express/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!http.js
39 changes: 39 additions & 0 deletions examples/express/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import "dotenv/config";
import express from "express";
import nacl from "tweetnacl";

const PORT = process.env.PORT ?? 3000;
const PUBLIC_KEY = process.env.PUBLIC_KEY ?? "a3cb7366ee8ca77225b4d41772e270e4e831d171d1de71d91707c42e7ba82cc9";
const app = express();

app.use(express.text({ type: "application/json" }));

app.use(async (req, res) => {
// get headers and body from POST request
const timestamp = req.headers["x-signature-timestamp"];
const signature = req.headers["x-signature-ed25519"];
const body = req.body;

if (!timestamp) return res.send("missing required timestamp in headers").status(400);
if (!signature) return res.send("missing required signature in headers").status(400);
if (!body) return res.send("missing body").status(400);

// validate signature using public key
const isVerified = nacl.sign.detached.verify(
Buffer.from(timestamp + body),
Buffer.from(signature, "hex"),
Buffer.from(PUBLIC_KEY, "hex"),
);

console.dir({ timestamp, signature, isVerified });
console.dir(body);
if (!isVerified) {
return res.send("invalid request signature").status(401);
}
return res.send("OK").status(200);
});

app.listen(PORT, () => {
console.log(`Listening on port http://localhost:${PORT}`);
console.log(`Signature validation using ${PUBLIC_KEY}`);
});
22 changes: 12 additions & 10 deletions examples/node/http.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import nacl from "tweetnacl";
import * as http from "node:http";
import "dotenv/config";
import nacl from "tweetnacl";

const PORT = process.env.PORT ?? 3000;
const PUBLIC_KEY = process.env.PUBLIC_KEY ?? "a3cb7366ee8ca77225b4d41772e270e4e831d171d1de71d91707c42e7ba82cc9";
const server = http.createServer();

function rawBody(request: http.IncomingMessage) {
return new Promise<string>((resolve, reject) => {
let chunks: Uint8Array[] = [];
request.on('data', (chunk) => {
chunks.push(chunk);
}).on('end', () => {
resolve(Buffer.concat(chunks).toString());
const chunks: Uint8Array[] = [];
request
.on("data", (chunk) => {
chunks.push(chunk);
})
.on("end", () => {
resolve(Buffer.concat(chunks).toString());
});
});
}

// Create a local server to serve Prometheus gauges
server.on("request", async (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });

// get headers and body from POST request
const timestamp = String(req.headers["x-signature-timestamp"]);
Expand All @@ -33,11 +35,11 @@ server.on("request", async (req, res) => {
// validate signature using public key
const isVerified = nacl.sign.detached.verify(
Buffer.from(timestamp + body),
Buffer.from(signature, 'hex'),
Buffer.from(PUBLIC_KEY, 'hex')
Buffer.from(signature, "hex"),
Buffer.from(PUBLIC_KEY, "hex"),
);

console.dir({timestamp, signature, isVerified});
console.dir({ timestamp, signature, isVerified });
console.dir(body);
if (!isVerified) {
return res.writeHead(401).end("invalid request signature");
Expand Down
Loading

0 comments on commit c2561f9

Please sign in to comment.