@shunt-network/verify 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export type VerifyResult = {
2
2
  ok: true;
3
3
  requestId: string;
4
+ agent?: string;
4
5
  } | {
5
6
  ok: false;
6
- reason: "missing_headers" | "stale_timestamp" | "bad_signature" | "replay";
7
+ reason: "missing_headers" | "stale_timestamp" | "bad_signature" | "agent_required" | "replay";
7
8
  };
8
9
  export interface VerifyInput {
9
10
  secret: string | string[];
@@ -13,6 +14,8 @@ export interface VerifyInput {
13
14
  getHeader: (name: string) => string | undefined | null;
14
15
  maxSkewSec?: number;
15
16
  replayCache?: ReplayCache;
17
+ /** Reject requests that carry no signed agent identity (v1 signatures). */
18
+ requireAgent?: boolean;
16
19
  }
17
20
  export declare class ReplayCache {
18
21
  private ttlMs;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,eAAe,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE9F,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,qBAAa,WAAW;IAEV,OAAO,CAAC,KAAK;IADzB,OAAO,CAAC,IAAI,CAA6B;IACzC,YAAoB,KAAK,SAAc,EAAI;IAC3C,8CAA8C;IAC9C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMzB;CACF;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,YAAY,CA4BxD"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EACF,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,GAChB,QAAQ,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,qBAAa,WAAW;IAEV,OAAO,CAAC,KAAK;IADzB,OAAO,CAAC,IAAI,CAA6B;IACzC,YAAoB,KAAK,SAAc,EAAI;IAC3C,8CAA8C;IAC9C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMzB;CACF;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,YAAY,CA6CxD"}
package/dist/core.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ const AGENT_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/; // base58 Solana pubkey
2
3
  export class ReplayCache {
3
4
  ttlMs;
4
5
  seen = new Map();
@@ -20,14 +21,31 @@ export class ReplayCache {
20
21
  export function verifyShunt(i) {
21
22
  const ts = i.getHeader("x-shunt-timestamp");
22
23
  const rid = i.getHeader("x-shunt-request-id");
23
- const sig = (i.getHeader("x-shunt-signature") ?? "").replace(/^v1=/, "");
24
- if (!ts || !rid || !sig)
24
+ const m = /^(v1|v2)=([0-9a-f]+)$/.exec(i.getHeader("x-shunt-signature") ?? "");
25
+ if (!ts || !rid || !m)
25
26
  return { ok: false, reason: "missing_headers" };
27
+ const version = m[1];
28
+ const sig = m[2];
29
+ // Only v2 signatures cover the agent, so only v2 can produce a trusted agent.
30
+ // A v1 request's x-shunt-agent header is never returned, even if present.
31
+ let agent;
32
+ if (version === "v2") {
33
+ const raw = i.getHeader("x-shunt-agent");
34
+ if (!raw || !AGENT_RE.test(raw))
35
+ return { ok: false, reason: "missing_headers" };
36
+ agent = raw;
37
+ }
38
+ else if (i.requireAgent) {
39
+ return { ok: false, reason: "agent_required" };
40
+ }
26
41
  const skew = Math.abs(Date.now() / 1000 - Number(ts));
27
42
  if (!Number.isFinite(skew) || skew > (i.maxSkewSec ?? 300))
28
43
  return { ok: false, reason: "stale_timestamp" };
29
44
  const bodyHash = crypto.createHash("sha256").update(i.rawBody).digest("hex");
30
- const payload = `v1\n${ts}\n${rid}\n${i.method.toUpperCase()}\n${i.pathAndQuery}\n${bodyHash}`;
45
+ const method = i.method.toUpperCase();
46
+ const payload = version === "v2"
47
+ ? `v2\n${ts}\n${rid}\n${agent}\n${method}\n${i.pathAndQuery}\n${bodyHash}`
48
+ : `v1\n${ts}\n${rid}\n${method}\n${i.pathAndQuery}\n${bodyHash}`;
31
49
  const secrets = Array.isArray(i.secret) ? i.secret : [i.secret];
32
50
  const sigBuf = Buffer.from(sig, "utf8");
33
51
  const valid = secrets.some((s) => {
@@ -39,6 +57,6 @@ export function verifyShunt(i) {
39
57
  // only record the id AFTER the signature is valid, so attackers can't fill the cache
40
58
  if (i.replayCache?.check(rid))
41
59
  return { ok: false, reason: "replay" };
42
- return { ok: true, requestId: rid };
60
+ return { ok: true, requestId: rid, agent };
43
61
  }
44
62
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/dist/express.d.ts CHANGED
@@ -3,5 +3,6 @@ export declare const shuntRawBody: (req: any, _res: any, buf: Buffer) => void;
3
3
  export declare function shuntExpress(secret: string | string[], opts?: {
4
4
  maxSkewSec?: number;
5
5
  replayProtection?: boolean;
6
+ requireAgent?: boolean;
6
7
  }): (req: any, res: any, next: any) => any;
7
8
  //# sourceMappingURL=express.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,eAAO,MAAM,YAAY,QAAS,GAAG,QAAQ,GAAG,OAAO,MAAM,SAE5D,CAAC;AAEF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,SAGjD,GAAG,OAAO,GAAG,QAAQ,GAAG,SAgBtC"}
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,eAAO,MAAM,YAAY,QAAS,GAAG,QAAQ,GAAG,OAAO,MAAM,SAE5D,CAAC;AAEF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,SAGzE,GAAG,OAAO,GAAG,QAAQ,GAAG,SAkBtC"}
package/dist/express.js CHANGED
@@ -13,12 +13,14 @@ export function shuntExpress(secret, opts = {}) {
13
13
  rawBody: req.rawBody ?? Buffer.alloc(0),
14
14
  getHeader: (n) => req.get(n),
15
15
  maxSkewSec: opts.maxSkewSec,
16
+ requireAgent: opts.requireAgent,
16
17
  replayCache,
17
18
  });
18
19
  if (!r.ok) {
19
20
  return res.status(401).json({ error: "Unauthorized: requests must come via Shunt" });
20
21
  }
21
- req.shunt = { requestId: r.requestId, agent: req.get("x-shunt-agent") };
22
+ // req.shunt.agent is the VERIFIED agent. Never read the raw x-shunt-agent header.
23
+ req.shunt = { requestId: r.requestId, agent: r.agent };
22
24
  next();
23
25
  };
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAErD,gFAAgF;AAChF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAE,IAAS,EAAE,GAAW,EAAE,EAAE;IAC/D,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,UAAU,YAAY,CAC1B,MAAyB,EACzB,IAAI,GAAwD,EAAE;IAE9D,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,OAAO,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,WAAW,CAAC;YACpB,MAAM;YACN,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,GAAG,CAAC,WAAW;YAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACvC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,WAAW;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,GAAG,CAAC,KAAK,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;QACxE,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAErD,gFAAgF;AAChF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAE,IAAS,EAAE,GAAW,EAAE,EAAE;IAC/D,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,UAAU,YAAY,CAC1B,MAAyB,EACzB,IAAI,GAAgF,EAAE;IAEtF,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,OAAO,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,WAAW,CAAC;YACpB,MAAM;YACN,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,YAAY,EAAE,GAAG,CAAC,WAAW;YAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACvC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,WAAW;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,kFAAkF;QAClF,GAAG,CAAC,KAAK,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACvD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
package/dist/web.d.ts CHANGED
@@ -1,10 +1,19 @@
1
1
  import { ReplayCache } from "./core.js";
2
- export declare function verifyShuntRequest(req: Request, secret: string | string[], opts?: {
2
+ export interface ShuntContext {
3
+ requestId: string;
4
+ /** Verified agent wallet (present for v2 signatures). */
5
+ agent?: string;
6
+ }
7
+ export interface ShuntWebOptions {
3
8
  maxSkewSec?: number;
4
9
  replayCache?: ReplayCache;
5
- }): Promise<import("./core.js").VerifyResult>;
10
+ requireAgent?: boolean;
11
+ }
12
+ export declare function verifyShuntRequest(req: Request, secret: string | string[], opts?: ShuntWebOptions): Promise<import("./core.js").VerifyResult>;
13
+ /** Inside a withShunt handler: const { agent } = getShunt(req)!; */
14
+ export declare const getShunt: (req: Request) => ShuntContext | undefined;
6
15
  /** Next.js App Router: export const POST = withShunt(secret, async (req) => ...) */
7
- export declare function withShunt<T extends (req: Request, ...a: any[]) => Promise<Response> | Response>(secret: string | string[], handler: T): T;
8
- /** Hono: app.use("/paid/*", shuntHono(secret)) */
9
- export declare const shuntHono: (secret: string | string[]) => (c: any, next: any) => Promise<any>;
16
+ export declare function withShunt<T extends (req: Request, ...a: any[]) => Promise<Response> | Response>(secret: string | string[], handler: T, opts?: ShuntWebOptions): T;
17
+ /** Hono: app.use("/paid/*", shuntHono(secret)); then c.get("shunt").agent */
18
+ export declare const shuntHono: (secret: string | string[], opts?: ShuntWebOptions) => (c: any, next: any) => Promise<any>;
10
19
  //# sourceMappingURL=web.d.ts.map
package/dist/web.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAE,MAAM,WAAW,CAAC;AAErD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAO,6CAY9D;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,EAC7F,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,OAAO,EAAE,CAAC,GACT,CAAC,CAQH;AAED,kDAAkD;AAClD,eAAO,MAAM,SAAS,WAAY,MAAM,GAAG,MAAM,EAAE,SAAe,GAAG,QAAQ,GAAG,iBAI/E,CAAC"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,IAAI,GAAE,eAAoB,6CAY3B;AAKD,oEAAoE;AACpE,eAAO,MAAM,QAAQ,QAAS,OAAO,KAAG,YAAY,GAAG,SAA8B,CAAC;AAEtF,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,EAC7F,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,OAAO,EAAE,CAAC,EACV,IAAI,GAAE,eAAoB,GACzB,CAAC,CASH;AAED,6EAA6E;AAC7E,eAAO,MAAM,SAAS,WACX,MAAM,GAAG,MAAM,EAAE,SAAQ,eAAe,SACrC,GAAG,QAAQ,GAAG,iBAKvB,CAAC"}
package/dist/web.js CHANGED
@@ -11,21 +11,27 @@ export async function verifyShuntRequest(req, secret, opts = {}) {
11
11
  ...opts,
12
12
  });
13
13
  }
14
+ // Verified context, keyed by the Request object the handler receives.
15
+ const contexts = new WeakMap();
16
+ /** Inside a withShunt handler: const { agent } = getShunt(req)!; */
17
+ export const getShunt = (req) => contexts.get(req);
14
18
  /** Next.js App Router: export const POST = withShunt(secret, async (req) => ...) */
15
- export function withShunt(secret, handler) {
19
+ export function withShunt(secret, handler, opts = {}) {
16
20
  return (async (req, ...args) => {
17
- const r = await verifyShuntRequest(req, secret);
21
+ const r = await verifyShuntRequest(req, secret, opts);
18
22
  if (!r.ok) {
19
23
  return Response.json({ error: "Unauthorized: requests must come via Shunt" }, { status: 401 });
20
24
  }
25
+ contexts.set(req, { requestId: r.requestId, agent: r.agent });
21
26
  return handler(req, ...args);
22
27
  });
23
28
  }
24
- /** Hono: app.use("/paid/*", shuntHono(secret)) */
25
- export const shuntHono = (secret) => async (c, next) => {
26
- const r = await verifyShuntRequest(c.req.raw, secret);
29
+ /** Hono: app.use("/paid/*", shuntHono(secret)); then c.get("shunt").agent */
30
+ export const shuntHono = (secret, opts = {}) => async (c, next) => {
31
+ const r = await verifyShuntRequest(c.req.raw, secret, opts);
27
32
  if (!r.ok)
28
33
  return c.json({ error: "Unauthorized: requests must come via Shunt" }, 401);
34
+ c.set("shunt", { requestId: r.requestId, agent: r.agent });
29
35
  await next();
30
36
  };
31
37
  //# sourceMappingURL=web.js.map
package/dist/web.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,WAAW,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAY,EACZ,MAAyB,EACzB,IAAI,GAAuD,EAAE;IAE7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,OAAO,WAAW,CAAC;QACjB,MAAM;QACN,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM;QACvC,OAAO;QACP,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,SAAS,CACvB,MAAyB,EACzB,OAAU;IAEV,OAAO,CAAC,KAAK,EAAE,GAAY,EAAE,GAAG,IAAW,EAAE,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACjG,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAM,CAAC;AACV,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAyB,EAAE,EAAE,CAAC,KAAK,EAAE,CAAM,EAAE,IAAS,EAAE,EAAE;IAClF,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;IACvF,MAAM,IAAI,EAAE,CAAC;AACf,CAAC,CAAC"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,WAAW,CAAC;AAcrD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAY,EACZ,MAAyB,EACzB,IAAI,GAAoB,EAAE;IAE1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,OAAO,WAAW,CAAC;QACjB,MAAM;QACN,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,YAAY,EAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM;QACvC,OAAO;QACP,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAED,sEAAsE;AACtE,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAyB,CAAC;AAEtD,oEAAoE;AACpE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAY,EAA4B,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEtF,oFAAoF;AACpF,MAAM,UAAU,SAAS,CACvB,MAAyB,EACzB,OAAU,EACV,IAAI,GAAoB,EAAE;IAE1B,OAAO,CAAC,KAAK,EAAE,GAAY,EAAE,GAAG,IAAW,EAAE,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACjG,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9D,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAM,CAAC;AACV,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,SAAS,GACpB,CAAC,MAAyB,EAAE,IAAI,GAAoB,EAAE,EAAE,EAAE,CACxD,KAAK,EAAE,CAAM,EAAE,IAAS,EAAE,EAAE;IAC1B,MAAM,CAAC,GAAG,MAAM,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4CAA4C,EAAE,EAAE,GAAG,CAAC,CAAC;IACvF,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAyB,CAAC,CAAC;IAClF,MAAM,IAAI,EAAE,CAAC;AACf,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shunt-network/verify",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Aditya Patwa",