@alchemy/common 0.0.0-alpha.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 (212) hide show
  1. package/LICENSE +21 -0
  2. package/dist/esm/actions/addBreadCrumb.d.ts +14 -0
  3. package/dist/esm/actions/addBreadCrumb.js +27 -0
  4. package/dist/esm/actions/addBreadCrumb.js.map +1 -0
  5. package/dist/esm/chains.d.ts +234 -0
  6. package/dist/esm/chains.js +113 -0
  7. package/dist/esm/chains.js.map +1 -0
  8. package/dist/esm/errors/AccountNotFoundError.d.ts +10 -0
  9. package/dist/esm/errors/AccountNotFoundError.js +19 -0
  10. package/dist/esm/errors/AccountNotFoundError.js.map +1 -0
  11. package/dist/esm/errors/BaseError.d.ts +23 -0
  12. package/dist/esm/errors/BaseError.js +40 -0
  13. package/dist/esm/errors/BaseError.js.map +1 -0
  14. package/dist/esm/errors/ChainNotFoundError.d.ts +11 -0
  15. package/dist/esm/errors/ChainNotFoundError.js +19 -0
  16. package/dist/esm/errors/ChainNotFoundError.js.map +1 -0
  17. package/dist/esm/errors/ConnectionConfigError.d.ts +13 -0
  18. package/dist/esm/errors/ConnectionConfigError.js +25 -0
  19. package/dist/esm/errors/ConnectionConfigError.js.map +1 -0
  20. package/dist/esm/errors/FetchError.d.ts +15 -0
  21. package/dist/esm/errors/FetchError.js +25 -0
  22. package/dist/esm/errors/FetchError.js.map +1 -0
  23. package/dist/esm/errors/InvalidRequestError.d.ts +13 -0
  24. package/dist/esm/errors/InvalidRequestError.js +22 -0
  25. package/dist/esm/errors/InvalidRequestError.js.map +1 -0
  26. package/dist/esm/errors/MethodUnsupportedError.d.ts +13 -0
  27. package/dist/esm/errors/MethodUnsupportedError.js +21 -0
  28. package/dist/esm/errors/MethodUnsupportedError.js.map +1 -0
  29. package/dist/esm/errors/ServerError.d.ts +15 -0
  30. package/dist/esm/errors/ServerError.js +25 -0
  31. package/dist/esm/errors/ServerError.js.map +1 -0
  32. package/dist/esm/index.d.ts +29 -0
  33. package/dist/esm/index.js +27 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/logging/config.d.ts +190 -0
  36. package/dist/esm/logging/config.js +279 -0
  37. package/dist/esm/logging/config.js.map +1 -0
  38. package/dist/esm/logging/index.d.ts +6 -0
  39. package/dist/esm/logging/index.js +5 -0
  40. package/dist/esm/logging/index.js.map +1 -0
  41. package/dist/esm/logging/local.d.ts +10 -0
  42. package/dist/esm/logging/local.js +35 -0
  43. package/dist/esm/logging/local.js.map +1 -0
  44. package/dist/esm/logging/logger.d.ts +80 -0
  45. package/dist/esm/logging/logger.js +111 -0
  46. package/dist/esm/logging/logger.js.map +1 -0
  47. package/dist/esm/logging/noop.d.ts +6 -0
  48. package/dist/esm/logging/noop.js +12 -0
  49. package/dist/esm/logging/noop.js.map +1 -0
  50. package/dist/esm/logging/sinks.d.ts +90 -0
  51. package/dist/esm/logging/sinks.js +111 -0
  52. package/dist/esm/logging/sinks.js.map +1 -0
  53. package/dist/esm/logging/types.d.ts +96 -0
  54. package/dist/esm/logging/types.js +2 -0
  55. package/dist/esm/logging/types.js.map +1 -0
  56. package/dist/esm/logging/utils.d.ts +7 -0
  57. package/dist/esm/logging/utils.js +21 -0
  58. package/dist/esm/logging/utils.js.map +1 -0
  59. package/dist/esm/rest/restClient.d.ts +34 -0
  60. package/dist/esm/rest/restClient.js +55 -0
  61. package/dist/esm/rest/restClient.js.map +1 -0
  62. package/dist/esm/rest/types.d.ts +24 -0
  63. package/dist/esm/rest/types.js +2 -0
  64. package/dist/esm/rest/types.js.map +1 -0
  65. package/dist/esm/tracing/traceHeader.d.ts +82 -0
  66. package/dist/esm/tracing/traceHeader.js +145 -0
  67. package/dist/esm/tracing/traceHeader.js.map +1 -0
  68. package/dist/esm/tracing/updateHeaders.d.ts +24 -0
  69. package/dist/esm/tracing/updateHeaders.js +61 -0
  70. package/dist/esm/tracing/updateHeaders.js.map +1 -0
  71. package/dist/esm/transport/alchemy.d.ts +110 -0
  72. package/dist/esm/transport/alchemy.js +164 -0
  73. package/dist/esm/transport/alchemy.js.map +1 -0
  74. package/dist/esm/transport/chainRegistry.d.ts +31 -0
  75. package/dist/esm/transport/chainRegistry.js +95 -0
  76. package/dist/esm/transport/chainRegistry.js.map +1 -0
  77. package/dist/esm/transport/connection.d.ts +20 -0
  78. package/dist/esm/transport/connection.js +2 -0
  79. package/dist/esm/transport/connection.js.map +1 -0
  80. package/dist/esm/transport/connectionSchema.d.ts +124 -0
  81. package/dist/esm/transport/connectionSchema.js +121 -0
  82. package/dist/esm/transport/connectionSchema.js.map +1 -0
  83. package/dist/esm/utils/assertNever.d.ts +8 -0
  84. package/dist/esm/utils/assertNever.js +12 -0
  85. package/dist/esm/utils/assertNever.js.map +1 -0
  86. package/dist/esm/utils/bigint.d.ts +24 -0
  87. package/dist/esm/utils/bigint.js +37 -0
  88. package/dist/esm/utils/bigint.js.map +1 -0
  89. package/dist/esm/utils/createEip1193HandlerFactory.d.ts +18 -0
  90. package/dist/esm/utils/createEip1193HandlerFactory.js +11 -0
  91. package/dist/esm/utils/createEip1193HandlerFactory.js.map +1 -0
  92. package/dist/esm/utils/headers.d.ts +7 -0
  93. package/dist/esm/utils/headers.js +29 -0
  94. package/dist/esm/utils/headers.js.map +1 -0
  95. package/dist/esm/utils/lowerAddress.d.ts +8 -0
  96. package/dist/esm/utils/lowerAddress.js +9 -0
  97. package/dist/esm/utils/lowerAddress.js.map +1 -0
  98. package/dist/esm/utils/raise.d.ts +8 -0
  99. package/dist/esm/utils/raise.js +14 -0
  100. package/dist/esm/utils/raise.js.map +1 -0
  101. package/dist/esm/utils/types.d.ts +10 -0
  102. package/dist/esm/utils/types.js +2 -0
  103. package/dist/esm/utils/types.js.map +1 -0
  104. package/dist/esm/version.d.ts +1 -0
  105. package/dist/esm/version.js +4 -0
  106. package/dist/esm/version.js.map +1 -0
  107. package/dist/types/actions/addBreadCrumb.d.ts +15 -0
  108. package/dist/types/actions/addBreadCrumb.d.ts.map +1 -0
  109. package/dist/types/chains.d.ts +235 -0
  110. package/dist/types/chains.d.ts.map +1 -0
  111. package/dist/types/errors/AccountNotFoundError.d.ts +11 -0
  112. package/dist/types/errors/AccountNotFoundError.d.ts.map +1 -0
  113. package/dist/types/errors/BaseError.d.ts +24 -0
  114. package/dist/types/errors/BaseError.d.ts.map +1 -0
  115. package/dist/types/errors/ChainNotFoundError.d.ts +12 -0
  116. package/dist/types/errors/ChainNotFoundError.d.ts.map +1 -0
  117. package/dist/types/errors/ConnectionConfigError.d.ts +14 -0
  118. package/dist/types/errors/ConnectionConfigError.d.ts.map +1 -0
  119. package/dist/types/errors/FetchError.d.ts +16 -0
  120. package/dist/types/errors/FetchError.d.ts.map +1 -0
  121. package/dist/types/errors/InvalidRequestError.d.ts +14 -0
  122. package/dist/types/errors/InvalidRequestError.d.ts.map +1 -0
  123. package/dist/types/errors/MethodUnsupportedError.d.ts +14 -0
  124. package/dist/types/errors/MethodUnsupportedError.d.ts.map +1 -0
  125. package/dist/types/errors/ServerError.d.ts +16 -0
  126. package/dist/types/errors/ServerError.d.ts.map +1 -0
  127. package/dist/types/index.d.ts +30 -0
  128. package/dist/types/index.d.ts.map +1 -0
  129. package/dist/types/logging/config.d.ts +191 -0
  130. package/dist/types/logging/config.d.ts.map +1 -0
  131. package/dist/types/logging/index.d.ts +7 -0
  132. package/dist/types/logging/index.d.ts.map +1 -0
  133. package/dist/types/logging/local.d.ts +11 -0
  134. package/dist/types/logging/local.d.ts.map +1 -0
  135. package/dist/types/logging/logger.d.ts +81 -0
  136. package/dist/types/logging/logger.d.ts.map +1 -0
  137. package/dist/types/logging/noop.d.ts +7 -0
  138. package/dist/types/logging/noop.d.ts.map +1 -0
  139. package/dist/types/logging/sinks.d.ts +91 -0
  140. package/dist/types/logging/sinks.d.ts.map +1 -0
  141. package/dist/types/logging/types.d.ts +97 -0
  142. package/dist/types/logging/types.d.ts.map +1 -0
  143. package/dist/types/logging/utils.d.ts +8 -0
  144. package/dist/types/logging/utils.d.ts.map +1 -0
  145. package/dist/types/rest/restClient.d.ts +35 -0
  146. package/dist/types/rest/restClient.d.ts.map +1 -0
  147. package/dist/types/rest/types.d.ts +25 -0
  148. package/dist/types/rest/types.d.ts.map +1 -0
  149. package/dist/types/tracing/traceHeader.d.ts +83 -0
  150. package/dist/types/tracing/traceHeader.d.ts.map +1 -0
  151. package/dist/types/tracing/updateHeaders.d.ts +25 -0
  152. package/dist/types/tracing/updateHeaders.d.ts.map +1 -0
  153. package/dist/types/transport/alchemy.d.ts +111 -0
  154. package/dist/types/transport/alchemy.d.ts.map +1 -0
  155. package/dist/types/transport/chainRegistry.d.ts +32 -0
  156. package/dist/types/transport/chainRegistry.d.ts.map +1 -0
  157. package/dist/types/transport/connection.d.ts +21 -0
  158. package/dist/types/transport/connection.d.ts.map +1 -0
  159. package/dist/types/transport/connectionSchema.d.ts +125 -0
  160. package/dist/types/transport/connectionSchema.d.ts.map +1 -0
  161. package/dist/types/utils/assertNever.d.ts +9 -0
  162. package/dist/types/utils/assertNever.d.ts.map +1 -0
  163. package/dist/types/utils/bigint.d.ts +25 -0
  164. package/dist/types/utils/bigint.d.ts.map +1 -0
  165. package/dist/types/utils/createEip1193HandlerFactory.d.ts +19 -0
  166. package/dist/types/utils/createEip1193HandlerFactory.d.ts.map +1 -0
  167. package/dist/types/utils/headers.d.ts +8 -0
  168. package/dist/types/utils/headers.d.ts.map +1 -0
  169. package/dist/types/utils/lowerAddress.d.ts +9 -0
  170. package/dist/types/utils/lowerAddress.d.ts.map +1 -0
  171. package/dist/types/utils/raise.d.ts +9 -0
  172. package/dist/types/utils/raise.d.ts.map +1 -0
  173. package/dist/types/utils/types.d.ts +11 -0
  174. package/dist/types/utils/types.d.ts.map +1 -0
  175. package/dist/types/version.d.ts +2 -0
  176. package/dist/types/version.d.ts.map +1 -0
  177. package/package.json +67 -0
  178. package/src/actions/addBreadCrumb.ts +38 -0
  179. package/src/chains.ts +118 -0
  180. package/src/errors/AccountNotFoundError.ts +16 -0
  181. package/src/errors/BaseError.ts +51 -0
  182. package/src/errors/ChainNotFoundError.ts +15 -0
  183. package/src/errors/ConnectionConfigError.ts +22 -0
  184. package/src/errors/FetchError.ts +21 -0
  185. package/src/errors/InvalidRequestError.ts +19 -0
  186. package/src/errors/MethodUnsupportedError.ts +17 -0
  187. package/src/errors/ServerError.ts +21 -0
  188. package/src/index.ts +60 -0
  189. package/src/logging/config.ts +365 -0
  190. package/src/logging/index.ts +20 -0
  191. package/src/logging/local.ts +39 -0
  192. package/src/logging/logger.ts +194 -0
  193. package/src/logging/noop.ts +13 -0
  194. package/src/logging/sinks.ts +115 -0
  195. package/src/logging/types.ts +111 -0
  196. package/src/logging/utils.ts +31 -0
  197. package/src/rest/restClient.ts +64 -0
  198. package/src/rest/types.ts +42 -0
  199. package/src/tracing/traceHeader.ts +154 -0
  200. package/src/tracing/updateHeaders.ts +66 -0
  201. package/src/transport/alchemy.ts +242 -0
  202. package/src/transport/chainRegistry.ts +115 -0
  203. package/src/transport/connection.ts +19 -0
  204. package/src/transport/connectionSchema.ts +145 -0
  205. package/src/utils/assertNever.ts +12 -0
  206. package/src/utils/bigint.ts +58 -0
  207. package/src/utils/createEip1193HandlerFactory.ts +25 -0
  208. package/src/utils/headers.ts +48 -0
  209. package/src/utils/lowerAddress.ts +10 -0
  210. package/src/utils/raise.ts +14 -0
  211. package/src/utils/types.ts +14 -0
  212. package/src/version.ts +3 -0
