@shroud-fi/self-host-relayer 0.1.0

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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/cjs/dev-entry.d.ts +24 -0
  4. package/dist/cjs/dev-entry.d.ts.map +1 -0
  5. package/dist/cjs/dev-entry.js +75 -0
  6. package/dist/cjs/dev-entry.js.map +1 -0
  7. package/dist/cjs/errors.d.ts +41 -0
  8. package/dist/cjs/errors.d.ts.map +1 -0
  9. package/dist/cjs/errors.js +63 -0
  10. package/dist/cjs/errors.js.map +1 -0
  11. package/dist/cjs/index.d.ts +8 -0
  12. package/dist/cjs/index.d.ts.map +1 -0
  13. package/dist/cjs/index.js +26 -0
  14. package/dist/cjs/index.js.map +1 -0
  15. package/dist/cjs/package.json +1 -0
  16. package/dist/cjs/prod-entry.d.ts +33 -0
  17. package/dist/cjs/prod-entry.d.ts.map +1 -0
  18. package/dist/cjs/prod-entry.js +98 -0
  19. package/dist/cjs/prod-entry.js.map +1 -0
  20. package/dist/cjs/relay-eth.d.ts +43 -0
  21. package/dist/cjs/relay-eth.d.ts.map +1 -0
  22. package/dist/cjs/relay-eth.js +95 -0
  23. package/dist/cjs/relay-eth.js.map +1 -0
  24. package/dist/cjs/relay.d.ts +38 -0
  25. package/dist/cjs/relay.d.ts.map +1 -0
  26. package/dist/cjs/relay.js +83 -0
  27. package/dist/cjs/relay.js.map +1 -0
  28. package/dist/cjs/server.d.ts +18 -0
  29. package/dist/cjs/server.d.ts.map +1 -0
  30. package/dist/cjs/server.js +384 -0
  31. package/dist/cjs/server.js.map +1 -0
  32. package/dist/cjs/types.d.ts +83 -0
  33. package/dist/cjs/types.d.ts.map +1 -0
  34. package/dist/cjs/types.js +3 -0
  35. package/dist/cjs/types.js.map +1 -0
  36. package/dist/esm/dev-entry.d.ts +24 -0
  37. package/dist/esm/dev-entry.d.ts.map +1 -0
  38. package/dist/esm/dev-entry.js +73 -0
  39. package/dist/esm/dev-entry.js.map +1 -0
  40. package/dist/esm/errors.d.ts +41 -0
  41. package/dist/esm/errors.d.ts.map +1 -0
  42. package/dist/esm/errors.js +53 -0
  43. package/dist/esm/errors.js.map +1 -0
  44. package/dist/esm/index.d.ts +8 -0
  45. package/dist/esm/index.d.ts.map +1 -0
  46. package/dist/esm/index.js +10 -0
  47. package/dist/esm/index.js.map +1 -0
  48. package/dist/esm/prod-entry.d.ts +33 -0
  49. package/dist/esm/prod-entry.d.ts.map +1 -0
  50. package/dist/esm/prod-entry.js +96 -0
  51. package/dist/esm/prod-entry.js.map +1 -0
  52. package/dist/esm/relay-eth.d.ts +43 -0
  53. package/dist/esm/relay-eth.d.ts.map +1 -0
  54. package/dist/esm/relay-eth.js +91 -0
  55. package/dist/esm/relay-eth.js.map +1 -0
  56. package/dist/esm/relay.d.ts +38 -0
  57. package/dist/esm/relay.d.ts.map +1 -0
  58. package/dist/esm/relay.js +79 -0
  59. package/dist/esm/relay.js.map +1 -0
  60. package/dist/esm/server.d.ts +18 -0
  61. package/dist/esm/server.d.ts.map +1 -0
  62. package/dist/esm/server.js +377 -0
  63. package/dist/esm/server.js.map +1 -0
  64. package/dist/esm/types.d.ts +83 -0
  65. package/dist/esm/types.d.ts.map +1 -0
  66. package/dist/esm/types.js +2 -0
  67. package/dist/esm/types.js.map +1 -0
  68. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  69. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  70. package/dist/tsconfig.tsbuildinfo +1 -0
  71. package/package.json +65 -0
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Dev entry: reads config from env vars and starts the server.
3
+ *
4
+ * Required env:
5
+ * SHROUDFI_RELAYER_CONTRACT - deployed ShroudFiRelayer address
6
+ * SHROUDFI_RELAYER_FORWARDER_KEY - 0x-prefixed 32-byte forwarder EOA key
7
+ * SHROUDFI_RELAYER_RPC_URL - chain RPC URL
8
+ *
9
+ * Optional env:
10
+ * SHROUDFI_RELAYER_CHAIN_ID - default 84532
11
+ * SHROUDFI_RELAYER_PORT - default 8787
12
+ * SHROUDFI_RELAYER_ORIGINS - comma-sep allowed origins (default localhost demo)
13
+ * SHROUDFI_RELAYER_RATE_LIMIT - per-IP requests per minute (default 30)
14
+ * SHROUDFI_ETH_RELAYER_CONTRACT - deployed ShroudFiEthRelayer address.
15
+ * When set, /relay-eth becomes active for
16
+ * gasless ETH sweeps via EIP-7702. When
17
+ * unset, /relay-eth returns 501.
18
+ *
19
+ * Privacy: this file is the ONLY place that touches process.env for the
20
+ * forwarder key. Once read, the key flows into a viem account closure inside
21
+ * the server and never resurfaces.
22
+ */
23
+ export {};
24
+ //# sourceMappingURL=dev-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-entry.d.ts","sourceRoot":"","sources":["../../src/dev-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Dev entry: reads config from env vars and starts the server.
3
+ *
4
+ * Required env:
5
+ * SHROUDFI_RELAYER_CONTRACT - deployed ShroudFiRelayer address
6
+ * SHROUDFI_RELAYER_FORWARDER_KEY - 0x-prefixed 32-byte forwarder EOA key
7
+ * SHROUDFI_RELAYER_RPC_URL - chain RPC URL
8
+ *
9
+ * Optional env:
10
+ * SHROUDFI_RELAYER_CHAIN_ID - default 84532
11
+ * SHROUDFI_RELAYER_PORT - default 8787
12
+ * SHROUDFI_RELAYER_ORIGINS - comma-sep allowed origins (default localhost demo)
13
+ * SHROUDFI_RELAYER_RATE_LIMIT - per-IP requests per minute (default 30)
14
+ * SHROUDFI_ETH_RELAYER_CONTRACT - deployed ShroudFiEthRelayer address.
15
+ * When set, /relay-eth becomes active for
16
+ * gasless ETH sweeps via EIP-7702. When
17
+ * unset, /relay-eth returns 501.
18
+ *
19
+ * Privacy: this file is the ONLY place that touches process.env for the
20
+ * forwarder key. Once read, the key flows into a viem account closure inside
21
+ * the server and never resurfaces.
22
+ */
23
+ import { startServer } from './server.js';
24
+ import { RelayConfigError } from './errors.js';
25
+ function envOrThrow(name) {
26
+ const v = process.env[name];
27
+ if (v === undefined || v.trim().length === 0) {
28
+ throw new RelayConfigError(name);
29
+ }
30
+ return v.trim();
31
+ }
32
+ function loadConfig() {
33
+ const chainId = Number(process.env.SHROUDFI_RELAYER_CHAIN_ID?.trim() ?? '84532');
34
+ const port = Number(process.env.SHROUDFI_RELAYER_PORT?.trim() ?? '8787');
35
+ const rateLimitPerMinute = Number(process.env.SHROUDFI_RELAYER_RATE_LIMIT?.trim() ?? '30');
36
+ const originsCsv = process.env.SHROUDFI_RELAYER_ORIGINS?.trim() ??
37
+ 'http://localhost:3000,http://localhost:3001,http://localhost:3002,http://localhost:3003,http://localhost:3005,http://localhost:3006,http://localhost:3008,http://localhost:3009,http://127.0.0.1:3005,http://127.0.0.1:3009';
38
+ const allowedOrigins = originsCsv
39
+ .split(',')
40
+ .map((s) => s.trim())
41
+ .filter((s) => s.length > 0);
42
+ const ethRelayerRaw = process.env.SHROUDFI_ETH_RELAYER_CONTRACT?.trim();
43
+ const ethRelayerContract = ethRelayerRaw !== undefined && ethRelayerRaw.length > 0
44
+ ? ethRelayerRaw
45
+ : undefined;
46
+ const base = {
47
+ chainId,
48
+ port,
49
+ rateLimitPerMinute,
50
+ allowedOrigins,
51
+ relayerContract: envOrThrow('SHROUDFI_RELAYER_CONTRACT'),
52
+ rpcUrl: envOrThrow('SHROUDFI_RELAYER_RPC_URL'),
53
+ forwarderPrivateKey: envOrThrow('SHROUDFI_RELAYER_FORWARDER_KEY'),
54
+ };
55
+ return ethRelayerContract === undefined
56
+ ? base
57
+ : { ...base, ethRelayerContract };
58
+ }
59
+ async function main() {
60
+ const cfg = loadConfig();
61
+ await startServer(cfg);
62
+ // Print a single line so the operator knows the service is up. NO key,
63
+ // NO RPC URL, NO contract address (those are public but we keep the
64
+ // surface minimal — they can be queried via /health).
65
+ // eslint-disable-next-line no-console
66
+ console.log(`self-host-relayer listening on http://127.0.0.1:${cfg.port} (chain ${cfg.chainId})`);
67
+ }
68
+ void main().catch((err) => {
69
+ // eslint-disable-next-line no-console
70
+ console.error(err instanceof Error ? err.name : 'StartupError');
71
+ process.exit(1);
72
+ });
73
+ //# sourceMappingURL=dev-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-entry.js","sourceRoot":"","sources":["../../src/dev-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAI/C,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,UAAU;IACjB,MAAM,OAAO,GAAG,MAAM,CACpB,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,IAAI,OAAO,CACzD,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,CAAC;IACzE,MAAM,kBAAkB,GAAG,MAAM,CAC/B,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,EAAE,IAAI,IAAI,CACxD,CAAC;IACF,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE;QAC5C,6NAA6N,CAAC;IAChO,MAAM,cAAc,GAAG,UAAU;SAC9B,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE/B,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,IAAI,EAAE,CAAC;IACxE,MAAM,kBAAkB,GACtB,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;QACrD,CAAC,CAAE,aAAyB;QAC5B,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,IAAI,GAAG;QACX,OAAO;QACP,IAAI;QACJ,kBAAkB;QAClB,cAAc;QACd,eAAe,EAAE,UAAU,CAAC,2BAA2B,CAAY;QACnE,MAAM,EAAE,UAAU,CAAC,0BAA0B,CAAC;QAC9C,mBAAmB,EAAE,UAAU,CAC7B,gCAAgC,CAC1B;KACT,CAAC;IACF,OAAO,kBAAkB,KAAK,SAAS;QACrC,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,kBAAkB,EAAE,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACvB,uEAAuE;IACvE,oEAAoE;IACpE,sDAAsD;IACtD,sCAAsC;IACtC,OAAO,CAAC,GAAG,CACT,mDAAmD,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,OAAO,GAAG,CACrF,CAAC;AACJ,CAAC;AAED,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACjC,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Privacy-safe errors for @shroud-fi/self-host-relayer.
3
+ *
4
+ * Invariants mirrored from other packages:
5
+ * - No key bytes in messages
6
+ * - No amount values in messages
7
+ * - No private signature bytes in messages
8
+ */
9
+ export declare class SelfHostRelayerError extends Error {
10
+ readonly name: string;
11
+ constructor(message: string, options?: {
12
+ cause?: unknown;
13
+ });
14
+ }
15
+ export declare class InvalidRelayRequestError extends SelfHostRelayerError {
16
+ readonly name: string;
17
+ constructor();
18
+ }
19
+ export declare class RelayBroadcastError extends SelfHostRelayerError {
20
+ readonly name: string;
21
+ constructor(underlyingName?: string, options?: {
22
+ cause?: unknown;
23
+ });
24
+ }
25
+ export declare class RelayConfigError extends SelfHostRelayerError {
26
+ readonly name: string;
27
+ constructor(field: string);
28
+ }
29
+ export declare class InvalidRelayEthRequestError extends SelfHostRelayerError {
30
+ readonly name: string;
31
+ constructor();
32
+ }
33
+ export declare class EthRelayerNotConfiguredError extends SelfHostRelayerError {
34
+ readonly name: string;
35
+ constructor();
36
+ }
37
+ export declare class AuthorizationContractMismatchError extends SelfHostRelayerError {
38
+ readonly name: string;
39
+ constructor();
40
+ }
41
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,EAAE,MAAM,CAA0B;gBAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAG3D;AAED,qBAAa,wBAAyB,SAAQ,oBAAoB;IAChE,SAAkB,IAAI,EAAE,MAAM,CAA8B;;CAI7D;AAED,qBAAa,mBAAoB,SAAQ,oBAAoB;IAC3D,SAAkB,IAAI,EAAE,MAAM,CAAyB;gBAC3C,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAQnE;AAED,qBAAa,gBAAiB,SAAQ,oBAAoB;IACxD,SAAkB,IAAI,EAAE,MAAM,CAAsB;gBACxC,KAAK,EAAE,MAAM;CAG1B;AAED,qBAAa,2BAA4B,SAAQ,oBAAoB;IACnE,SAAkB,IAAI,EAAE,MAAM,CAAiC;;CAIhE;AAED,qBAAa,4BAA6B,SAAQ,oBAAoB;IACpE,SAAkB,IAAI,EAAE,MAAM,CAAkC;;CAIjE;AAED,qBAAa,kCAAmC,SAAQ,oBAAoB;IAC1E,SAAkB,IAAI,EAAE,MAAM,CAAwC;;CAIvE"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Privacy-safe errors for @shroud-fi/self-host-relayer.
3
+ *
4
+ * Invariants mirrored from other packages:
5
+ * - No key bytes in messages
6
+ * - No amount values in messages
7
+ * - No private signature bytes in messages
8
+ */
9
+ export class SelfHostRelayerError extends Error {
10
+ name = 'SelfHostRelayerError';
11
+ constructor(message, options) {
12
+ super(message, options);
13
+ }
14
+ }
15
+ export class InvalidRelayRequestError extends SelfHostRelayerError {
16
+ name = 'InvalidRelayRequestError';
17
+ constructor() {
18
+ super('Relay request body failed validation');
19
+ }
20
+ }
21
+ export class RelayBroadcastError extends SelfHostRelayerError {
22
+ name = 'RelayBroadcastError';
23
+ constructor(underlyingName, options) {
24
+ super(underlyingName !== undefined
25
+ ? `Broadcast failed (${underlyingName})`
26
+ : 'Broadcast failed', options);
27
+ }
28
+ }
29
+ export class RelayConfigError extends SelfHostRelayerError {
30
+ name = 'RelayConfigError';
31
+ constructor(field) {
32
+ super(`Relayer config missing required field: ${field}`);
33
+ }
34
+ }
35
+ export class InvalidRelayEthRequestError extends SelfHostRelayerError {
36
+ name = 'InvalidRelayEthRequestError';
37
+ constructor() {
38
+ super('Relay ETH request body failed validation');
39
+ }
40
+ }
41
+ export class EthRelayerNotConfiguredError extends SelfHostRelayerError {
42
+ name = 'EthRelayerNotConfiguredError';
43
+ constructor() {
44
+ super('ETH relayer contract address not configured');
45
+ }
46
+ }
47
+ export class AuthorizationContractMismatchError extends SelfHostRelayerError {
48
+ name = 'AuthorizationContractMismatchError';
49
+ constructor() {
50
+ super('EIP-7702 authorization address does not match configured ETH relayer');
51
+ }
52
+ }
53
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC3B,IAAI,GAAW,sBAAsB,CAAC;IACxD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,oBAAoB;IAC9C,IAAI,GAAW,0BAA0B,CAAC;IAC5D;QACE,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAChD,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,oBAAoB;IACzC,IAAI,GAAW,qBAAqB,CAAC;IACvD,YAAY,cAAuB,EAAE,OAA6B;QAChE,KAAK,CACH,cAAc,KAAK,SAAS;YAC1B,CAAC,CAAC,qBAAqB,cAAc,GAAG;YACxC,CAAC,CAAC,kBAAkB,EACtB,OAAO,CACR,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,oBAAoB;IACtC,IAAI,GAAW,kBAAkB,CAAC;IACpD,YAAY,KAAa;QACvB,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,oBAAoB;IACjD,IAAI,GAAW,6BAA6B,CAAC;IAC/D;QACE,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACpD,CAAC;CACF;AAED,MAAM,OAAO,4BAA6B,SAAQ,oBAAoB;IAClD,IAAI,GAAW,8BAA8B,CAAC;IAChE;QACE,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACvD,CAAC;CACF;AAED,MAAM,OAAO,kCAAmC,SAAQ,oBAAoB;IACxD,IAAI,GAAW,oCAAoC,CAAC;IACtE;QACE,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAChF,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export { buildServer, startServer } from './server.js';
2
+ export { buildRelayCalldata, relayRequest } from './relay.js';
3
+ export type { RelayCtx, RelayResult } from './relay.js';
4
+ export { buildEthSweepCalldata, relayEthRequest, } from './relay-eth.js';
5
+ export type { RelayEthCtx, RelayEthResult } from './relay-eth.js';
6
+ export type { RelayRequest, RelayResponse, RelaySuccess, RelayFailure, ServiceConfig, RelayEthRequest, } from './types.js';
7
+ export { SelfHostRelayerError, InvalidRelayRequestError, RelayBroadcastError, RelayConfigError, InvalidRelayEthRequestError, EthRelayerNotConfiguredError, AuthorizationContractMismatchError, } from './errors.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,4BAA4B,EAC5B,kCAAkC,GACnC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ // Public surface — @shroud-fi/self-host-relayer
2
+ //
3
+ // Exports the server builder + the pure relay-logic helpers so the same
4
+ // package can be embedded in another Node process or run standalone via
5
+ // `pnpm dev`.
6
+ export { buildServer, startServer } from './server.js';
7
+ export { buildRelayCalldata, relayRequest } from './relay.js';
8
+ export { buildEthSweepCalldata, relayEthRequest, } from './relay-eth.js';
9
+ export { SelfHostRelayerError, InvalidRelayRequestError, RelayBroadcastError, RelayConfigError, InvalidRelayEthRequestError, EthRelayerNotConfiguredError, AuthorizationContractMismatchError, } from './errors.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,cAAc;AAEd,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,OAAO,EACL,qBAAqB,EACrB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,4BAA4B,EAC5B,kCAAkC,GACnC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Production entry: strict env, fail-fast on missing required values, no
3
+ * permissive defaults that could mask misconfiguration in deployment.
4
+ *
5
+ * Required env (no defaults — startup fails if any are missing):
6
+ * SHROUDFI_RELAYER_CONTRACT - deployed ShroudFiRelayer address
7
+ * SHROUDFI_RELAYER_FORWARDER_KEY - 0x-prefixed 32-byte forwarder EOA key
8
+ * SHROUDFI_RELAYER_RPC_URL - chain RPC URL
9
+ * SHROUDFI_RELAYER_ORIGINS - comma-sep allowed origins (e.g. https://app.shroudfi.live)
10
+ * SHROUDFI_RELAYER_CHAIN_ID - chain id (84532 = Base Sepolia, 8453 = Base)
11
+ * SHROUDFI_RELAYER_PORT - bind port (typically 8789 on droplet)
12
+ *
13
+ * Optional env:
14
+ * SHROUDFI_RELAYER_RATE_LIMIT - per-IP requests per minute (default 30)
15
+ * SHROUDFI_ETH_RELAYER_CONTRACT - deployed ShroudFiEthRelayer address.
16
+ * When set, /relay-eth becomes active for
17
+ * gasless ETH sweeps via EIP-7702. When
18
+ * unset, /relay-eth returns 501.
19
+ * DEBUG_DIAGNOSTICS - "1" to enable per-request preflight + sig recovery logs
20
+ *
21
+ * Differences from dev-entry.ts:
22
+ * - Every required field uses envOrThrow; no fallbacks
23
+ * - SHROUDFI_RELAYER_ORIGINS is REQUIRED (dev defaults to localhost; prod must be explicit)
24
+ * - No startup log line printed to stdout — only journald via PM2 captures fastify's
25
+ * own "Server listening at ..." line
26
+ * - DEBUG_DIAGNOSTICS env opts into the per-request debug logs (off by default)
27
+ *
28
+ * Privacy: this file is the ONLY place that touches process.env for the
29
+ * forwarder key. Once read, the key flows into a viem account closure inside
30
+ * the server and never resurfaces.
31
+ */
32
+ export {};
33
+ //# sourceMappingURL=prod-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prod-entry.d.ts","sourceRoot":"","sources":["../../src/prod-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Production entry: strict env, fail-fast on missing required values, no
3
+ * permissive defaults that could mask misconfiguration in deployment.
4
+ *
5
+ * Required env (no defaults — startup fails if any are missing):
6
+ * SHROUDFI_RELAYER_CONTRACT - deployed ShroudFiRelayer address
7
+ * SHROUDFI_RELAYER_FORWARDER_KEY - 0x-prefixed 32-byte forwarder EOA key
8
+ * SHROUDFI_RELAYER_RPC_URL - chain RPC URL
9
+ * SHROUDFI_RELAYER_ORIGINS - comma-sep allowed origins (e.g. https://app.shroudfi.live)
10
+ * SHROUDFI_RELAYER_CHAIN_ID - chain id (84532 = Base Sepolia, 8453 = Base)
11
+ * SHROUDFI_RELAYER_PORT - bind port (typically 8789 on droplet)
12
+ *
13
+ * Optional env:
14
+ * SHROUDFI_RELAYER_RATE_LIMIT - per-IP requests per minute (default 30)
15
+ * SHROUDFI_ETH_RELAYER_CONTRACT - deployed ShroudFiEthRelayer address.
16
+ * When set, /relay-eth becomes active for
17
+ * gasless ETH sweeps via EIP-7702. When
18
+ * unset, /relay-eth returns 501.
19
+ * DEBUG_DIAGNOSTICS - "1" to enable per-request preflight + sig recovery logs
20
+ *
21
+ * Differences from dev-entry.ts:
22
+ * - Every required field uses envOrThrow; no fallbacks
23
+ * - SHROUDFI_RELAYER_ORIGINS is REQUIRED (dev defaults to localhost; prod must be explicit)
24
+ * - No startup log line printed to stdout — only journald via PM2 captures fastify's
25
+ * own "Server listening at ..." line
26
+ * - DEBUG_DIAGNOSTICS env opts into the per-request debug logs (off by default)
27
+ *
28
+ * Privacy: this file is the ONLY place that touches process.env for the
29
+ * forwarder key. Once read, the key flows into a viem account closure inside
30
+ * the server and never resurfaces.
31
+ */
32
+ import { startServer } from './server.js';
33
+ import { RelayConfigError } from './errors.js';
34
+ function envOrThrow(name) {
35
+ const v = process.env[name];
36
+ if (v === undefined || v.trim().length === 0) {
37
+ throw new RelayConfigError(name);
38
+ }
39
+ return v.trim();
40
+ }
41
+ function loadConfig() {
42
+ const chainId = Number(envOrThrow('SHROUDFI_RELAYER_CHAIN_ID'));
43
+ if (!Number.isFinite(chainId) || chainId <= 0) {
44
+ throw new RelayConfigError('SHROUDFI_RELAYER_CHAIN_ID');
45
+ }
46
+ const port = Number(envOrThrow('SHROUDFI_RELAYER_PORT'));
47
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
48
+ throw new RelayConfigError('SHROUDFI_RELAYER_PORT');
49
+ }
50
+ const rateLimitRaw = process.env.SHROUDFI_RELAYER_RATE_LIMIT?.trim();
51
+ const rateLimitPerMinute = rateLimitRaw && rateLimitRaw.length > 0 ? Number(rateLimitRaw) : 30;
52
+ if (!Number.isFinite(rateLimitPerMinute) || rateLimitPerMinute <= 0) {
53
+ throw new RelayConfigError('SHROUDFI_RELAYER_RATE_LIMIT');
54
+ }
55
+ const originsCsv = envOrThrow('SHROUDFI_RELAYER_ORIGINS');
56
+ const allowedOrigins = originsCsv
57
+ .split(',')
58
+ .map((s) => s.trim())
59
+ .filter((s) => s.length > 0);
60
+ if (allowedOrigins.length === 0) {
61
+ throw new RelayConfigError('SHROUDFI_RELAYER_ORIGINS');
62
+ }
63
+ const debugDiagnostics = process.env.DEBUG_DIAGNOSTICS === '1';
64
+ const ethRelayerRaw = process.env.SHROUDFI_ETH_RELAYER_CONTRACT?.trim();
65
+ const ethRelayerContract = ethRelayerRaw !== undefined && ethRelayerRaw.length > 0
66
+ ? ethRelayerRaw
67
+ : undefined;
68
+ const base = {
69
+ chainId,
70
+ port,
71
+ rateLimitPerMinute,
72
+ allowedOrigins,
73
+ relayerContract: envOrThrow('SHROUDFI_RELAYER_CONTRACT'),
74
+ rpcUrl: envOrThrow('SHROUDFI_RELAYER_RPC_URL'),
75
+ forwarderPrivateKey: envOrThrow('SHROUDFI_RELAYER_FORWARDER_KEY'),
76
+ debugDiagnostics,
77
+ };
78
+ return ethRelayerContract === undefined
79
+ ? base
80
+ : { ...base, ethRelayerContract };
81
+ }
82
+ async function main() {
83
+ const cfg = loadConfig();
84
+ await startServer(cfg);
85
+ // Intentionally no stdout — Fastify's logger already emits a "Server
86
+ // listening at ..." line that PM2/journald captures. Avoid extra surface.
87
+ }
88
+ void main().catch((err) => {
89
+ // Startup failure → emit only the error class name to stderr, then exit 1.
90
+ // PM2 will record this and (per ecosystem config) attempt restart up to
91
+ // max_restarts before giving up.
92
+ // eslint-disable-next-line no-console
93
+ console.error(err instanceof Error ? err.name : 'StartupError');
94
+ process.exit(1);
95
+ });
96
+ //# sourceMappingURL=prod-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prod-entry.js","sourceRoot":"","sources":["../../src/prod-entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * ETH gasless sweep relay — broadcasts an EIP-7702 type-0x04 tx that delegates
3
+ * the stealth EOA to ShroudFiEthRelayer and calls sweepETH(destination,
4
+ * deadline, signature).
5
+ *
6
+ * Privacy invariants:
7
+ * - Relayer EOA's private key held in the viem account closure. Never
8
+ * logged or attached to thrown errors.
9
+ * - The EIP-712 signature in the request is a one-time spending
10
+ * authorization bound to (destination, deadline, chainId, stealthEOA).
11
+ * We pass it through verbatim — never store or re-sign.
12
+ * - No amount fields anywhere in the request or response.
13
+ */
14
+ import { type Account, type Chain, type Hex, type PublicClient, type Transport, type WalletClient } from 'viem';
15
+ import type { RelayEthRequest } from './types.js';
16
+ /**
17
+ * Same generic-loose shape as RelayCtx. Holds the broadcast-side viem clients
18
+ * plus the relayer EOA. The relayer EOA pays gas for the outer tx.
19
+ */
20
+ export interface RelayEthCtx {
21
+ readonly publicClient: PublicClient<Transport, Chain | undefined>;
22
+ readonly walletClient: WalletClient<Transport, Chain | undefined, Account>;
23
+ readonly account: Account;
24
+ }
25
+ export interface RelayEthResult {
26
+ readonly txHash: Hex;
27
+ readonly blockNumber: bigint;
28
+ }
29
+ /**
30
+ * Build the inner sweepETH calldata. The OUTER tx is the type-0x04 transaction
31
+ * itself which carries the authorization list and the `to: stealthAddress`;
32
+ * the inner data is what executes once the EOA's code is set to the relayer.
33
+ */
34
+ export declare function buildEthSweepCalldata(req: RelayEthRequest): Hex;
35
+ /**
36
+ * Submit the type-0x04 tx and wait for receipt.
37
+ *
38
+ * On any viem error we wrap with RelayBroadcastError(name, { cause: err }) so
39
+ * the server can walk the cause chain and log the actual revert reason
40
+ * (public on-chain data) without surfacing it to clients.
41
+ */
42
+ export declare function relayEthRequest(ctx: RelayEthCtx, req: RelayEthRequest): Promise<RelayEthResult>;
43
+ //# sourceMappingURL=relay-eth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-eth.d.ts","sourceRoot":"","sources":["../../src/relay-eth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,YAAY,EAEjB,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAgBlD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;IAClE,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAmBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,GAAG,CAM/D;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,cAAc,CAAC,CAyBzB"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * ETH gasless sweep relay — broadcasts an EIP-7702 type-0x04 tx that delegates
3
+ * the stealth EOA to ShroudFiEthRelayer and calls sweepETH(destination,
4
+ * deadline, signature).
5
+ *
6
+ * Privacy invariants:
7
+ * - Relayer EOA's private key held in the viem account closure. Never
8
+ * logged or attached to thrown errors.
9
+ * - The EIP-712 signature in the request is a one-time spending
10
+ * authorization bound to (destination, deadline, chainId, stealthEOA).
11
+ * We pass it through verbatim — never store or re-sign.
12
+ * - No amount fields anywhere in the request or response.
13
+ */
14
+ import { encodeFunctionData, } from 'viem';
15
+ import { RelayBroadcastError } from './errors.js';
16
+ const SWEEP_ETH_ABI = [
17
+ {
18
+ type: 'function',
19
+ name: 'sweepETH',
20
+ stateMutability: 'nonpayable',
21
+ inputs: [
22
+ { name: 'destination', type: 'address' },
23
+ { name: 'deadline', type: 'uint256' },
24
+ { name: 'signature', type: 'bytes' },
25
+ ],
26
+ outputs: [],
27
+ },
28
+ ];
29
+ /**
30
+ * Reconstruct a viem `SignedAuthorization` from the wire-encoded fields. The
31
+ * fields are exactly what the SDK serialises in @shroud-fi/relayer's
32
+ * eth-sweep.ts — `nonce` arrives as a number, `chainId` as a number, `r`/`s`
33
+ * as 0x-prefixed hex, `yParity` as 0 or 1.
34
+ */
35
+ function reconstructAuthorization(req) {
36
+ return {
37
+ address: req.authorization.address,
38
+ chainId: req.authorization.chainId,
39
+ nonce: req.authorization.nonce,
40
+ r: req.authorization.r,
41
+ s: req.authorization.s,
42
+ yParity: req.authorization.yParity,
43
+ };
44
+ }
45
+ /**
46
+ * Build the inner sweepETH calldata. The OUTER tx is the type-0x04 transaction
47
+ * itself which carries the authorization list and the `to: stealthAddress`;
48
+ * the inner data is what executes once the EOA's code is set to the relayer.
49
+ */
50
+ export function buildEthSweepCalldata(req) {
51
+ return encodeFunctionData({
52
+ abi: SWEEP_ETH_ABI,
53
+ functionName: 'sweepETH',
54
+ args: [req.destination, BigInt(req.deadline), req.signature],
55
+ });
56
+ }
57
+ /**
58
+ * Submit the type-0x04 tx and wait for receipt.
59
+ *
60
+ * On any viem error we wrap with RelayBroadcastError(name, { cause: err }) so
61
+ * the server can walk the cause chain and log the actual revert reason
62
+ * (public on-chain data) without surfacing it to clients.
63
+ */
64
+ export async function relayEthRequest(ctx, req) {
65
+ const data = buildEthSweepCalldata(req);
66
+ const authorization = reconstructAuthorization(req);
67
+ try {
68
+ const txHash = await ctx.walletClient.sendTransaction({
69
+ account: ctx.account,
70
+ chain: ctx.walletClient.chain ?? null,
71
+ to: req.stealthAddress,
72
+ data,
73
+ value: 0n,
74
+ authorizationList: [authorization],
75
+ });
76
+ const receipt = await ctx.publicClient.waitForTransactionReceipt({
77
+ hash: txHash,
78
+ });
79
+ if (receipt.status !== 'success') {
80
+ throw new RelayBroadcastError('TransactionReverted');
81
+ }
82
+ return { txHash, blockNumber: receipt.blockNumber };
83
+ }
84
+ catch (err) {
85
+ if (err instanceof RelayBroadcastError)
86
+ throw err;
87
+ const name = err instanceof Error ? err.name : 'UnknownError';
88
+ throw new RelayBroadcastError(name, { cause: err });
89
+ }
90
+ }
91
+ //# sourceMappingURL=relay-eth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-eth.js","sourceRoot":"","sources":["../../src/relay-eth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,kBAAkB,GAQnB,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,aAAa,GAAG;IACpB;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,UAAU;QAChB,eAAe,EAAE,YAAY;QAC7B,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;YACxC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE;YACrC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE;SACrC;QACD,OAAO,EAAE,EAAE;KACZ;CACO,CAAC;AAiBX;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,GAAoB;IACpD,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,OAAO;QAClC,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,OAAO;QAClC,KAAK,EAAE,GAAG,CAAC,aAAa,CAAC,KAAK;QAC9B,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QACtB,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QACtB,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,OAAO;KACnC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAoB;IACxD,OAAO,kBAAkB,CAAC;QACxB,GAAG,EAAE,aAAa;QAClB,YAAY,EAAE,UAAU;QACxB,IAAI,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAgB,EAChB,GAAoB;IAEpB,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,aAAa,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,eAAe,CAAC;YACpD,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,IAAI;YACrC,EAAE,EAAE,GAAG,CAAC,cAAc;YACtB,IAAI;YACJ,KAAK,EAAE,EAAE;YACT,iBAAiB,EAAE,CAAC,aAAa,CAAC;SACnC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,yBAAyB,CAAC;YAC/D,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB;YAAE,MAAM,GAAG,CAAC;QAClD,MAAM,IAAI,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC;QAC9D,MAAM,IAAI,mBAAmB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Core relay logic. Pure function — given a validated request + viem clients,
3
+ * encodes the ERC-2771 wrapped calldata and broadcasts via the relayer EOA.
4
+ *
5
+ * Privacy invariants:
6
+ * - The relayer EOA's private key is held in a viem account closure. It is
7
+ * never logged, serialized, or attached to thrown errors.
8
+ * - The stealth address is data, not key material.
9
+ * - The permit (v, r, s, deadline) is a one-time authorization for the
10
+ * specific (owner, spender, value, deadline) bound at signing time.
11
+ */
12
+ import { type Account, type Address, type Chain, type Hex, type PublicClient, type Transport, type WalletClient } from 'viem';
13
+ import type { RelayRequest } from './types.js';
14
+ export interface RelayCtx {
15
+ readonly publicClient: PublicClient<Transport, Chain | undefined>;
16
+ readonly walletClient: WalletClient<Transport, Chain | undefined, Account>;
17
+ readonly account: Account;
18
+ readonly relayerContract: Address;
19
+ }
20
+ export interface RelayResult {
21
+ readonly txHash: Hex;
22
+ readonly blockNumber: bigint;
23
+ }
24
+ /**
25
+ * Build the ERC-2771-wrapped calldata: encoded sweepERC20WithPermit(...) with
26
+ * the 20-byte stealth address appended. ShroudFiRelayer's ERC2771Context
27
+ * reads _msgSender() as the appended address when msg.sender is the trusted
28
+ * forwarder (= the relayer EOA = `account` here).
29
+ */
30
+ export declare function buildRelayCalldata(req: RelayRequest): Hex;
31
+ /**
32
+ * Broadcast the wrapped tx. Waits for the receipt before returning.
33
+ *
34
+ * Throws RelayBroadcastError on any underlying viem error. Errors are wrapped
35
+ * to strip out potentially key-bearing payloads from the visible message.
36
+ */
37
+ export declare function relayRequest(ctx: RelayCtx, req: RelayRequest): Promise<RelayResult>;
38
+ //# sourceMappingURL=relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAuB/C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;IAClE,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,GAAG,CAgBzD;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,QAAQ,EACb,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,WAAW,CAAC,CAkBtB"}