@aa-sdk/core 4.20.1 → 4.22.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 (97) hide show
  1. package/dist/esm/actions/smartAccount/buildUserOperation.d.ts +3 -3
  2. package/dist/esm/actions/smartAccount/buildUserOperation.js +7 -3
  3. package/dist/esm/actions/smartAccount/buildUserOperation.js.map +1 -1
  4. package/dist/esm/actions/smartAccount/buildUserOperationFromTx.d.ts +2 -2
  5. package/dist/esm/actions/smartAccount/buildUserOperationFromTx.js +4 -2
  6. package/dist/esm/actions/smartAccount/buildUserOperationFromTx.js.map +1 -1
  7. package/dist/esm/actions/smartAccount/buildUserOperationFromTxs.d.ts +2 -2
  8. package/dist/esm/actions/smartAccount/buildUserOperationFromTxs.js +4 -2
  9. package/dist/esm/actions/smartAccount/buildUserOperationFromTxs.js.map +1 -1
  10. package/dist/esm/actions/smartAccount/checkGasSponsorshipEligibility.d.ts +2 -2
  11. package/dist/esm/actions/smartAccount/checkGasSponsorshipEligibility.js +4 -2
  12. package/dist/esm/actions/smartAccount/checkGasSponsorshipEligibility.js.map +1 -1
  13. package/dist/esm/actions/smartAccount/dropAndReplaceUserOperation.d.ts +2 -2
  14. package/dist/esm/actions/smartAccount/dropAndReplaceUserOperation.js +4 -2
  15. package/dist/esm/actions/smartAccount/dropAndReplaceUserOperation.js.map +1 -1
  16. package/dist/esm/actions/smartAccount/estimateUserOperationGas.d.ts +2 -2
  17. package/dist/esm/actions/smartAccount/estimateUserOperationGas.js +4 -2
  18. package/dist/esm/actions/smartAccount/estimateUserOperationGas.js.map +1 -1
  19. package/dist/esm/actions/smartAccount/sendTransaction.d.ts +2 -2
  20. package/dist/esm/actions/smartAccount/sendTransaction.js +4 -2
  21. package/dist/esm/actions/smartAccount/sendTransaction.js.map +1 -1
  22. package/dist/esm/actions/smartAccount/sendTransactions.d.ts +2 -2
  23. package/dist/esm/actions/smartAccount/sendTransactions.js +4 -2
  24. package/dist/esm/actions/smartAccount/sendTransactions.js.map +1 -1
  25. package/dist/esm/actions/smartAccount/sendUserOperation.d.ts +2 -2
  26. package/dist/esm/actions/smartAccount/sendUserOperation.js +4 -2
  27. package/dist/esm/actions/smartAccount/sendUserOperation.js.map +1 -1
  28. package/dist/esm/actions/smartAccount/upgradeAccount.js +3 -1
  29. package/dist/esm/actions/smartAccount/upgradeAccount.js.map +1 -1
  30. package/dist/esm/actions/smartAccount/waitForUserOperationTransacation.d.ts +1 -1
  31. package/dist/esm/actions/smartAccount/waitForUserOperationTransacation.js +4 -2
  32. package/dist/esm/actions/smartAccount/waitForUserOperationTransacation.js.map +1 -1
  33. package/dist/esm/client/addBreadcrumb.d.ts +13 -0
  34. package/dist/esm/client/addBreadcrumb.js +22 -0
  35. package/dist/esm/client/addBreadcrumb.js.map +1 -0
  36. package/dist/esm/client/smartAccountClient.d.ts +9 -0
  37. package/dist/esm/client/smartAccountClient.js +14 -4
  38. package/dist/esm/client/smartAccountClient.js.map +1 -1
  39. package/dist/esm/index.d.ts +2 -0
  40. package/dist/esm/index.js +2 -0
  41. package/dist/esm/index.js.map +1 -1
  42. package/dist/esm/utils/traceHeader.d.ts +70 -0
  43. package/dist/esm/utils/traceHeader.js +133 -0
  44. package/dist/esm/utils/traceHeader.js.map +1 -0
  45. package/dist/esm/utils/userop.js +4 -4
  46. package/dist/esm/utils/userop.js.map +1 -1
  47. package/dist/esm/version.d.ts +1 -1
  48. package/dist/esm/version.js +1 -1
  49. package/dist/esm/version.js.map +1 -1
  50. package/dist/types/actions/smartAccount/buildUserOperation.d.ts +3 -3
  51. package/dist/types/actions/smartAccount/buildUserOperation.d.ts.map +1 -1
  52. package/dist/types/actions/smartAccount/buildUserOperationFromTx.d.ts +2 -2
  53. package/dist/types/actions/smartAccount/buildUserOperationFromTx.d.ts.map +1 -1
  54. package/dist/types/actions/smartAccount/buildUserOperationFromTxs.d.ts +2 -2
  55. package/dist/types/actions/smartAccount/buildUserOperationFromTxs.d.ts.map +1 -1
  56. package/dist/types/actions/smartAccount/checkGasSponsorshipEligibility.d.ts +2 -2
  57. package/dist/types/actions/smartAccount/checkGasSponsorshipEligibility.d.ts.map +1 -1
  58. package/dist/types/actions/smartAccount/dropAndReplaceUserOperation.d.ts +2 -2
  59. package/dist/types/actions/smartAccount/dropAndReplaceUserOperation.d.ts.map +1 -1
  60. package/dist/types/actions/smartAccount/estimateUserOperationGas.d.ts +2 -2
  61. package/dist/types/actions/smartAccount/estimateUserOperationGas.d.ts.map +1 -1
  62. package/dist/types/actions/smartAccount/sendTransaction.d.ts +2 -2
  63. package/dist/types/actions/smartAccount/sendTransaction.d.ts.map +1 -1
  64. package/dist/types/actions/smartAccount/sendTransactions.d.ts +2 -2
  65. package/dist/types/actions/smartAccount/sendTransactions.d.ts.map +1 -1
  66. package/dist/types/actions/smartAccount/sendUserOperation.d.ts +2 -2
  67. package/dist/types/actions/smartAccount/sendUserOperation.d.ts.map +1 -1
  68. package/dist/types/actions/smartAccount/upgradeAccount.d.ts.map +1 -1
  69. package/dist/types/actions/smartAccount/waitForUserOperationTransacation.d.ts +1 -1
  70. package/dist/types/actions/smartAccount/waitForUserOperationTransacation.d.ts.map +1 -1
  71. package/dist/types/client/addBreadcrumb.d.ts +14 -0
  72. package/dist/types/client/addBreadcrumb.d.ts.map +1 -0
  73. package/dist/types/client/smartAccountClient.d.ts +9 -0
  74. package/dist/types/client/smartAccountClient.d.ts.map +1 -1
  75. package/dist/types/index.d.ts +2 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/dist/types/utils/traceHeader.d.ts +71 -0
  78. package/dist/types/utils/traceHeader.d.ts.map +1 -0
  79. package/dist/types/version.d.ts +1 -1
  80. package/package.json +2 -2
  81. package/src/actions/smartAccount/buildUserOperation.ts +7 -4
  82. package/src/actions/smartAccount/buildUserOperationFromTx.ts +4 -2
  83. package/src/actions/smartAccount/buildUserOperationFromTxs.ts +4 -2
  84. package/src/actions/smartAccount/checkGasSponsorshipEligibility.ts +4 -2
  85. package/src/actions/smartAccount/dropAndReplaceUserOperation.ts +4 -2
  86. package/src/actions/smartAccount/estimateUserOperationGas.ts +4 -2
  87. package/src/actions/smartAccount/sendTransaction.ts +4 -2
  88. package/src/actions/smartAccount/sendTransactions.ts +4 -2
  89. package/src/actions/smartAccount/sendUserOperation.ts +4 -2
  90. package/src/actions/smartAccount/upgradeAccount.ts +3 -1
  91. package/src/actions/smartAccount/waitForUserOperationTransacation.ts +4 -2
  92. package/src/client/addBreadcrumb.ts +25 -0
  93. package/src/client/smartAccountClient.ts +23 -3
  94. package/src/index.ts +2 -0
  95. package/src/utils/traceHeader.ts +133 -0
  96. package/src/utils/userop.ts +4 -4
  97. package/src/version.ts +1 -1
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Some tools that are useful when dealing with the values
3
+ * of the trace header. Follows the W3C trace context standard.
4
+ *
5
+ * @see https://www.w3.org/TR/trace-context/
6
+ */
7
+ export declare class TraceHeader {
8
+ readonly traceId: string;
9
+ readonly parentId: string;
10
+ readonly traceFlags: string;
11
+ readonly traceState: Record<string, string>;
12
+ /**
13
+ * Initializes a new instance with the provided trace identifiers and state information.
14
+ *
15
+ * @param {string} traceId The unique identifier for the trace
16
+ * @param {string} parentId The identifier of the parent trace
17
+ * @param {string} traceFlags Flags containing trace-related options
18
+ * @param {TraceHeader["traceState"]} traceState The trace state information for additional trace context
19
+ */
20
+ constructor(traceId: string, parentId: string, traceFlags: string, traceState: TraceHeader["traceState"]);
21
+ /**
22
+ * Creating a default trace id that is a random setup for both trace id and parent id
23
+ *
24
+ * @example ```ts
25
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
26
+ * ```
27
+ *
28
+ * @returns {TraceHeader} A default trace header
29
+ */
30
+ static default(): TraceHeader;
31
+ /**
32
+ * Should be able to consume a trace header from the headers of an http request
33
+ *
34
+ * @example ```ts
35
+ * const traceHeader = TraceHeader.fromTraceHeader(headers);
36
+ * ```
37
+ *
38
+ * @param {Record<string,string>} headers The headers from the http request
39
+ * @returns {TraceHeader | undefined} The trace header object, or nothing if not found
40
+ */
41
+ static fromTraceHeader(headers: Record<string, string>): TraceHeader | undefined;
42
+ /**
43
+ * Should be able to convert the trace header to the format that is used in the headers of an http request
44
+ *
45
+ * @example ```ts
46
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
47
+ * const headers = traceHeader.toTraceHeader();
48
+ * ```
49
+ *
50
+ * @returns {{stracheader: string, tracestate: string}} The trace header in the format of a record, used in our http client
51
+ */
52
+ toTraceHeader(): {
53
+ readonly traceheader: `00-${string}-${string}-${string}`;
54
+ readonly tracestate: string;
55
+ };
56
+ /**
57
+ * Should be able to create a new trace header with a new event in the trace state,
58
+ * as the key of the eventName as breadcrumbs appending onto previous breadcrumbs with the - infix if exists. And the
59
+ * trace parent gets updated as according to the docs
60
+ *
61
+ * @example ```ts
62
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
63
+ * const newTraceHeader = traceHeader.withEvent("newEvent");
64
+ * ```
65
+ *
66
+ * @param {string} eventName The key of the new event
67
+ * @returns {TraceHeader} The new trace header
68
+ */
69
+ withEvent(eventName: string): TraceHeader;
70
+ }
71
+ //# sourceMappingURL=traceHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traceHeader.d.ts","sourceRoot":"","sources":["../../../src/utils/traceHeader.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE5C;;;;;;;OAOG;gBAED,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC;IAQvC;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO;IAQd;;;;;;;;;OASG;IACH,MAAM,CAAC,eAAe,CACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,WAAW,GAAG,SAAS;IAsB1B;;;;;;;;;OASG;IACH,aAAa;;;;IASb;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;CAS1C"}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "4.20.1";
1
+ export declare const VERSION = "4.22.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aa-sdk/core",
3
3
  "license": "MIT",