@@ -0,0 +1,145 @@
1
+ function generateRandomHexString(numBytes) {
2
+ const hexPairs = new Array(numBytes).fill(0).map(() => Math.floor(Math.random() * 16)
3
+ .toString(16)
4
+ .padStart(2, "0"));
5
+ return hexPairs.join("");
6
+ }
7
+ /**
8
+ * These are the headers that are used in the trace headers, could be found in the spec
9
+ *
10
+ * @see https://www.w3.org/TR/trace-context/#design-overview
11
+ */
12
+ export const TRACE_HEADER_NAME = "traceparent";
13
+ /**
14
+ * These are the headers that are used in the trace headers, could be found in the spec
15
+ *
16
+ * @see https://www.w3.org/TR/trace-context/#design-overview
17
+ */
18
+ export const TRACE_HEADER_STATE = "tracestate";
19
+ const clientTraceId = generateRandomHexString(16);
20
+ /**
21
+ * Some tools that are useful when dealing with the values
22
+ * of the trace header. Follows the W3C trace context standard.
23
+ *
24
+ * @see https://www.w3.org/TR/trace-context/
25
+ */
26
+ export class TraceHeader {
27
+ /**
28
+ * Initializes a new instance with the provided trace identifiers and state information.
29
+ *
30
+ * @param {string} traceId The unique identifier for the trace
31
+ * @param {string} parentId The identifier of the parent trace
32
+ * @param {string} traceFlags Flags containing trace-related options
33
+ * @param {TraceHeader["traceState"]} traceState The trace state information for additional trace context
34
+ */
35
+ constructor(traceId, parentId, traceFlags, traceState) {
36
+ Object.defineProperty(this, "traceId", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: void 0
41
+ });
42
+ Object.defineProperty(this, "parentId", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: void 0
47
+ });
48
+ Object.defineProperty(this, "traceFlags", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: void 0
53
+ });
54
+ Object.defineProperty(this, "traceState", {
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true,
58
+ value: void 0
59
+ });
60
+ this.traceId = traceId;
61
+ this.parentId = parentId;
62
+ this.traceFlags = traceFlags;
63
+ this.traceState = traceState;
64
+ }
65
+ /**
66
+ * Creating a default trace id that is a random setup for both trace id and parent id
67
+ *
68
+ * @example ```ts
69
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
70
+ * ```
71
+ *
72
+ * @returns {TraceHeader} A default trace header
73
+ */
74
+ static default() {
75
+ return new TraceHeader(clientTraceId, generateRandomHexString(8), "00", //Means no flag have been set, and no sampled state https://www.w3.org/TR/trace-context/#trace-flags
76
+ {});
77
+ }
78
+ /**
79
+ * Should be able to consume a trace header from the headers of an http request
80
+ *
81
+ * @example ```ts
82
+ * const traceHeader = TraceHeader.fromTraceHeader(headers);
83
+ * ```
84
+ *
85
+ * @param {Record<string,string>} headers The headers from the http request
86
+ * @returns {TraceHeader | undefined} The trace header object, or nothing if not found
87
+ */
88
+ static fromTraceHeader(headers) {
89
+ if (!headers[TRACE_HEADER_NAME]) {
90
+ return undefined;
91
+ }
92
+ const [version, traceId, parentId, traceFlags] = headers[TRACE_HEADER_NAME]?.split("-");
93
+ const traceState = headers[TRACE_HEADER_STATE]?.split(",").reduce((acc, curr) => {
94
+ const [key, value] = curr.split("=");
95
+ acc[key] = value;
96
+ return acc;
97
+ }, {}) || {};
98
+ if (version !== "00") {
99
+ console.debug(new Error(`Invalid version for traceheader: ${headers[TRACE_HEADER_NAME]}`));
100
+ return undefined;
101
+ }
102
+ return new TraceHeader(traceId, parentId, traceFlags, traceState);
103
+ }
104
+ /**
105
+ * Should be able to convert the trace header to the format that is used in the headers of an http request
106
+ *
107
+ * @example ```ts
108
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
109
+ * const headers = traceHeader.toTraceHeader();
110
+ * ```
111
+ *
112
+ * @returns {{traceparent: string, tracestate: string}} The trace header in the format of a record, used in our http client
113
+ */
114
+ toTraceHeader() {
115
+ return {
116
+ [TRACE_HEADER_NAME]: `00-${this.traceId}-${this.parentId}-${this.traceFlags}`,
117
+ [TRACE_HEADER_STATE]: Object.entries(this.traceState)
118
+ .map(([key, value]) => `${key}=${value}`)
119
+ .join(","),
120
+ };
121
+ }
122
+ /**
123
+ * Should be able to create a new trace header with a new event in the trace state,
124
+ * as the key of the eventName as breadcrumbs appending onto previous breadcrumbs with the - infix if exists. And the
125
+ * trace parent gets updated as according to the docs
126
+ *
127
+ * @example ```ts
128
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
129
+ * const newTraceHeader = traceHeader.withEvent("newEvent");
130
+ * ```
131
+ *
132
+ * @param {string} eventName The key of the new event
133
+ * @returns {TraceHeader} The new trace header
134
+ */
135
+ withEvent(eventName) {
136
+ const breadcrumbs = this.traceState.breadcrumbs
137
+ ? `${this.traceState.breadcrumbs}-${eventName}`
138
+ : eventName;
139
+ return new TraceHeader(this.traceId, this.parentId, this.traceFlags, {
140
+ ...this.traceState,
141
+ breadcrumbs,
142
+ });
143
+ }
144
+ }
145
+ //# sourceMappingURL=traceHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traceHeader.js","sourceRoot":"","sources":["../../../src/tracing/traceHeader.ts"],"names":[],"mappings":"AAAA,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;SAC3B,QAAQ,CAAC,EAAE,CAAC;SACZ,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CACpB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAC/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAE/C,MAAM,aAAa,GAAG,uBAAuB,CAAC,EAAE,CAAC,CAAC;AAClD;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IAMtB;;;;;;;OAOG;IACH,YACE,OAAe,EACf,QAAgB,EAChB,UAAkB,EAClB,UAAqC;QAjB9B;;;;;WAAgB;QAChB;;;;;WAAiB;QACjB;;;;;WAAmB;QACnB;;;;;WAAmC;QAgB1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO;QACZ,OAAO,IAAI,WAAW,CACpB,aAAa,EACb,uBAAuB,CAAC,CAAC,CAAC,EAC1B,IAAI,EAAE,oGAAoG;QAC1G,EAAE,CACH,CAAC;IACJ,CAAC;IACD;;;;;;;;;OASG;IACH,MAAM,CAAC,eAAe,CACpB,OAA+B;QAE/B,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,GAC5C,OAAO,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAEzC,MAAM,UAAU,GACd,OAAO,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAC5C,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACZ,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACjB,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAA4B,CAC7B,IAAI,EAAE,CAAC;QACV,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CACX,IAAI,KAAK,CACP,oCAAoC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CACjE,CACF,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;;;;OASG;IACH,aAAa;QACX,OAAO;YACL,CAAC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,EAAE;YAC7E,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;iBAClD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;iBACxC,IAAI,CAAC,GAAG,CAAC;SACJ,CAAC;IACb,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,SAAiB;QACzB,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW;YAC7C,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI,SAAS,EAAE;YAC/C,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE;YACnE,GAAG,IAAI,CAAC,UAAU;YAClB,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["function generateRandomHexString(numBytes: number) {\n const hexPairs = new Array(numBytes).fill(0).map(() =>\n Math.floor(Math.random() * 16)\n .toString(16)\n .padStart(2, \"0\"),\n );\n return hexPairs.join(\"\");\n}\n\n/**\n * These are the headers that are used in the trace headers, could be found in the spec\n *\n * @see https://www.w3.org/TR/trace-context/#design-overview\n */\n\nexport const TRACE_HEADER_NAME = \"traceparent\";\n/**\n * These are the headers that are used in the trace headers, could be found in the spec\n *\n * @see https://www.w3.org/TR/trace-context/#design-overview\n */\nexport const TRACE_HEADER_STATE = \"tracestate\";\n\nconst clientTraceId = generateRandomHexString(16);\n/**\n * Some tools that are useful when dealing with the values\n * of the trace header. Follows the W3C trace context standard.\n *\n * @see https://www.w3.org/TR/trace-context/\n */\nexport class TraceHeader {\n readonly traceId: string;\n readonly parentId: string;\n readonly traceFlags: string;\n readonly traceState: Record<string, string>;\n\n /**\n * Initializes a new instance with the provided trace identifiers and state information.\n *\n * @param {string} traceId The unique identifier for the trace\n * @param {string} parentId The identifier of the parent trace\n * @param {string} traceFlags Flags containing trace-related options\n * @param {TraceHeader[\"traceState\"]} traceState The trace state information for additional trace context\n */\n constructor(\n traceId: string,\n parentId: string,\n traceFlags: string,\n traceState: TraceHeader[\"traceState\"],\n ) {\n this.traceId = traceId;\n this.parentId = parentId;\n this.traceFlags = traceFlags;\n this.traceState = traceState;\n }\n\n /**\n * Creating a default trace id that is a random setup for both trace id and parent id\n *\n * @example ```ts\n * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();\n * ```\n *\n * @returns {TraceHeader} A default trace header\n */\n static default() {\n return new TraceHeader(\n clientTraceId,\n generateRandomHexString(8),\n \"00\", //Means no flag have been set, and no sampled state https://www.w3.org/TR/trace-context/#trace-flags\n {},\n );\n }\n /**\n * Should be able to consume a trace header from the headers of an http request\n *\n * @example ```ts\n * const traceHeader = TraceHeader.fromTraceHeader(headers);\n * ```\n *\n * @param {Record<string,string>} headers The headers from the http request\n * @returns {TraceHeader | undefined} The trace header object, or nothing if not found\n */\n static fromTraceHeader(\n headers: Record<string, string>,\n ): TraceHeader | undefined {\n if (!headers[TRACE_HEADER_NAME]) {\n return undefined;\n }\n const [version, traceId, parentId, traceFlags] =\n headers[TRACE_HEADER_NAME]?.split(\"-\");\n\n const traceState =\n headers[TRACE_HEADER_STATE]?.split(\",\").reduce(\n (acc, curr) => {\n const [key, value] = curr.split(\"=\");\n acc[key] = value;\n return acc;\n },\n {} as Record<string, string>,\n ) || {};\n if (version !== \"00\") {\n console.debug(\n new Error(\n `Invalid version for traceheader: ${headers[TRACE_HEADER_NAME]}`,\n ),\n );\n return undefined;\n }\n return new TraceHeader(traceId, parentId, traceFlags, traceState);\n }\n\n /**\n * Should be able to convert the trace header to the format that is used in the headers of an http request\n *\n * @example ```ts\n * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();\n * const headers = traceHeader.toTraceHeader();\n * ```\n *\n * @returns {{traceparent: string, tracestate: string}} The trace header in the format of a record, used in our http client\n */\n toTraceHeader() {\n return {\n [TRACE_HEADER_NAME]: `00-${this.traceId}-${this.parentId}-${this.traceFlags}`,\n [TRACE_HEADER_STATE]: Object.entries(this.traceState)\n .map(([key, value]) => `${key}=${value}`)\n .join(\",\"),\n } as const;\n }\n\n /**\n * Should be able to create a new trace header with a new event in the trace state,\n * as the key of the eventName as breadcrumbs appending onto previous breadcrumbs with the - infix if exists. And the\n * trace parent gets updated as according to the docs\n *\n * @example ```ts\n * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();\n * const newTraceHeader = traceHeader.withEvent(\"newEvent\");\n * ```\n *\n * @param {string} eventName The key of the new event\n * @returns {TraceHeader} The new trace header\n */\n withEvent(eventName: string): TraceHeader {\n const breadcrumbs = this.traceState.breadcrumbs\n ? `${this.traceState.breadcrumbs}-${eventName}`\n : eventName;\n return new TraceHeader(this.traceId, this.parentId, this.traceFlags, {\n ...this.traceState,\n breadcrumbs,\n });\n }\n}\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Remove the tracking headers. This is used in our split transport to ensure that we remove the headers that
3
+ * are not used by the other systems.
4
+ *
5
+ * @param {unknown} x The headers to remove the tracking headers from
6
+ */
7
+ export declare function mutateRemoveTrackingHeaders(x?: unknown): void;
8
+ /**
9
+ * Update the headers with the trace header and breadcrumb.
10
+ *
11
+ * These trace headers are used in the imply ingestion pipeline to trace the request.
12
+ * And the breadcrumb is used to get finer grain details in the trace.
13
+ *
14
+ * Then there are the trace headers that are part of the W3C trace context standard.
15
+ *
16
+ * @param {string} crumb The crumb to add to the breadcrumb
17
+ * @returns {Function} A function that updates the headers
18
+ */
19
+ export declare function headersUpdate(crumb: string): (x: Record<string, string>) => {
20
+ traceparent: `00-${string}-${string}-${string}`;
21
+ tracestate: string;
22
+ "X-Alchemy-Client-Breadcrumb": string;
23
+ "X-Alchemy-Client-Trace-Id": string;
24
+ };
@@ -0,0 +1,61 @@
1
+ import { TRACE_HEADER_NAME, TRACE_HEADER_STATE, TraceHeader, } from "./traceHeader.js";
2
+ /**
3
+ * The header that is used to track the trace id.
4
+ * We use a client specific one to not mess with the span tracing of the servers.
5
+ *
6
+ * @see headersUpdate
7
+ */
8
+ const TRACKER_HEADER = "X-Alchemy-Client-Trace-Id";
9
+ /**
10
+ * The header that is used to track the breadcrumb.
11
+ *
12
+ * @see headersUpdate
13
+ */
14
+ const TRACKER_BREADCRUMB = "X-Alchemy-Client-Breadcrumb";
15
+ /**
16
+ * Remove the tracking headers. This is used in our split transport to ensure that we remove the headers that
17
+ * are not used by the other systems.
18
+ *
19
+ * @param {unknown} x The headers to remove the tracking headers from
20
+ */
21
+ export function mutateRemoveTrackingHeaders(x) {
22
+ if (!x)
23
+ return;
24
+ if (Array.isArray(x))
25
+ return;
26
+ if (typeof x !== "object")
27
+ return;
28
+ TRACKER_HEADER in x && delete x[TRACKER_HEADER];
29
+ TRACKER_BREADCRUMB in x && delete x[TRACKER_BREADCRUMB];
30
+ TRACE_HEADER_NAME in x && delete x[TRACE_HEADER_NAME];
31
+ TRACE_HEADER_STATE in x && delete x[TRACE_HEADER_STATE];
32
+ }
33
+ function addCrumb(previous, crumb) {
34
+ if (!previous)
35
+ return crumb;
36
+ return `${previous} > ${crumb}`;
37
+ }
38
+ /**
39
+ * Update the headers with the trace header and breadcrumb.
40
+ *
41
+ * These trace headers are used in the imply ingestion pipeline to trace the request.
42
+ * And the breadcrumb is used to get finer grain details in the trace.
43
+ *
44
+ * Then there are the trace headers that are part of the W3C trace context standard.
45
+ *
46
+ * @param {string} crumb The crumb to add to the breadcrumb
47
+ * @returns {Function} A function that updates the headers
48
+ */
49
+ export function headersUpdate(crumb) {
50
+ const headerUpdate_ = (x) => {
51
+ const traceHeader = (TraceHeader.fromTraceHeader(x) || TraceHeader.default()).withEvent(crumb);
52
+ return {
53
+ [TRACKER_HEADER]: traceHeader.parentId,
54
+ ...x,
55
+ [TRACKER_BREADCRUMB]: addCrumb(x[TRACKER_BREADCRUMB], crumb),
56
+ ...traceHeader.toTraceHeader(),
57
+ };
58
+ };
59
+ return headerUpdate_;
60
+ }
61
+ //# sourceMappingURL=updateHeaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateHeaders.js","sourceRoot":"","sources":["../../../src/tracing/updateHeaders.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAEnD;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,6BAA6B,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CAAC,CAAW;IACrD,IAAI,CAAC,CAAC;QAAE,OAAO;IACf,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO;IAC7B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO;IAClC,cAAc,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC;IAChD,kBAAkB,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC;IACxD,iBAAiB,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtD,kBAAkB,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,QAAQ,CAAC,QAA4B,EAAE,KAAa;IAC3D,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,GAAG,QAAQ,MAAM,KAAK,EAAE,CAAC;AAClC,CAAC;AACD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,aAAa,GAAG,CAAC,CAAyB,EAAE,EAAE;QAClD,MAAM,WAAW,GAAG,CAClB,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,CACxD,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO;YACL,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,QAAQ;YACtC,GAAG,CAAC;YACJ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC;YAC5D,GAAG,WAAW,CAAC,aAAa,EAAE;SAC/B,CAAC;IACJ,CAAC,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import {\n TRACE_HEADER_NAME,\n TRACE_HEADER_STATE,\n TraceHeader,\n} from \"./traceHeader.js\";\n\n/**\n * The header that is used to track the trace id.\n * We use a client specific one to not mess with the span tracing of the servers.\n *\n * @see headersUpdate\n */\nconst TRACKER_HEADER = \"X-Alchemy-Client-Trace-Id\";\n\n/**\n * The header that is used to track the breadcrumb.\n *\n * @see headersUpdate\n */\nconst TRACKER_BREADCRUMB = \"X-Alchemy-Client-Breadcrumb\";\n\n/**\n * Remove the tracking headers. This is used in our split transport to ensure that we remove the headers that\n * are not used by the other systems.\n *\n * @param {unknown} x The headers to remove the tracking headers from\n */\nexport function mutateRemoveTrackingHeaders(x?: unknown) {\n if (!x) return;\n if (Array.isArray(x)) return;\n if (typeof x !== \"object\") return;\n TRACKER_HEADER in x && delete x[TRACKER_HEADER];\n TRACKER_BREADCRUMB in x && delete x[TRACKER_BREADCRUMB];\n TRACE_HEADER_NAME in x && delete x[TRACE_HEADER_NAME];\n TRACE_HEADER_STATE in x && delete x[TRACE_HEADER_STATE];\n}\n\nfunction addCrumb(previous: string | undefined, crumb: string): string {\n if (!previous) return crumb;\n return `${previous} > ${crumb}`;\n}\n/**\n * Update the headers with the trace header and breadcrumb.\n *\n * These trace headers are used in the imply ingestion pipeline to trace the request.\n * And the breadcrumb is used to get finer grain details in the trace.\n *\n * Then there are the trace headers that are part of the W3C trace context standard.\n *\n * @param {string} crumb The crumb to add to the breadcrumb\n * @returns {Function} A function that updates the headers\n */\nexport function headersUpdate(crumb: string) {\n const headerUpdate_ = (x: Record<string, string>) => {\n const traceHeader = (\n TraceHeader.fromTraceHeader(x) || TraceHeader.default()\n ).withEvent(crumb);\n return {\n [TRACKER_HEADER]: traceHeader.parentId,\n ...x,\n [TRACKER_BREADCRUMB]: addCrumb(x[TRACKER_BREADCRUMB], crumb),\n ...traceHeader.toTraceHeader(),\n };\n };\n return headerUpdate_;\n}\n"]}
@@ -0,0 +1,110 @@
1
+ import { type Chain, type EIP1193RequestFn, type HttpTransportConfig, type RpcSchema, type Transport } from "viem";
2
+ /**
3
+ * Configuration options for the Alchemy transport.
4
+ * Extends viem's HttpTransportConfig with Alchemy-specific options while omitting
5
+ * options that are not relevant or supported by Alchemy.
6
+ */
7
+ export interface AlchemyTransportConfig extends Omit<HttpTransportConfig, "batch" | "key" | "methods" | "name" | "raw"> {
8
+ /** API key for Alchemy authentication */
9
+ apiKey?: string;
10
+ /** JWT token for authentication */
11
+ jwt?: string;
12
+ /** Custom RPC URL (optional - defaults to chain's Alchemy URL, but can be used to override the chain's Alchemy URL) */
13
+ url?: string;
14
+ }
15
+ type AlchemyTransportBase<rpcSchema extends RpcSchema | undefined = undefined> = Transport<"alchemyHttp", {
16
+ alchemyRpcUrl: string;
17
+ fetchOptions: AlchemyTransportConfig["fetchOptions"];
18
+ config: AlchemyTransportConfig;
19
+ }, EIP1193RequestFn<rpcSchema>>;
20
+ export type AlchemyTransport<rpcSchema extends RpcSchema | undefined = undefined> = AlchemyTransportBase<rpcSchema> & {
21
+ updateHeaders(newHeaders: HeadersInit): void;
22
+ };
23
+ /**
24
+ * A type guard for the transport to determine if it is an Alchemy transport.
25
+ * Used in cases where we would like to do switching depending on the transport.
26
+ *
27
+ * @param {Transport} transport The transport to check
28
+ * @param {Chain} chain Chain for the transport to run its function to return the transport config
29
+ * @returns {boolean} `true` if the transport is an Alchemy transport, otherwise `false`
30
+ */
31
+ export declare function isAlchemyTransport(transport: Transport, chain: Chain): transport is AlchemyTransport;
32
+ /**
33
+ * Creates an Alchemy HTTP transport for connecting to Alchemy's services.
34
+ *
35
+ * @example
36
+ * Using API Key:
37
+ * ```ts
38
+ * import { alchemyTransport } from "@alchemy/common";
39
+ *
40
+ * const transport = alchemyTransport({ apiKey: "your-api-key" });
41
+ * ```
42
+ *
43
+ * @example
44
+ * Using JWT:
45
+ * ```ts
46
+ * import { alchemyTransport } from "@alchemy/common";
47
+ *
48
+ * const transport = alchemyTransport({ jwt: "your-jwt-token" });
49
+ * ```
50
+ *
51
+ * @example
52
+ * Using URL directly:
53
+ * ```ts
54
+ * import { alchemyTransport } from "@alchemy/common";
55
+ *
56
+ * const transport = alchemyTransport({ url: "https://eth-mainnet.g.alchemy.com/v2/your-key" });
57
+ * ```
58
+ *
59
+ * @example
60
+ * Using custom URL with API key:
61
+ * ```ts
62
+ * import { alchemyTransport } from "@alchemy/common";
63
+ *
64
+ * const transport = alchemyTransport({
65
+ * url: "https://custom-alchemy.com/v2",
66
+ * apiKey: "your-api-key"
67
+ * });
68
+ * ```
69
+ *
70
+ * @example
71
+ * Using custom URL with JWT:
72
+ * ```ts
73
+ * import { alchemyTransport } from "@alchemy/common";
74
+ *
75
+ * const transport = alchemyTransport({
76
+ * url: "https://custom-alchemy.com/v2",
77
+ * jwt: "your-jwt-token"
78
+ * });
79
+ * ```
80
+ *
81
+ * @example
82
+ * Using HTTP debugging options:
83
+ * ```ts
84
+ * import { alchemyTransport } from "@alchemy/common";
85
+ *
86
+ * const transport = alchemyTransport({
87
+ * apiKey: "your-api-key",
88
+ * onFetchRequest: (request) => console.log("Request:", request),
89
+ * onFetchResponse: (response) => console.log("Response:", response),
90
+ * timeout: 30000,
91
+ * retryCount: 3,
92
+ * retryDelay: 1000
93
+ * });
94
+ * ```
95
+ *
96
+ * @param {AlchemyTransportConfig} config - The configuration object for the Alchemy transport (extends viem's HttpTransportConfig)
97
+ * @param {string} [config.apiKey] - API key for Alchemy authentication
98
+ * @param {string} [config.jwt] - JWT token for authentication
99
+ * @param {string} [config.url] - Direct URL to Alchemy endpoint or a proxy URL
100
+ * @param {Function} [config.onFetchRequest] - Callback for debugging outgoing requests
101
+ * @param {Function} [config.onFetchResponse] - Callback for debugging responses
102
+ * @param {number} [config.timeout] - Request timeout in milliseconds
103
+ * @param {number} [config.retryCount] - The number of retry attempts
104
+ * @param {number} [config.retryDelay] - The delay between retries, in milliseconds
105
+ * @param {object} [config.fetchOptions] - Optional fetch options for HTTP requests
106
+ * @param {object} [config.httpOptions] - HTTP transport options for debugging (onFetchRequest, onFetchResponse, timeout, batch)
107
+ * @returns {AlchemyTransport} The configured Alchemy transport function
108
+ */
109
+ export declare function alchemyTransport<rpcSchema extends RpcSchema | undefined = undefined>(config: AlchemyTransportConfig): AlchemyTransport<rpcSchema>;
110
+ export {};
@@ -0,0 +1,164 @@
1
+ import { createTransport, http, } from "viem";
2
+ import { BaseError } from "../errors/BaseError.js";
3
+ import { mutateRemoveTrackingHeaders } from "../tracing/updateHeaders.js";
4
+ import { ChainNotFoundError } from "../errors/ChainNotFoundError.js";
5
+ import { getAlchemyRpcUrl } from "./chainRegistry.js";
6
+ import { convertHeadersToObject, withAlchemyHeaders, } from "../utils/headers.js";
7
+ /**
8
+ * A type guard for the transport to determine if it is an Alchemy transport.
9
+ * Used in cases where we would like to do switching depending on the transport.
10
+ *
11
+ * @param {Transport} transport The transport to check
12
+ * @param {Chain} chain Chain for the transport to run its function to return the transport config
13
+ * @returns {boolean} `true` if the transport is an Alchemy transport, otherwise `false`
14
+ */
15
+ export function isAlchemyTransport(transport, chain) {
16
+ return transport({ chain }).config.type === "alchemyHttp";
17
+ }
18
+ /**
19
+ * Creates an Alchemy HTTP transport for connecting to Alchemy's services.
20
+ *
21
+ * @example
22
+ * Using API Key:
23
+ * ```ts
24
+ * import { alchemyTransport } from "@alchemy/common";
25
+ *
26
+ * const transport = alchemyTransport({ apiKey: "your-api-key" });
27
+ * ```
28
+ *
29
+ * @example
30
+ * Using JWT:
31
+ * ```ts
32
+ * import { alchemyTransport } from "@alchemy/common";
33
+ *
34
+ * const transport = alchemyTransport({ jwt: "your-jwt-token" });
35
+ * ```
36
+ *
37
+ * @example
38
+ * Using URL directly:
39
+ * ```ts
40
+ * import { alchemyTransport } from "@alchemy/common";
41
+ *
42
+ * const transport = alchemyTransport({ url: "https://eth-mainnet.g.alchemy.com/v2/your-key" });
43
+ * ```
44
+ *
45
+ * @example
46
+ * Using custom URL with API key:
47
+ * ```ts
48
+ * import { alchemyTransport } from "@alchemy/common";
49
+ *
50
+ * const transport = alchemyTransport({
51
+ * url: "https://custom-alchemy.com/v2",
52
+ * apiKey: "your-api-key"
53
+ * });
54
+ * ```
55
+ *
56
+ * @example
57
+ * Using custom URL with JWT:
58
+ * ```ts
59
+ * import { alchemyTransport } from "@alchemy/common";
60
+ *
61
+ * const transport = alchemyTransport({
62
+ * url: "https://custom-alchemy.com/v2",
63
+ * jwt: "your-jwt-token"
64
+ * });
65
+ * ```
66
+ *
67
+ * @example
68
+ * Using HTTP debugging options:
69
+ * ```ts
70
+ * import { alchemyTransport } from "@alchemy/common";
71
+ *
72
+ * const transport = alchemyTransport({
73
+ * apiKey: "your-api-key",
74
+ * onFetchRequest: (request) => console.log("Request:", request),
75
+ * onFetchResponse: (response) => console.log("Response:", response),
76
+ * timeout: 30000,
77
+ * retryCount: 3,
78
+ * retryDelay: 1000
79
+ * });
80
+ * ```
81
+ *
82
+ * @param {AlchemyTransportConfig} config - The configuration object for the Alchemy transport (extends viem's HttpTransportConfig)
83
+ * @param {string} [config.apiKey] - API key for Alchemy authentication
84
+ * @param {string} [config.jwt] - JWT token for authentication
85
+ * @param {string} [config.url] - Direct URL to Alchemy endpoint or a proxy URL
86
+ * @param {Function} [config.onFetchRequest] - Callback for debugging outgoing requests
87
+ * @param {Function} [config.onFetchResponse] - Callback for debugging responses
88
+ * @param {number} [config.timeout] - Request timeout in milliseconds
89
+ * @param {number} [config.retryCount] - The number of retry attempts
90
+ * @param {number} [config.retryDelay] - The delay between retries, in milliseconds
91
+ * @param {object} [config.fetchOptions] - Optional fetch options for HTTP requests
92
+ * @param {object} [config.httpOptions] - HTTP transport options for debugging (onFetchRequest, onFetchResponse, timeout, batch)
93
+ * @returns {AlchemyTransport} The configured Alchemy transport function
94
+ */
95
+ export function alchemyTransport(config) {
96
+ const { apiKey, jwt, url, fetchOptions: fetchOptions_, retryCount, retryDelay, ...httpTransportConfig } = config;
97
+ // Create a copy of fetch options for modification
98
+ const fetchOptions = { ...fetchOptions_ };
99
+ fetchOptions.headers = withAlchemyHeaders({
100
+ headers: fetchOptions.headers,
101
+ apiKey,
102
+ jwt,
103
+ });
104
+ const transport = (opts) => {
105
+ const { chain } = opts;
106
+ mutateRemoveTrackingHeaders(config?.fetchOptions?.headers);
107
+ const rpcUrl = (() => {
108
+ if (url) {
109
+ return url;
110
+ }
111
+ if (!chain) {
112
+ throw new ChainNotFoundError();
113
+ }
114
+ const alchemyUrl = getAlchemyRpcUrl(chain.id);
115
+ if (alchemyUrl) {
116
+ return alchemyUrl;
117
+ }
118
+ // Fallback: check for legacy alchemy RPC URLs in chain definition
119
+ if (chain.rpcUrls?.alchemy?.http?.[0]) {
120
+ return chain.rpcUrls.alchemy.http[0];
121
+ }
122
+ throw new BaseError(`Chain ${chain.id} (${chain.name}) is not supported by Alchemy. To use this chain:\n\n` +
123
+ `1. Use a direct RPC URL:\n` +
124
+ ` alchemyTransport({ url: "https://your-alchemy-endpoint.com/v2/your-key" })\n\n` +
125
+ `2. Add alchemy RPC to your chain definition:\n` +
126
+ ` defineChain({ rpcUrls: { alchemy: { http: ["https://your-alchemy-url/v2"] }}})\n\n` +
127
+ `3. Or use a standard RPC provider:\n` +
128
+ ` import { http } from "viem";\n` +
129
+ ` http("https://your-standard-rpc.com")`);
130
+ })();
131
+ const innerTransport = http(rpcUrl, {
132
+ // Standard viem options are passed through to the underlying transport, with
133
+ // the exception of retryCount and retryDelay because those are handled by
134
+ // the outer Alchemy transport.
135
+ ...httpTransportConfig,
136
+ fetchOptions,
137
+ // Retry count must be 0 here in order to respect the retry
138
+ // count that is already specified on the underlying transport.
139
+ retryCount: 0,
140
+ });
141
+ return createTransport({
142
+ key: "alchemyHttp",
143
+ name: "Alchemy HTTP Transport",
144
+ request: innerTransport(opts).request,
145
+ retryCount: retryCount ?? opts?.retryCount,
146
+ retryDelay,
147
+ type: "alchemyHttp",
148
+ }, {
149
+ alchemyRpcUrl: rpcUrl,
150
+ fetchOptions,
151
+ config,
152
+ });
153
+ };
154
+ return Object.assign(transport, {
155
+ updateHeaders(newHeaders_) {
156
+ const newHeaders = convertHeadersToObject(newHeaders_);
157
+ fetchOptions.headers = {
158
+ ...fetchOptions.headers,
159
+ ...newHeaders,
160
+ };
161
+ },
162
+ });
163
+ }
164
+ //# sourceMappingURL=alchemy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alchemy.js","sourceRoot":"","sources":["../../../src/transport/alchemy.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createTransport,\n http,\n type Chain,\n type EIP1193RequestFn,\n type HttpTransportConfig,\n type RpcSchema,\n type Transport,\n} from \"viem\";\nimport { BaseError } from \"../errors/BaseError.js\";\nimport { mutateRemoveTrackingHeaders } from \"../tracing/updateHeaders.js\";\nimport { ChainNotFoundError } from \"../errors/ChainNotFoundError.js\";\nimport { getAlchemyRpcUrl } from \"./chainRegistry.js\";\nimport {\n convertHeadersToObject,\n withAlchemyHeaders,\n} from \"../utils/headers.js\";\n\n/**\n * Configuration options for the Alchemy transport.\n * Extends viem's HttpTransportConfig with Alchemy-specific options while omitting\n * options that are not relevant or supported by Alchemy.\n */\nexport interface AlchemyTransportConfig\n extends Omit<\n HttpTransportConfig,\n \"batch\" | \"key\" | \"methods\" | \"name\" | \"raw\"\n > {\n /** API key for Alchemy authentication */\n apiKey?: string;\n /** JWT token for authentication */\n jwt?: string;\n /** Custom RPC URL (optional - defaults to chain's Alchemy URL, but can be used to override the chain's Alchemy URL) */\n url?: string;\n}\n\ntype AlchemyTransportBase<rpcSchema extends RpcSchema | undefined = undefined> =\n Transport<\n \"alchemyHttp\",\n {\n alchemyRpcUrl: string;\n fetchOptions: AlchemyTransportConfig[\"fetchOptions\"];\n config: AlchemyTransportConfig;\n },\n EIP1193RequestFn<rpcSchema>\n >;\n\nexport type AlchemyTransport<\n rpcSchema extends RpcSchema | undefined = undefined,\n> = AlchemyTransportBase<rpcSchema> & {\n updateHeaders(newHeaders: HeadersInit): void;\n};\n\n/**\n * A type guard for the transport to determine if it is an Alchemy transport.\n * Used in cases where we would like to do switching depending on the transport.\n *\n * @param {Transport} transport The transport to check\n * @param {Chain} chain Chain for the transport to run its function to return the transport config\n * @returns {boolean} `true` if the transport is an Alchemy transport, otherwise `false`\n */\nexport function isAlchemyTransport(\n transport: Transport,\n chain: Chain,\n): transport is AlchemyTransport {\n return transport({ chain }).config.type === \"alchemyHttp\";\n}\n\n/**\n * Creates an Alchemy HTTP transport for connecting to Alchemy's services.\n *\n * @example\n * Using API Key:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({ apiKey: \"your-api-key\" });\n * ```\n *\n * @example\n * Using JWT:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({ jwt: \"your-jwt-token\" });\n * ```\n *\n * @example\n * Using URL directly:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({ url: \"https://eth-mainnet.g.alchemy.com/v2/your-key\" });\n * ```\n *\n * @example\n * Using custom URL with API key:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({\n * url: \"https://custom-alchemy.com/v2\",\n * apiKey: \"your-api-key\"\n * });\n * ```\n *\n * @example\n * Using custom URL with JWT:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({\n * url: \"https://custom-alchemy.com/v2\",\n * jwt: \"your-jwt-token\"\n * });\n * ```\n *\n * @example\n * Using HTTP debugging options:\n * ```ts\n * import { alchemyTransport } from \"@alchemy/common\";\n *\n * const transport = alchemyTransport({\n * apiKey: \"your-api-key\",\n * onFetchRequest: (request) => console.log(\"Request:\", request),\n * onFetchResponse: (response) => console.log(\"Response:\", response),\n * timeout: 30000,\n * retryCount: 3,\n * retryDelay: 1000\n * });\n * ```\n *\n * @param {AlchemyTransportConfig} config - The configuration object for the Alchemy transport (extends viem's HttpTransportConfig)\n * @param {string} [config.apiKey] - API key for Alchemy authentication\n * @param {string} [config.jwt] - JWT token for authentication\n * @param {string} [config.url] - Direct URL to Alchemy endpoint or a proxy URL\n * @param {Function} [config.onFetchRequest] - Callback for debugging outgoing requests\n * @param {Function} [config.onFetchResponse] - Callback for debugging responses\n * @param {number} [config.timeout] - Request timeout in milliseconds\n * @param {number} [config.retryCount] - The number of retry attempts\n * @param {number} [config.retryDelay] - The delay between retries, in milliseconds\n * @param {object} [config.fetchOptions] - Optional fetch options for HTTP requests\n * @param {object} [config.httpOptions] - HTTP transport options for debugging (onFetchRequest, onFetchResponse, timeout, batch)\n * @returns {AlchemyTransport} The configured Alchemy transport function\n */\nexport function alchemyTransport<\n rpcSchema extends RpcSchema | undefined = undefined,\n>(config: AlchemyTransportConfig): AlchemyTransport<rpcSchema> {\n const {\n apiKey,\n jwt,\n url,\n fetchOptions: fetchOptions_,\n retryCount,\n retryDelay,\n ...httpTransportConfig\n } = config;\n\n // Create a copy of fetch options for modification\n const fetchOptions = { ...fetchOptions_ };\n\n fetchOptions.headers = withAlchemyHeaders({\n headers: fetchOptions.headers,\n apiKey,\n jwt,\n });\n\n const transport: AlchemyTransportBase = (opts) => {\n const { chain } = opts;\n\n mutateRemoveTrackingHeaders(config?.fetchOptions?.headers);\n\n const rpcUrl = (() => {\n if (url) {\n return url;\n }\n\n if (!chain) {\n throw new ChainNotFoundError();\n }\n\n const alchemyUrl = getAlchemyRpcUrl(chain.id);\n if (alchemyUrl) {\n return alchemyUrl;\n }\n\n // Fallback: check for legacy alchemy RPC URLs in chain definition\n if (chain.rpcUrls?.alchemy?.http?.[0]) {\n return chain.rpcUrls.alchemy.http[0];\n }\n\n throw new BaseError(\n `Chain ${chain.id} (${chain.name}) is not supported by Alchemy. To use this chain:\\n\\n` +\n `1. Use a direct RPC URL:\\n` +\n ` alchemyTransport({ url: \"https://your-alchemy-endpoint.com/v2/your-key\" })\\n\\n` +\n `2. Add alchemy RPC to your chain definition:\\n` +\n ` defineChain({ rpcUrls: { alchemy: { http: [\"https://your-alchemy-url/v2\"] }}})\\n\\n` +\n `3. Or use a standard RPC provider:\\n` +\n ` import { http } from \"viem\";\\n` +\n ` http(\"https://your-standard-rpc.com\")`,\n );\n })();\n\n const innerTransport = http(rpcUrl, {\n // Standard viem options are passed through to the underlying transport, with\n // the exception of retryCount and retryDelay because those are handled by\n // the outer Alchemy transport.\n ...httpTransportConfig,\n fetchOptions,\n // Retry count must be 0 here in order to respect the retry\n // count that is already specified on the underlying transport.\n retryCount: 0,\n });\n\n return createTransport(\n {\n key: \"alchemyHttp\",\n name: \"Alchemy HTTP Transport\",\n request: innerTransport(opts).request,\n retryCount: retryCount ?? opts?.retryCount,\n retryDelay,\n type: \"alchemyHttp\",\n },\n {\n alchemyRpcUrl: rpcUrl,\n fetchOptions,\n config,\n },\n );\n };\n\n return Object.assign(transport, {\n updateHeaders(newHeaders_: HeadersInit) {\n const newHeaders = convertHeadersToObject(newHeaders_);\n\n fetchOptions.headers = {\n ...fetchOptions.headers,\n ...newHeaders,\n };\n },\n });\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Internal registry mapping chain IDs to Alchemy RPC base URLs.
3
+ * This replaces the need for custom chain exports with embedded Alchemy URLs.
4
+ */
5
+ export declare const ALCHEMY_RPC_MAPPING: Record<number, string>;
6
+ /**
7
+ * Gets the Alchemy RPC base URL for a given chain ID.
8
+ *
9
+ * @param {number} chainId The chain ID to lookup
10
+ * @returns {string | undefined} The Alchemy RPC base URL or undefined if not supported
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const rpcUrl = getAlchemyRpcUrl(1); // "https://eth-mainnet.g.alchemy.com/v2"
15
+ * const customUrl = getAlchemyRpcUrl(999); // undefined
16
+ * ```
17
+ */
18
+ export declare function getAlchemyRpcUrl(chainId: number): string | undefined;
19
+ /**
20
+ * Checks if a chain ID is supported by the Alchemy RPC registry.
21
+ *
22
+ * @param {number} chainId The chain ID to check
23
+ * @returns {boolean} True if the chain is supported, false otherwise
24
+ */
25
+ export declare function isChainSupported(chainId: number): boolean;
26
+ /**
27
+ * Gets all supported chain IDs from the registry.
28
+ *
29
+ * @returns {number[]} Array of supported chain IDs
30
+ */
31
+ export declare function getSupportedChainIds(): number[];