@spectratools/tx-shared 0.4.3 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- type TxErrorCode = 'INSUFFICIENT_FUNDS' | 'NONCE_CONFLICT' | 'TX_REVERTED' | 'GAS_ESTIMATION_FAILED' | 'SIGNER_NOT_CONFIGURED' | 'KEYSTORE_DECRYPT_FAILED' | 'PRIVY_AUTH_FAILED' | 'PRIVY_TRANSPORT_FAILED';
1
+ type TxErrorCode = 'INSUFFICIENT_FUNDS' | 'NONCE_CONFLICT' | 'TX_REVERTED' | 'GAS_ESTIMATION_FAILED' | 'SIGNER_NOT_CONFIGURED' | 'KEYSTORE_DECRYPT_FAILED' | 'PRIVY_AUTH_FAILED' | 'PRIVY_TRANSPORT_FAILED' | 'PRIVY_POLICY_BLOCKED';
2
2
  declare class TxError extends Error {
3
3
  readonly code: TxErrorCode;
4
4
  constructor(code: TxErrorCode, message: string, cause?: unknown);
@@ -0,0 +1,160 @@
1
+ import { Address, PublicClient, WalletClient, Account, Abi, Chain } from 'viem';
2
+ import { TxError } from './errors.js';
3
+ import { TxResult } from './types.js';
4
+
5
+ interface PrivyRpcIntentRequest {
6
+ method: string;
7
+ params: Record<string, unknown>;
8
+ [key: string]: unknown;
9
+ }
10
+ type PrivyIntentStatus = 'pending' | 'executed' | 'failed' | 'expired' | 'rejected' | 'dismissed' | string;
11
+ interface PrivyRpcIntentResponse {
12
+ intent_id: string;
13
+ status: PrivyIntentStatus;
14
+ resource_id?: string;
15
+ request_details?: Record<string, unknown>;
16
+ dismissal_reason?: string;
17
+ action_result?: {
18
+ response_body?: Record<string, unknown>;
19
+ [key: string]: unknown;
20
+ };
21
+ [key: string]: unknown;
22
+ }
23
+ interface PrivyWalletResponse {
24
+ id: string;
25
+ address: string;
26
+ owner_id: string | null;
27
+ policy_ids: string[];
28
+ [key: string]: unknown;
29
+ }
30
+ interface PrivyPolicyResponse {
31
+ id: string;
32
+ owner_id: string | null;
33
+ rules: unknown[];
34
+ [key: string]: unknown;
35
+ }
36
+ interface PrivyNormalizedPolicy {
37
+ id: string;
38
+ ownerId: string | null;
39
+ ruleCount: number;
40
+ allowlistedContracts: Address[];
41
+ maxValueWei?: bigint;
42
+ }
43
+ interface PrivyPolicyVisibility {
44
+ walletId: string;
45
+ policyIds: string[];
46
+ policies: PrivyNormalizedPolicy[];
47
+ contractAllowlist: Address[];
48
+ maxValueWei?: bigint;
49
+ }
50
+ type PrivyPolicyViolationType = 'contract-allowlist' | 'native-value-cap';
51
+ interface PrivyPolicyViolation {
52
+ type: PrivyPolicyViolationType;
53
+ message: string;
54
+ policyIds: string[];
55
+ actual: string;
56
+ expected: string;
57
+ }
58
+ interface PrivyPolicyPreflightRequest {
59
+ to?: Address;
60
+ value?: bigint;
61
+ }
62
+ interface PrivyPolicyPreflightResult {
63
+ status: 'allowed' | 'blocked';
64
+ visibility: PrivyPolicyVisibility;
65
+ violations: PrivyPolicyViolation[];
66
+ }
67
+ interface CreatePrivyClientOptions {
68
+ appId: string;
69
+ walletId: string;
70
+ authorizationKey: string;
71
+ apiUrl?: string;
72
+ fetchImplementation?: typeof fetch;
73
+ }
74
+ interface PrivyRequestOptions {
75
+ idempotencyKey?: string;
76
+ }
77
+ interface PrivyClient {
78
+ readonly appId: string;
79
+ readonly walletId: string;
80
+ readonly apiUrl: string;
81
+ createRpcIntent(request: PrivyRpcIntentRequest, options?: PrivyRequestOptions): Promise<PrivyRpcIntentResponse>;
82
+ getWallet(): Promise<PrivyWalletResponse>;
83
+ getPolicy(policyId: string): Promise<PrivyPolicyResponse>;
84
+ }
85
+ declare function createPrivyClient(options: CreatePrivyClientOptions): PrivyClient;
86
+ /** Normalize a raw Privy policy object into tx-shared's policy model. */
87
+ declare function normalizePrivyPolicy(policy: PrivyPolicyResponse): PrivyNormalizedPolicy;
88
+ /** Fetch wallet policies and return normalized visibility data for callers. */
89
+ declare function fetchPrivyPolicyVisibility(client: PrivyClient): Promise<PrivyPolicyVisibility>;
90
+ /**
91
+ * Evaluate immediately-deterministic Privy constraints (contract allowlists + native value caps).
92
+ */
93
+ declare function preflightPrivyTransactionPolicy(client: PrivyClient, request: PrivyPolicyPreflightRequest): Promise<PrivyPolicyPreflightResult>;
94
+ /** Convert blocked preflight output into a deterministic structured TxError. */
95
+ declare function toPrivyPolicyViolationError(result: PrivyPolicyPreflightResult): TxError;
96
+
97
+ /** Options for the {@link executeTx} lifecycle. */
98
+ interface ExecuteTxOptions {
99
+ /** Viem public client used for gas estimation, simulation, and receipt retrieval. */
100
+ publicClient: PublicClient;
101
+ /** Viem wallet client used to submit the transaction. */
102
+ walletClient: WalletClient;
103
+ /** Signer account. */
104
+ account: Account;
105
+ /** Target contract address. */
106
+ address: Address;
107
+ /** Contract ABI (must include the target function). */
108
+ abi: Abi;
109
+ /** Name of the contract function to call. */
110
+ functionName: string;
111
+ /** Optional chain to use for the transaction. */
112
+ chain?: Chain;
113
+ /** Arguments passed to the contract function. */
114
+ args?: unknown[];
115
+ /** Native value (in wei) to send with the transaction. */
116
+ value?: bigint;
117
+ /** Gas limit override. When provided the estimate is still performed but this value is used for submission. */
118
+ gasLimit?: bigint;
119
+ /** Max fee per gas override (EIP-1559). */
120
+ maxFeePerGas?: bigint;
121
+ /** Nonce override. */
122
+ nonce?: number;
123
+ /**
124
+ * When `true` the transaction is simulated but **not** broadcast.
125
+ * Returns a {@link DryRunResult} instead of a {@link TxResult}.
126
+ */
127
+ dryRun?: boolean;
128
+ }
129
+ /** Result returned when `dryRun` is `true`. */
130
+ interface DryRunResult {
131
+ /** Discriminator — always `'dry-run'` for dry-run results. */
132
+ status: 'dry-run';
133
+ /** Estimated gas units for the call. */
134
+ estimatedGas: bigint;
135
+ /** Simulated return value from `simulateContract`. */
136
+ simulationResult: unknown;
137
+ /** Optional Privy policy visibility for Privy-backed accounts. */
138
+ privyPolicy?: PrivyPolicyPreflightResult;
139
+ }
140
+ /**
141
+ * Execute a full transaction lifecycle:
142
+ *
143
+ * 1. **Estimate** gas via `publicClient.estimateContractGas`.
144
+ * 2. **Simulate** contract call via `publicClient.simulateContract`.
145
+ * 3. **Preflight** Privy policies when a Privy-backed account is used.
146
+ * - If `dryRun` is `true`, return a {@link DryRunResult} without broadcasting.
147
+ * 4. **Submit** the transaction via `walletClient.writeContract`.
148
+ * 5. **Wait** for the receipt via `publicClient.waitForTransactionReceipt`.
149
+ * 6. **Normalize** the receipt into a {@link TxResult}.
150
+ *
151
+ * Errors thrown by viem are mapped to structured {@link TxError} codes:
152
+ * - `INSUFFICIENT_FUNDS` — sender lacks balance for value + gas.
153
+ * - `NONCE_CONFLICT` — nonce already used or too low.
154
+ * - `GAS_ESTIMATION_FAILED` — gas estimation or simulation reverted.
155
+ * - `TX_REVERTED` — on-chain revert (includes reason when available).
156
+ * - `PRIVY_POLICY_BLOCKED` — Privy policy preflight determined the tx is not allowed.
157
+ */
158
+ declare function executeTx(options: ExecuteTxOptions): Promise<TxResult | DryRunResult>;
159
+
160
+ export { type DryRunResult as D, type ExecuteTxOptions as E, type PrivyClient as P, type PrivyNormalizedPolicy as a, type PrivyPolicyPreflightRequest as b, type PrivyPolicyPreflightResult as c, type PrivyPolicyViolation as d, type PrivyPolicyVisibility as e, createPrivyClient as f, executeTx as g, fetchPrivyPolicyVisibility as h, normalizePrivyPolicy as n, preflightPrivyTransactionPolicy as p, toPrivyPolicyViolationError as t };
@@ -1,63 +1,4 @@
1
- import { PublicClient, WalletClient, Account, Address, Abi, Chain } from 'viem';
2
- import { TxResult } from './types.js';
3
-
4
- /** Options for the {@link executeTx} lifecycle. */
5
- interface ExecuteTxOptions {
6
- /** Viem public client used for gas estimation, simulation, and receipt retrieval. */
7
- publicClient: PublicClient;
8
- /** Viem wallet client used to submit the transaction. */
9
- walletClient: WalletClient;
10
- /** Signer account. */
11
- account: Account;
12
- /** Target contract address. */
13
- address: Address;
14
- /** Contract ABI (must include the target function). */
15
- abi: Abi;
16
- /** Name of the contract function to call. */
17
- functionName: string;
18
- /** Optional chain to use for the transaction. */
19
- chain?: Chain;
20
- /** Arguments passed to the contract function. */
21
- args?: unknown[];
22
- /** Native value (in wei) to send with the transaction. */
23
- value?: bigint;
24
- /** Gas limit override. When provided the estimate is still performed but this value is used for submission. */
25
- gasLimit?: bigint;
26
- /** Max fee per gas override (EIP-1559). */
27
- maxFeePerGas?: bigint;
28
- /** Nonce override. */
29
- nonce?: number;
30
- /**
31
- * When `true` the transaction is simulated but **not** broadcast.
32
- * Returns a {@link DryRunResult} instead of a {@link TxResult}.
33
- */
34
- dryRun?: boolean;
35
- }
36
- /** Result returned when `dryRun` is `true`. */
37
- interface DryRunResult {
38
- /** Discriminator — always `'dry-run'` for dry-run results. */
39
- status: 'dry-run';
40
- /** Estimated gas units for the call. */
41
- estimatedGas: bigint;
42
- /** Simulated return value from `simulateContract`. */
43
- simulationResult: unknown;
44
- }
45
- /**
46
- * Execute a full transaction lifecycle:
47
- *
48
- * 1. **Estimate** gas via `publicClient.estimateContractGas`.
49
- * 2. **Simulate** contract call via `publicClient.simulateContract`.
50
- * - If `dryRun` is `true`, return a {@link DryRunResult} without broadcasting.
51
- * 3. **Submit** the transaction via `walletClient.writeContract`.
52
- * 4. **Wait** for the receipt via `publicClient.waitForTransactionReceipt`.
53
- * 5. **Normalize** the receipt into a {@link TxResult}.
54
- *
55
- * Errors thrown by viem are mapped to structured {@link TxError} codes:
56
- * - `INSUFFICIENT_FUNDS` — sender lacks balance for value + gas.
57
- * - `NONCE_CONFLICT` — nonce already used or too low.
58
- * - `GAS_ESTIMATION_FAILED` — gas estimation or simulation reverted.
59
- * - `TX_REVERTED` — on-chain revert (includes reason when available).
60
- */
61
- declare function executeTx(options: ExecuteTxOptions): Promise<TxResult | DryRunResult>;
62
-
63
- export { type DryRunResult, type ExecuteTxOptions, executeTx };
1
+ import 'viem';
2
+ export { D as DryRunResult, E as ExecuteTxOptions, g as executeTx } from './execute-tx-DO8p_9dP.js';
3
+ import './types.js';
4
+ import './errors.js';
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  executeTx
3
- } from "./chunk-4XI6TBKX.js";
3
+ } from "./chunk-HFRJBEDT.js";
4
4
  import "./chunk-6T4D5UCR.js";