4
- "version": "4.20.1",
4
+ "version": "4.22.0",
5
5
  "description": "viem based SDK that enables interactions with ERC-4337 Smart Accounts. ABIs are based off the definitions generated in @account-abstraction/contracts",
6
6
  "author": "Alchemy",
7
7
  "type": "module",
@@ -65,5 +65,5 @@
65
65
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
66
66
  },
67
67
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
68
- "gitHead": "8ee8571d4bbf78d75fb7c2a40e299808eaa63bfb"
68
+ "gitHead": "07a9e38db91c0a8937f3e2f28e25c95605e31698"
69
69
  }
@@ -1,4 +1,4 @@
1
- import type { Chain, Client, Transport } from "viem";
1
+ import { type Chain, type Client, type Transport } from "viem";
2
2
  import {
3
3
  type GetEntryPointFromAccount,
4
4
  type SmartContractAccount,
@@ -13,7 +13,9 @@ import type {
13
13
  BuildUserOperationParameters,
14
14
  UserOperationContext,
15
15
  } from "./types";
16
+ import { clientHeaderTrack } from "../../client/addBreadcrumb.js";
16
17
 
18
+ const USER_OPERATION_METHOD = "buildUserOperation";
17
19
  /**
18
20
  * Builds a user operation using the provided client and operation parameters. Ensures that the account exists and the client is compatible.
19
21
  *
@@ -33,7 +35,7 @@ import type {
33
35
  * });
34
36
  * ```
35
37
  *
36
- * @param {Client<TTransport, TChain, TAccount>} client the client instance used to build the user operation
38
+ * @param {Client<TTransport, TChain, TAccount>} client_ the client instance used to build the user operation
37
39
  * @param {BuildUserOperationParameters<TAccount, TContext, TEntryPointVersion>} args the parameters required to build the user operation, including account, overrides, and context
38
40
  * @returns {Promise<UserOperationStruct<TEntryPointVersion>>} a promise that resolves to a `UserOperationStruct` object containing the built user operation details
39
41
  */
@@ -48,9 +50,10 @@ export async function buildUserOperation<
48
50
  | undefined,
49
51
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
50
52
  >(
51
- client: Client<TTransport, TChain, TAccount>,
53
+ client_: Client<TTransport, TChain, TAccount>,
52
54
  args: BuildUserOperationParameters<TAccount, TContext, TEntryPointVersion>
53
55
  ): Promise<UserOperationStruct<TEntryPointVersion>> {
56
+ const client = clientHeaderTrack(client_, USER_OPERATION_METHOD);
54
57
  const { account = client.account, overrides, context } = args;
55
58
  if (!account) {
56
59
  throw new AccountNotFoundError();
@@ -59,7 +62,7 @@ export async function buildUserOperation<
59
62
  if (!isBaseSmartAccountClient(client)) {
60
63
  throw new IncompatibleClientError(
61
64
  "BaseSmartAccountClient",
62
- "buildUserOperation",
65
+ USER_OPERATION_METHOD,
63
66
  client
64
67
  );
65
68
  }
@@ -18,6 +18,7 @@ import type {
18
18
  } from "../../types.js";
19
19
  import { buildUserOperation } from "./buildUserOperation.js";
20
20
  import type { UserOperationContext } from "./types.js";
21
+ import { clientHeaderTrack } from "../../index.js";
21
22
 
22
23
  /**
23
24
  * Performs `buildUserOperationFromTx` in batch and builds into a single, yet to be signed `UserOperation` (UO) struct. The output user operation struct will be filled with all gas fields (and paymaster data if a paymaster is used) based on the transactions data (`to`, `data`, `value`, `maxFeePerGas`, `maxPriorityFeePerGas`) computed using the configured `ClientMiddlewares` on the `SmartAccountClient`
@@ -52,7 +53,7 @@ import type { UserOperationContext } from "./types.js";
52
53
  * const uoHash = await smartAccountClient.sendRawUserOperation({ request, entryPoint: entryPointAddress });
53
54
  * ```
54
55
  *
55
- * @param {Client<Transport, TChain, TAccount>} client the smart account client to use for RPC requests
56
+ * @param {Client<Transport, TChain, TAccount>} client_ the smart account client to use for RPC requests
56
57
  * @param {SendTransactionParameters} args the send tx parameters
57
58
  * @param {UserOperationOverrides} overrides optional overrides to use for any of the fields
58
59
  * @param {TContext} context if the smart account client requires additinoal context for building UOs
@@ -69,11 +70,12 @@ export async function buildUserOperationFromTx<
69
70
  | undefined,
70
71
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
71
72
  >(
72
- client: Client<Transport, TChain, TAccount>,
73
+ client_: Client<Transport, TChain, TAccount>,
73
74
  args: SendTransactionParameters<TChain, TAccount, TChainOverride>,
74
75
  overrides?: UserOperationOverrides<TEntryPointVersion>,
75
76
  context?: TContext
76
77
  ): Promise<UserOperationStruct<TEntryPointVersion>> {
78
+ const client = clientHeaderTrack(client_, "buildUserOperationFromTx");
77
79
  const { account = client.account, ...request } = args;
78
80
  if (!account || typeof account === "string") {
79
81
  throw new AccountNotFoundError();
@@ -15,6 +15,7 @@ import type {
15
15
  BuildUserOperationFromTransactionsResult,
16
16
  UserOperationContext,
17
17
  } from "./types";
18
+ import { clientHeaderTrack } from "../../index.js";
18
19
 
19
20
  /**
20
21
  * Performs `buildUserOperationFromTx` in batch and builds into a single,
@@ -66,7 +67,7 @@ import type {
66
67
  * });
67
68
  * ```
68
69
  *
69
- * @param {Client<TTransport, TChain, TAccount>} client the smart account client to use to make RPC calls
70
+ * @param {Client<TTransport, TChain, TAccount>} client_ the smart account client to use to make RPC calls
70
71
  * @param {BuildTransactionParameters} args an object containing the requests to build as well as, the account if not hoisted, the context, the overrides, and optionally a flag to enable signing of the UO via the underlying middleware
71
72
  * @returns {Promise<BuildUserOperationFromTransactionsResult<TEntryPointVersion>>} a Promise containing the built user operation
72
73
  */
@@ -81,9 +82,10 @@ export async function buildUserOperationFromTxs<
81
82
  | UserOperationContext
82
83
  | undefined
83
84
  >(
84
- client: Client<TTransport, TChain, TAccount>,
85
+ client_: Client<TTransport, TChain, TAccount>,
85
86
  args: BuildTransactionParameters<TAccount, TContext, TEntryPointVersion>
86
87
  ): Promise<BuildUserOperationFromTransactionsResult<TEntryPointVersion>> {
88
+ const client = clientHeaderTrack(client_, "buildUserOperationFromTxs");
87
89
  const { account = client.account, requests, overrides, context } = args;
88
90
  if (!account) {
89
91
  throw new AccountNotFoundError();
@@ -12,6 +12,7 @@ import type {
12
12
  SendUserOperationParameters,
13
13
  UserOperationContext,
14
14
  } from "./types";
15
+ import { clientHeaderTrack } from "../../index.js";
15
16
 
16
17
  export type CheckGasSponsorshipEligibilityResult<
17
18
  TAccount extends SmartContractAccount | undefined =
@@ -47,7 +48,7 @@ export type CheckGasSponsorshipEligibilityResult<
47
48
  * );
48
49
  * ```
49
50
  *
50
- * @param {Client<TTransport, TChain, TAccount>} client the smart account client to use for making RPC calls
51
+ * @param {Client<TTransport, TChain, TAccount>} client_ the smart account client to use for making RPC calls
51
52
  * @param {SendUserOperationParameters} args containing the user operation, account, context, and overrides
52
53
  * @returns {Promise<CheckGasSponsorshipEligibilityResult<TAccount>>} a Promise containing a boolean indicating if the account is elgibile for sponsorship and the sponsored UO
53
54
  */
@@ -61,9 +62,10 @@ export function checkGasSponsorshipEligibility<
61
62
  | UserOperationContext
62
63
  | undefined
63
64
  >(
64
- client: Client<TTransport, TChain, TAccount>,
65
+ client_: Client<TTransport, TChain, TAccount>,
65
66
  args: SendUserOperationParameters<TAccount, TContext>
66
67
  ): Promise<CheckGasSponsorshipEligibilityResult<TAccount>> {
68
+ const client = clientHeaderTrack(client_, "checkGasSponsorshipEligibility");
67
69
  const { account = client.account, overrides, context } = args;
68
70
 
69
71
  if (!account) {
@@ -23,6 +23,7 @@ import type {
23
23
  DropAndReplaceUserOperationParameters,
24
24
  UserOperationContext,
25
25
  } from "./types";
26
+ import { clientHeaderTrack } from "../../index.js";
26
27
 
27
28
  /**
28
29
  * Drops an existing user operation and replaces it with a new one while ensuring the appropriate fees and overrides are applied.
@@ -42,7 +43,7 @@ import type {
42
43
  * });
43
44
  * ```
44
45
  *
45
- * @param {Client<TTransport, TChain, TAccount>} client The client instance with the transport, chain, and account information
46
+ * @param {Client<TTransport, TChain, TAccount>} client_ The client instance with the transport, chain, and account information
46
47
  * @param {DropAndReplaceUserOperationParameters<TAccount, TContext>} args The parameters required for dropping and replacing the user operation including the account, operation to drop, overrides, and context
47
48
  * @returns {Promise<SendUserOperationResult<TEntryPointVersion>>} A promise that resolves to the result of sending the new user operation
48
49
  */
@@ -57,9 +58,10 @@ export async function dropAndReplaceUserOperation<
57
58
  | undefined,
58
59
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
59
60
  >(
60
- client: Client<TTransport, TChain, TAccount>,
61
+ client_: Client<TTransport, TChain, TAccount>,
61
62
  args: DropAndReplaceUserOperationParameters<TAccount, TContext>
62
63
  ): Promise<SendUserOperationResult<TEntryPointVersion>> {
64
+ const client = clientHeaderTrack(client_, "dropAndReplaceUserOperation");
63
65
  const { account = client.account, uoToDrop, overrides, context } = args;
64
66
  if (!account) {
65
67
  throw new AccountNotFoundError();
@@ -13,6 +13,7 @@ import type {
13
13
  SendUserOperationParameters,
14
14
  UserOperationContext,
15
15
  } from "./types.js";
16
+ import { clientHeaderTrack } from "../../index.js";
16
17
 
17
18
  /**
18
19
  * Description SmartAccountClientAction for estimating the gas cost of a user operation
@@ -23,7 +24,7 @@ import type {
23
24
  * @template {SmartContractAccount | undefined} TAccount
24
25
  * @template {UserOperationContext | undefined} TContext
25
26
  * @template {GetEntryPointFromAccount<TAccount>} TEntryPointVersion
26
- * @param {Client<TTransport, TChain, TAccount>} client smart account client
27
+ * @param {Client<TTransport, TChain, TAccount>} client_ smart account client
27
28
  * @param {SendUserOperationParameters<TAccount, TContext>} args send user operation parameters
28
29
  * @returns {Promise<UserOperationEstimateGasResponse<TEntryPointVersion>>}user operation gas estimate response
29
30
  */
@@ -38,9 +39,10 @@ export async function estimateUserOperationGas<
38
39
  | undefined,
39
40
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
40
41
  >(
41
- client: Client<TTransport, TChain, TAccount>,
42
+ client_: Client<TTransport, TChain, TAccount>,
42
43
  args: SendUserOperationParameters<TAccount, TContext>
43
44
  ): Promise<UserOperationEstimateGasResponse<TEntryPointVersion>> {
45
+ const client = clientHeaderTrack(client_, "estimateUserOperationGas");
44
46
  const { account = client.account, overrides } = args;
45
47
  if (!account) {
46
48
  throw new AccountNotFoundError();
@@ -19,6 +19,7 @@ import { buildUserOperationFromTx } from "./buildUserOperationFromTx.js";
19
19
  import { _sendUserOperation } from "./internal/sendUserOperation.js";
20
20
  import type { UserOperationContext } from "./types.js";
21
21
  import { waitForUserOperationTransaction } from "./waitForUserOperationTransacation.js";
22
+ import { clientHeaderTrack } from "../../index.js";
22
23
 
23
24
  /**
24
25
  * Sends a transaction using the provided client, arguments, optional overrides, and context.
@@ -38,7 +39,7 @@ import { waitForUserOperationTransaction } from "./waitForUserOperationTransacat
38
39
  * });
39
40
  * ```
40
41
  *
41
- * @param {Client<Transport, TChain, TAccount>} client The client to send the transaction through
42
+ * @param {Client<Transport, TChain, TAccount>} client_ The client to send the transaction through
42
43
  * @param {SendTransactionParameters<TChain, TAccount, TChainOverride>} args The parameters required to send the transaction
43
44
  * @param {UserOperationOverrides<TEntryPointVersion>} [overrides] Optional overrides for the user operation
44
45
  * @param {UserOperationContext} [context] Optional context for the user operation
@@ -55,11 +56,12 @@ export async function sendTransaction<
55
56
  | undefined,
56
57
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
57
58
  >(
58
- client: Client<Transport, TChain, TAccount>,
59
+ client_: Client<Transport, TChain, TAccount>,
59
60
  args: SendTransactionParameters<TChain, TAccount, TChainOverride>,
60
61
  overrides?: UserOperationOverrides<TEntryPointVersion>,
61
62
  context?: TContext
62
63
  ): Promise<Hex> {
64
+ const client = clientHeaderTrack(client_, "estimateUserOperationGas");
63
65
  const { account = client.account } = args;
64
66
  if (!account || typeof account === "string") {
65
67
  throw new AccountNotFoundError();
@@ -8,6 +8,7 @@ import { buildUserOperationFromTxs } from "./buildUserOperationFromTxs.js";
8
8
  import { _sendUserOperation } from "./internal/sendUserOperation.js";
9
9
  import type { SendTransactionsParameters, UserOperationContext } from "./types";
10
10
  import { waitForUserOperationTransaction } from "./waitForUserOperationTransacation.js";
11
+ import { clientHeaderTrack } from "../../index.js";
11
12
 
12
13
  /**
13
14
  * Sends transactions using the provided client and transaction parameters. This function builds user operations from the transactions, sends them, and waits for the transaction to be mined.
@@ -28,7 +29,7 @@ import { waitForUserOperationTransaction } from "./waitForUserOperationTransacat
28
29
  * });
29
30
  * ```
30
31
  *
31
- * @param {Client<TTransport, TChain, TAccount>} client The client used to send the transactions
32
+ * @param {Client<TTransport, TChain, TAccount>} client_ The client used to send the transactions
32
33
  * @param {SendTransactionsParameters<TAccount, TContext>} args The parameters for sending the transactions, including requests, overrides, account, and context
33
34
  * @returns {Promise<Hex>} A promise that resolves to the transaction hash of the sent transactions
34
35
  */
@@ -40,9 +41,10 @@ export async function sendTransactions<
40
41
  | undefined,
41
42
  TContext extends UserOperationContext | undefined = UserOperationContext
42
43
  >(
43
- client: Client<TTransport, TChain, TAccount>,
44
+ client_: Client<TTransport, TChain, TAccount>,
44
45
  args: SendTransactionsParameters<TAccount, TContext>
45
46
  ): Promise<Hex> {
47
+ const client = clientHeaderTrack(client_, "estimateUserOperationGas");
46
48
  const { requests, overrides, account = client.account, context } = args;
47
49
  if (!account) {
48
50
  throw new AccountNotFoundError();
@@ -13,6 +13,7 @@ import type {
13
13
  SendUserOperationParameters,
14
14
  UserOperationContext,
15
15
  } from "./types.js";
16
+ import { clientHeaderTrack } from "../../index.js";
16
17
 
17
18
  /**
18
19
  * Sends a user operation or batch of user operations using the connected account. Before executing, sendUserOperation will run the user operation through the middleware pipeline.
@@ -31,7 +32,7 @@ import type {
31
32
  * });
32
33
  * ```
33
34
  *
34
- * @param {Client<TTransport, TChain, TAccount>} client the smart account client to use for RPC requests
35
+ * @param {Client<TTransport, TChain, TAccount>} client_ the smart account client to use for RPC requests
35
36
  * @param {SendUserOperationParameters<TAccount, TContext>} args contains the UO or batch to send, context, overrides, and account if not hoisted on the client
36
37
  * @returns {Promise<SendUserOperationResult<TEntryPointVersion>>} a Promise containing the result of the user operation
37
38
  */
@@ -46,9 +47,10 @@ export async function sendUserOperation<
46
47
  | undefined,
47
48
  TEntryPointVersion extends GetEntryPointFromAccount<TAccount> = GetEntryPointFromAccount<TAccount>
48
49
  >(
49
- client: Client<TTransport, TChain, TAccount>,
50
+ client_: Client<TTransport, TChain, TAccount>,
50
51
  args: SendUserOperationParameters<TAccount, TContext>
51
52
  ): Promise<SendUserOperationResult<TEntryPointVersion>> {
53
+ const client = clientHeaderTrack(client_, "sendUserOperation");
52
54
  const { account = client.account, context, overrides } = args;
53
55
 
54
56
  if (!account) {
@@ -6,6 +6,7 @@ import { IncompatibleClientError } from "../../errors/client.js";
6
6
  import { sendUserOperation } from "./sendUserOperation.js";
7
7
  import type { UpgradeAccountParams, UserOperationContext } from "./types.js";
8
8
  import { waitForUserOperationTransaction } from "./waitForUserOperationTransacation.js";
9
+ import { clientHeaderTrack } from "../../index.js";
9
10
 
10
11
  export const upgradeAccount: <
11
12
  TTransport extends Transport = Transport,
@@ -19,7 +20,8 @@ export const upgradeAccount: <
19
20
  >(
20
21
  client: Client<TTransport, TChain, TAccount>,
21
22
  args: UpgradeAccountParams<TAccount, TContext>
22
- ) => Promise<Hash> = async (client, args) => {
23
+ ) => Promise<Hash> = async (client_, args) => {
24
+ const client = clientHeaderTrack(client_, "upgradeAccount");
23
25
  const {
24
26
  account = client.account,
25
27
  upgradeTo,
@@ -4,6 +4,7 @@ import { IncompatibleClientError } from "../../errors/client.js";
4
4
  import { FailedToFindTransactionError } from "../../errors/transaction.js";
5
5
  import { Logger } from "../../logger.js";
6
6
  import type { WaitForUserOperationTxParameters } from "./types.js";
7
+ import { clientHeaderTrack } from "../../index.js";
7
8
 
8
9
  /**
9
10
  * Waits for a user operation transaction to be confirmed by checking the receipt periodically until it is found or a maximum number of retries is reached.
@@ -20,7 +21,7 @@ import type { WaitForUserOperationTxParameters } from "./types.js";
20
21
  * });
21
22
  * ```
22
23
  *
23
- * @param {Client<TTransport, TChain, any>} client The client instance used to interact with the blockchain
24
+ * @param {Client<TTransport, TChain, any>} client_ The client instance used to interact with the blockchain
24
25
  * @param {WaitForUserOperationTxParameters} args The parameters for the transaction to wait for
25
26
  * @param {Hex} args.hash The transaction hash to wait for
26
27
  * @param {WaitForUserOperationTxParameters["retries"]} [args.retries] Optional retry parameters
@@ -35,7 +36,8 @@ export const waitForUserOperationTransaction: <
35
36
  >(
36
37
  client: Client<TTransport, TChain, any>,
37
38
  args: WaitForUserOperationTxParameters
38
- ) => Promise<Hex> = async (client, args) => {
39
+ ) => Promise<Hex> = async (client_, args) => {
40
+ const client = clientHeaderTrack(client_, "waitForUserOperationTransaction");
39
41
  if (!isBaseSmartAccountClient(client)) {
40
42
  throw new IncompatibleClientError(
41
43
  "BaseSmartAccountClient",
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The symbol that is used to add a breadcrumb to the headers. Is an optional
3
+ * function that is used to add a breadcrumb to the headers.
4
+ */
5
+ export const ADD_BREADCRUMB = Symbol("addBreadcrumb");
6
+
7
+ function hasAddBreadcrumb<A extends {}>(
8
+ a: A
9
+ ): a is A & { [ADD_BREADCRUMB]: (breadcrumb: string) => A } {
10
+ return ADD_BREADCRUMB in a;
11
+ }
12
+
13
+ /**
14
+ * Add a crumb to the breadcrumb.
15
+ *
16
+ * @param {X} client Clients are somethings like viem, that we are adding breadcrumbs to, and could be owning the transport. Usually a alchemy client.
17
+ * @param {string} crumb The crumb to add to the breadcrumb
18
+ * @returns {Function} A function that updates the headers
19
+ */
20
+ export function clientHeaderTrack<X extends {}>(client: X, crumb: string): X {
21
+ if (hasAddBreadcrumb(client)) {
22
+ return client[ADD_BREADCRUMB](crumb);
23
+ }
24
+ return client;
25
+ }
@@ -29,6 +29,7 @@ import {
29
29
  } from "./decorators/smartAccountClient.js";
30
30
  import { SmartAccountClientOptsSchema } from "./schema.js";
31
31
  import type { ClientMiddlewareConfig } from "./types.js";
32
+ import { ADD_BREADCRUMB } from "./addBreadcrumb.js";
32
33
 
33
34
  type SmartAccountClientOpts = z.output<typeof SmartAccountClientOptsSchema>;
34
35
 
@@ -54,6 +55,15 @@ export type SmartAccountClientConfig<
54
55
  > & {
55
56
  account?: account;
56
57
  opts?: z.input<typeof SmartAccountClientOptsSchema>;
58
+ /**
59
+ * A function that adds a breadcrumb to the current context
60
+ * Note, most implementations will override the client with the default alchemy transport and this
61
+ * leads to the fact that a transport could be overwritten and not known until later.
62
+ *
63
+ * @param crumb A crumb, or span is telling that we are in a next step part of a multi step action
64
+ * @returns
65
+ */
66
+ addBreadCrumb?: <T>(crumb: string) => T;
57
67
  } & ClientMiddlewareConfig<context>
58
68
  >;
59
69
 
@@ -163,6 +173,7 @@ export function createSmartAccountClient(
163
173
  name = "account provider",
164
174
  transport,
165
175
  type = "SmartAccountClient",
176
+ addBreadCrumb,
166
177
  ...params
167
178
  } = config;
168
179
 
@@ -179,6 +190,7 @@ export function createSmartAccountClient(
179
190
  const rpcTransport = transport(opts);
180
191
 
181
192
  return custom({
193
+ name: "SmartAccountClientTransport",
182
194
  async request({ method, params }) {
183
195
  switch (method) {
184
196
  case "eth_accounts": {
@@ -263,9 +275,17 @@ export function createSmartAccountClient(
263
275
  })(opts);
264
276
  },
265
277
  })
266
- .extend(() => ({
267
- ...SmartAccountClientOptsSchema.parse(config.opts ?? {}),
268
- }))
278
+ .extend(() => {
279
+ const addBreadCrumbs = addBreadCrumb
280
+ ? {
281
+ [ADD_BREADCRUMB]: addBreadCrumb,
282
+ }
283
+ : {};
284
+ return {
285
+ ...SmartAccountClientOptsSchema.parse(config.opts ?? {}),
286
+ ...addBreadCrumbs,
287
+ };
288
+ })
269
289
  .extend(middlewareActions(config))
270
290
  .extend(smartAccountClientActions);
271
291
 
package/src/index.ts CHANGED
@@ -91,6 +91,7 @@ export {
91
91
  InvalidUserOperationError,
92
92
  WaitForUserOperationError,
93
93
  } from "./errors/useroperation.js";
94
+ export * from "./client/addBreadcrumb.js";
94
95
  export { LogLevel, Logger } from "./logger.js";
95
96
  export { middlewareActions } from "./middleware/actions.js";
96
97
  export { default7702UserOpSigner } from "./middleware/defaults/7702signer.js";
@@ -114,6 +115,7 @@ export { WalletClientSigner } from "./signer/wallet-client.js";
114
115
  export { split, type SplitTransportParams } from "./transport/split.js";
115
116
  export type * from "./types.js";
116
117
  export type * from "./utils/index.js";
118
+ export { TraceHeader } from "./utils/traceHeader.js";
117
119
  export {
118
120
  BigNumberishRangeSchema,
119
121
  BigNumberishSchema,
@@ -0,0 +1,133 @@
1
+ function generateRandomHexString(numBytes: number) {
2
+ const bytes = crypto.getRandomValues(new Uint8Array(numBytes));
3
+ const array = Array.from(bytes);
4
+ const hexPairs = array.map((b) => b.toString(16).padStart(2, "0"));
5
+ return hexPairs.join("");
6
+ }
7
+
8
+ const clientTraceId = generateRandomHexString(16);
9
+ /**
10
+ * Some tools that are useful when dealing with the values
11
+ * of the trace header. Follows the W3C trace context standard.
12
+ *
13
+ * @see https://www.w3.org/TR/trace-context/
14
+ */
15
+ export class TraceHeader {
16
+ readonly traceId: string;
17
+ readonly parentId: string;
18
+ readonly traceFlags: string;
19
+ readonly traceState: Record<string, string>;
20
+
21
+ /**
22
+ * Initializes a new instance with the provided trace identifiers and state information.
23
+ *
24
+ * @param {string} traceId The unique identifier for the trace
25
+ * @param {string} parentId The identifier of the parent trace
26
+ * @param {string} traceFlags Flags containing trace-related options
27
+ * @param {TraceHeader["traceState"]} traceState The trace state information for additional trace context
28
+ */
29
+ constructor(
30
+ traceId: string,
31
+ parentId: string,
32
+ traceFlags: string,
33
+ traceState: TraceHeader["traceState"]
34
+ ) {
35
+ this.traceId = traceId;
36
+ this.parentId = parentId;
37
+ this.traceFlags = traceFlags;
38
+ this.traceState = traceState;
39
+ }
40
+
41
+ /**
42
+ * Creating a default trace id that is a random setup for both trace id and parent id
43
+ *
44
+ * @example ```ts
45
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
46
+ * ```
47
+ *
48
+ * @returns {TraceHeader} A default trace header
49
+ */
50
+ static default() {
51
+ return new TraceHeader(
52
+ clientTraceId,
53
+ generateRandomHexString(8),
54
+ "00", //Means no flag have been set, and no sampled state https://www.w3.org/TR/trace-context/#trace-flags
55
+ {}
56
+ );
57
+ }
58
+ /**
59
+ * Should be able to consume a trace header from the headers of an http request
60
+ *
61
+ * @example ```ts
62
+ * const traceHeader = TraceHeader.fromTraceHeader(headers);
63
+ * ```
64
+ *
65
+ * @param {Record<string,string>} headers The headers from the http request
66
+ * @returns {TraceHeader | undefined} The trace header object, or nothing if not found
67
+ */
68
+ static fromTraceHeader(
69
+ headers: Record<string, string>
70
+ ): TraceHeader | undefined {
71
+ if (!headers["traceheader"]) {
72
+ return undefined;
73
+ }
74
+ const [version, traceId, parentId, traceFlags] =
75
+ headers["traceheader"]?.split("-");
76
+
77
+ const traceState =
78
+ headers["tracestate"]?.split(",").reduce((acc, curr) => {
79
+ const [key, value] = curr.split("=");
80
+ acc[key] = value;
81
+ return acc;
82
+ }, {} as Record<string, string>) || {};
83
+ if (version !== "00") {
84
+ console.debug(
85
+ new Error(`Invalid version for traceheader: ${headers["traceheader"]}`)
86
+ );
87
+ return undefined;
88
+ }
89
+ return new TraceHeader(traceId, parentId, traceFlags, traceState);
90
+ }
91
+
92
+ /**
93
+ * Should be able to convert the trace header to the format that is used in the headers of an http request
94
+ *
95
+ * @example ```ts
96
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
97
+ * const headers = traceHeader.toTraceHeader();
98
+ * ```
99
+ *
100
+ * @returns {{stracheader: string, tracestate: string}} The trace header in the format of a record, used in our http client
101
+ */
102
+ toTraceHeader() {
103
+ return {
104
+ traceheader: `00-${this.traceId}-${this.parentId}-${this.traceFlags}`,
105
+ tracestate: Object.entries(this.traceState)
106
+ .map(([key, value]) => `${key}=${value}`)
107
+ .join(","),
108
+ } as const;
109
+ }
110
+
111
+ /**
112
+ * Should be able to create a new trace header with a new event in the trace state,
113
+ * as the key of the eventName as breadcrumbs appending onto previous breadcrumbs with the - infix if exists. And the
114
+ * trace parent gets updated as according to the docs
115
+ *
116
+ * @example ```ts
117
+ * const traceHeader = TraceHeader.fromTraceHeader(headers) || TraceHeader.default();
118
+ * const newTraceHeader = traceHeader.withEvent("newEvent");
119
+ * ```
120
+ *
121
+ * @param {string} eventName The key of the new event
122
+ * @returns {TraceHeader} The new trace header
123
+ */
124
+ withEvent(eventName: string): TraceHeader {
125
+ const breadcrumbs = this.traceState.breadcrumbs
126
+ ? `${this.traceState.breadcrumbs}-${eventName}`
127
+ : eventName;
128
+ return new TraceHeader(this.traceId, this.parentId, this.traceFlags, {
129
+ ...this.traceState,
130
+ breadcrumbs,
131
+ });
132
+ }
133
+ }