5
5
  export {
6
6
  executeTx
package/dist/index.d.ts CHANGED
@@ -2,9 +2,10 @@ import { SignerOptions, TxSigner } from './types.js';
2
2
  export { SignerProvider, TxResult } from './types.js';
3
3
  export { TxError, TxErrorCode, toTxError } from './errors.js';
4
4
  export { abstractMainnet, createAbstractClient } from './chain.js';
5
- export { DryRunResult, ExecuteTxOptions, executeTx } from './execute-tx.js';
5
+ import { P as PrivyClient } from './execute-tx-DO8p_9dP.js';
6
+ export { D as DryRunResult, E as ExecuteTxOptions, a as PrivyNormalizedPolicy, b as PrivyPolicyPreflightRequest, c as PrivyPolicyPreflightResult, d as PrivyPolicyViolation, e as PrivyPolicyVisibility, f as createPrivyClient, g as executeTx, h as fetchPrivyPolicyVisibility, n as normalizePrivyPolicy, p as preflightPrivyTransactionPolicy, t as toPrivyPolicyViolationError } from './execute-tx-DO8p_9dP.js';
6
7
  import { z } from 'incur';
7
- import { Account, Address, Hex, Hash } from 'viem';
8
+ import { Address, Hex, Hash, SignableMessage, TypedData, TypedDataDefinition, SerializeTransactionFn, TransactionSerializable } from 'viem';
8
9
  import { KeyObject } from 'node:crypto';
9
10
 
10
11
  /**
@@ -60,59 +61,9 @@ interface KeystoreSignerOptions {
60
61
  */
61
62
  declare function createKeystoreSigner(options: KeystoreSignerOptions): TxSigner;
62
63
 
63
- interface PrivyRpcIntentRequest {
64
- method: string;
65
- params: Record<string, unknown>;
66
- [key: string]: unknown;
67
- }
68
- type PrivyIntentStatus = 'pending' | 'executed' | 'failed' | 'expired' | 'rejected' | 'dismissed' | string;
69
- interface PrivyRpcIntentResponse {
70
- intent_id: string;
71
- status: PrivyIntentStatus;
72
- resource_id?: string;
73
- request_details?: Record<string, unknown>;
74
- dismissal_reason?: string;
75
- action_result?: {
76
- response_body?: Record<string, unknown>;
77
- [key: string]: unknown;
78
- };
79
- [key: string]: unknown;
80
- }
81
- interface PrivyWalletResponse {
82
- id: string;
83
- address: string;
84
- owner_id: string | null;
85
- policy_ids: string[];
86
- [key: string]: unknown;
87
- }
88
- interface PrivyPolicyResponse {
89
- id: string;
90
- owner_id: string | null;
91
- rules: unknown[];
92
- [key: string]: unknown;
93
- }
94
- interface CreatePrivyClientOptions {
95
- appId: string;
96
- walletId: string;
97
- authorizationKey: string;
98
- apiUrl?: string;
99
- fetchImplementation?: typeof fetch;
100
- }
101
- interface PrivyRequestOptions {
102
- idempotencyKey?: string;
103
- }
104
- interface PrivyClient {
105
- readonly appId: string;
106
- readonly walletId: string;
107
- readonly apiUrl: string;
108
- createRpcIntent(request: PrivyRpcIntentRequest, options?: PrivyRequestOptions): Promise<PrivyRpcIntentResponse>;
109
- getWallet(): Promise<PrivyWalletResponse>;
110
- getPolicy(policyId: string): Promise<PrivyPolicyResponse>;
111
- }
112
- declare function createPrivyClient(options: CreatePrivyClientOptions): PrivyClient;
113
-
114
64
  type PrivyNumberish = bigint | number | string;
115
65
  interface PrivySendTransactionRequest {
66
+ from?: Address;
116
67
  to?: Address;
117
68
  data?: Hex;
118
69
  value?: PrivyNumberish;
@@ -124,11 +75,20 @@ interface PrivySendTransactionRequest {
124
75
  chainId?: PrivyNumberish;
125
76
  type?: number;
126
77
  }
127
- type PrivyAccount = Extract<Account, {
78
+ type PrivySignTransactionRequest = PrivySendTransactionRequest;
79
+ type PrivySignTypedDataRequest<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData> = TypedDataDefinition<typedData, primaryType>;
80
+ interface PrivyAccount {
81
+ address: Address;
128
82
  type: 'json-rpc';
129
- }> & {
130
83
  sendTransaction: (request: PrivySendTransactionRequest) => Promise<Hash>;
131
- };
84
+ signMessage: ({ message }: {
85
+ message: SignableMessage;
86
+ }) => Promise<Hex>;
87
+ signTypedData: <const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData>(parameters: PrivySignTypedDataRequest<typedData, primaryType>) => Promise<Hex>;
88
+ signTransaction: <serializer extends SerializeTransactionFn<TransactionSerializable> = SerializeTransactionFn<TransactionSerializable>, transaction extends Parameters<serializer>[0] = Parameters<serializer>[0]>(transaction: transaction, options?: {
89
+ serializer?: serializer;
90
+ }) => Promise<Hex>;
91
+ }
132
92
  interface CreatePrivyAccountOptions {
133
93
  client: PrivyClient;
134
94
  chainId?: number;
@@ -166,8 +126,15 @@ interface PrivySignerOptions {
166
126
  privyAuthorizationKey?: string;
167
127
  privyApiUrl?: string;
168
128
  }
169
- interface PrivySigner extends TxSigner {
129
+ interface PrivyPolicyContext {
130
+ appId: string;
131
+ walletId: string;
132
+ apiUrl: string;
133
+ client: PrivyClient;
134
+ }
135
+ interface PrivySigner {
170
136
  account: PrivyAccount;
137
+ address: Address;
171
138
  provider: 'privy';
172
139
  privy: {
173
140
  appId: string;
@@ -176,12 +143,21 @@ interface PrivySigner extends TxSigner {
176
143
  client: PrivyClient;
177
144
  };
178
145
  }
146
+ /**
147
+ * Attach Privy policy context to any account-like object so executeTx can run policy preflight checks.
148
+ */
149
+ declare function attachPrivyPolicyContext<TAccount extends object>(account: TAccount, context: PrivyPolicyContext): TAccount;
150
+ /** Read Privy policy context from an account when present. */
151
+ declare function getPrivyPolicyContext(account: unknown): PrivyPolicyContext | undefined;
179
152
  /**
180
153
  * Create a Privy signer envelope with reusable transport and request-signing primitives.
181
154
  *
182
- * The resolved account is backed by Privy RPC intents and includes a `sendTransaction`
183
- * helper that submits `eth_sendTransaction` intents and returns the resulting tx hash.
155
+ * The resolved account is backed by Privy RPC intents and supports:
156
+ * - `sendTransaction` via `eth_sendTransaction`
157
+ * - `signMessage` via `personal_sign`
158
+ * - `signTypedData` via `eth_signTypedData_v4`
159
+ * - `signTransaction` via `eth_signTransaction` (returns serialized tx hex; caller is responsible for broadcast)
184
160
  */
185
161
  declare function createPrivySigner(options: PrivySignerOptions): Promise<PrivySigner>;
186
162
 
187
- export { type KeystoreSignerOptions, type PrivyAccount, type PrivyAuthorizationPayload, type PrivyAuthorizationPayloadHeaders, type PrivyClient, type PrivySendTransactionRequest, type PrivySigner, type PrivySignerOptions, type SignerEnv, type SignerFlags, SignerOptions, TxSigner, createKeystoreSigner, createPrivateKeySigner, createPrivyAccount, createPrivyAuthorizationPayload, createPrivyClient, createPrivySigner, generatePrivyAuthorizationSignature, normalizePrivyApiUrl, parsePrivyAuthorizationKey, resolveSigner, serializePrivyAuthorizationPayload, signerEnvSchema, signerFlagSchema, toSignerOptions };
163
+ export { type KeystoreSignerOptions, type PrivyAccount, type PrivyAuthorizationPayload, type PrivyAuthorizationPayloadHeaders, PrivyClient, type PrivyPolicyContext, type PrivySendTransactionRequest, type PrivySignTransactionRequest, type PrivySignTypedDataRequest, type PrivySigner, type PrivySignerOptions, type SignerEnv, type SignerFlags, SignerOptions, TxSigner, attachPrivyPolicyContext, createKeystoreSigner, createPrivateKeySigner, createPrivyAccount, createPrivyAuthorizationPayload, createPrivySigner, generatePrivyAuthorizationSignature, getPrivyPolicyContext, normalizePrivyApiUrl, parsePrivyAuthorizationKey, resolveSigner, serializePrivyAuthorizationPayload, signerEnvSchema, signerFlagSchema, toSignerOptions };