@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/index.js CHANGED
@@ -3,8 +3,22 @@ import {
3
3
  createAbstractClient
4
4
  } from "./chunk-P4ACSL6N.js";
5
5
  import {
6
- executeTx
7
- } from "./chunk-4XI6TBKX.js";
6
+ attachPrivyPolicyContext,
7
+ createPrivyAccount,
8
+ createPrivyAuthorizationPayload,
9
+ createPrivyClient,
10
+ createPrivySigner,
11
+ executeTx,
12
+ fetchPrivyPolicyVisibility,
13
+ generatePrivyAuthorizationSignature,
14
+ getPrivyPolicyContext,
15
+ normalizePrivyApiUrl,
16
+ normalizePrivyPolicy,
17
+ parsePrivyAuthorizationKey,
18
+ preflightPrivyTransactionPolicy,
19
+ serializePrivyAuthorizationPayload,
20
+ toPrivyPolicyViolationError
21
+ } from "./chunk-HFRJBEDT.js";
8
22
  import {
9
23
  TxError,
10
24
  toTxError
@@ -57,599 +71,6 @@ function createKeystoreSigner(options) {
57
71
  return { account, address: account.address, provider: "keystore" };
58
72
  }
59
73
 
60
- // src/signers/privy-account.ts
61
- import { isAddress } from "viem";
62
- var DEFAULT_CHAIN_ID = 2741;
63
- var HASH_REGEX = /^0x[a-fA-F0-9]{64}$/;
64
- async function createPrivyAccount(options) {
65
- const wallet = await options.client.getWallet();
66
- if (typeof wallet.address !== "string" || !isAddress(wallet.address)) {
67
- throw new TxError(
68
- "PRIVY_TRANSPORT_FAILED",
69
- "Privy get wallet request failed: wallet address is missing or invalid"
70
- );
71
- }
72
- const address = wallet.address;
73
- const defaultChainId = options.chainId ?? DEFAULT_CHAIN_ID;
74
- return {
75
- address,
76
- type: "json-rpc",
77
- async sendTransaction(request) {
78
- const chainId = normalizeChainId(request.chainId ?? defaultChainId);
79
- const rpcRequest = createSendTransactionRpcRequest(address, chainId, request);
80
- const response = await options.client.createRpcIntent(rpcRequest);
81
- return parsePrivyTransactionHash(response);
82
- }
83
- };
84
- }
85
- function createSendTransactionRpcRequest(from, chainId, request) {
86
- const transaction = {
87
- from
88
- };
89
- if (request.to !== void 0) {
90
- transaction.to = request.to;
91
- }
92
- if (request.data !== void 0) {
93
- transaction.data = request.data;
94
- }
95
- if (request.value !== void 0) {
96
- transaction.value = normalizeNumberish(request.value, "value");
97
- }
98
- if (request.nonce !== void 0) {
99
- transaction.nonce = normalizeNumberish(request.nonce, "nonce");
100
- }
101
- if (request.gas !== void 0) {
102
- transaction.gas_limit = normalizeNumberish(request.gas, "gas");
103
- }
104
- if (request.gasPrice !== void 0) {
105
- transaction.gas_price = normalizeNumberish(request.gasPrice, "gasPrice");
106
- }
107
- if (request.maxFeePerGas !== void 0) {
108
- transaction.max_fee_per_gas = normalizeNumberish(request.maxFeePerGas, "maxFeePerGas");
109
- }
110
- if (request.maxPriorityFeePerGas !== void 0) {
111
- transaction.max_priority_fee_per_gas = normalizeNumberish(
112
- request.maxPriorityFeePerGas,
113
- "maxPriorityFeePerGas"
114
- );
115
- }
116
- if (request.type !== void 0) {
117
- transaction.type = request.type;
118
- }
119
- transaction.chain_id = chainId;
120
- return {
121
- method: "eth_sendTransaction",
122
- caip2: `eip155:${chainId}`,
123
- params: {
124
- transaction
125
- }
126
- };
127
- }
128
- function parsePrivyTransactionHash(response) {
129
- const intentId = response.intent_id;
130
- if (response.status !== "executed") {
131
- const reason = extractIntentReason(response) ?? "no reason provided";
132
- if (response.status === "failed") {
133
- throw new TxError("TX_REVERTED", `Privy rpc intent ${intentId} failed: ${reason}`);
134
- }
135
- if (response.status === "rejected" || response.status === "dismissed" || response.status === "expired") {
136
- throw new TxError(
137
- "PRIVY_AUTH_FAILED",
138
- `Privy rpc intent ${intentId} ${response.status}: ${reason}`
139
- );
140
- }
141
- throw new TxError(
142
- "PRIVY_TRANSPORT_FAILED",
143
- `Privy rpc intent ${intentId} did not execute (status: ${response.status})`
144
- );
145
- }
146
- const hash = extractIntentHash(response);
147
- if (hash === void 0 || !HASH_REGEX.test(hash)) {
148
- throw new TxError(
149
- "PRIVY_TRANSPORT_FAILED",
150
- `Privy rpc intent ${intentId} executed without a valid transaction hash`
151
- );
152
- }
153
- return hash;
154
- }
155
- function extractIntentHash(response) {
156
- if (!isRecord(response.action_result)) {
157
- return void 0;
158
- }
159
- const responseBody = response.action_result.response_body;
160
- if (!isRecord(responseBody)) {
161
- return void 0;
162
- }
163
- const data = responseBody.data;
164
- if (!isRecord(data)) {
165
- return void 0;
166
- }
167
- return typeof data.hash === "string" ? data.hash : void 0;
168
- }
169
- function extractIntentReason(response) {
170
- if (typeof response.dismissal_reason === "string" && response.dismissal_reason.length > 0) {
171
- return response.dismissal_reason;
172
- }
173
- if (isRecord(response.action_result)) {
174
- const responseBody = response.action_result.response_body;
175
- if (isRecord(responseBody)) {
176
- const error = responseBody.error;
177
- if (typeof error === "string" && error.length > 0) {
178
- return error;
179
- }
180
- if (isRecord(error)) {
181
- const errorMessage = error.message;
182
- if (typeof errorMessage === "string" && errorMessage.length > 0) {
183
- return errorMessage;
184
- }
185
- }
186
- const message = responseBody.message;
187
- if (typeof message === "string" && message.length > 0) {
188
- return message;
189
- }
190
- }
191
- }
192
- return void 0;
193
- }
194
- function normalizeChainId(chainId) {
195
- if (typeof chainId === "number") {
196
- if (!Number.isInteger(chainId) || chainId <= 0) {
197
- throw new TxError(
198
- "PRIVY_TRANSPORT_FAILED",
199
- "Failed to build Privy eth_sendTransaction payload: chainId must be a positive integer"
200
- );
201
- }
202
- return chainId;
203
- }
204
- if (typeof chainId === "bigint") {
205
- if (chainId <= 0n || chainId > BigInt(Number.MAX_SAFE_INTEGER)) {
206
- throw new TxError(
207
- "PRIVY_TRANSPORT_FAILED",
208
- "Failed to build Privy eth_sendTransaction payload: chainId must be a positive safe integer"
209
- );
210
- }
211
- return Number(chainId);
212
- }
213
- const trimmed = chainId.trim();
214
- if (trimmed.length === 0) {
215
- throw new TxError(
216
- "PRIVY_TRANSPORT_FAILED",
217
- "Failed to build Privy eth_sendTransaction payload: chainId is empty"
218
- );
219
- }
220
- if (/^0x[0-9a-fA-F]+$/.test(trimmed)) {
221
- const parsed2 = Number.parseInt(trimmed.slice(2), 16);
222
- if (!Number.isSafeInteger(parsed2) || parsed2 <= 0) {
223
- throw new TxError(
224
- "PRIVY_TRANSPORT_FAILED",
225
- "Failed to build Privy eth_sendTransaction payload: chainId must be a positive safe integer"
226
- );
227
- }
228
- return parsed2;
229
- }
230
- if (!/^[0-9]+$/.test(trimmed)) {
231
- throw new TxError(
232
- "PRIVY_TRANSPORT_FAILED",
233
- "Failed to build Privy eth_sendTransaction payload: chainId must be a positive safe integer"
234
- );
235
- }
236
- const parsed = Number(trimmed);
237
- if (!Number.isSafeInteger(parsed) || parsed <= 0) {
238
- throw new TxError(
239
- "PRIVY_TRANSPORT_FAILED",
240
- "Failed to build Privy eth_sendTransaction payload: chainId must be a positive safe integer"
241
- );
242
- }
243
- return parsed;
244
- }
245
- function normalizeNumberish(value, fieldName) {
246
- if (typeof value === "bigint") {
247
- if (value < 0n) {
248
- throw new TxError(
249
- "PRIVY_TRANSPORT_FAILED",
250
- `Failed to build Privy eth_sendTransaction payload: ${fieldName} cannot be negative`
251
- );
252
- }
253
- return value.toString(10);
254
- }
255
- if (typeof value === "number") {
256
- if (!Number.isFinite(value) || value < 0) {
257
- throw new TxError(
258
- "PRIVY_TRANSPORT_FAILED",
259
- `Failed to build Privy eth_sendTransaction payload: ${fieldName} must be a non-negative number`
260
- );
261
- }
262
- return Number.isInteger(value) ? value : value.toString();
263
- }
264
- const trimmed = value.trim();
265
- if (trimmed.length === 0) {
266
- throw new TxError(
267
- "PRIVY_TRANSPORT_FAILED",
268
- `Failed to build Privy eth_sendTransaction payload: ${fieldName} is empty`
269
- );
270
- }
271
- return trimmed;
272
- }
273
- function isRecord(value) {
274
- return typeof value === "object" && value !== null;
275
- }
276
-
277
- // src/signers/privy-signature.ts
278
- import { createPrivateKey, sign as signWithCrypto } from "crypto";
279
- var PRIVY_AUTHORIZATION_KEY_PREFIX = "wallet-auth:";
280
- var PRIVY_AUTHORIZATION_KEY_REGEX = /^wallet-auth:[A-Za-z0-9+/]+={0,2}$/;
281
- var DEFAULT_PRIVY_API_URL = "https://api.privy.io";
282
- function normalizePrivyApiUrl(apiUrl) {
283
- const value = (apiUrl ?? DEFAULT_PRIVY_API_URL).trim();
284
- if (value.length === 0) {
285
- throw new TxError(
286
- "PRIVY_AUTH_FAILED",
287
- "Invalid PRIVY_API_URL format: expected a non-empty http(s) URL"
288
- );
289
- }
290
- let parsed;
291
- try {
292
- parsed = new URL(value);
293
- } catch (cause) {
294
- throw new TxError(
295
- "PRIVY_AUTH_FAILED",
296
- "Invalid PRIVY_API_URL format: expected a non-empty http(s) URL",
297
- cause
298
- );
299
- }
300
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
301
- throw new TxError(
302
- "PRIVY_AUTH_FAILED",
303
- "Invalid PRIVY_API_URL format: expected a non-empty http(s) URL"
304
- );
305
- }
306
- return parsed.toString().replace(/\/+$/, "");
307
- }
308
- function parsePrivyAuthorizationKey(authorizationKey) {
309
- const normalizedKey = authorizationKey.trim();
310
- if (!PRIVY_AUTHORIZATION_KEY_REGEX.test(normalizedKey)) {
311
- throw new TxError(
312
- "PRIVY_AUTH_FAILED",
313
- "Invalid PRIVY_AUTHORIZATION_KEY format: expected wallet-auth:<base64-pkcs8-p256-private-key>"
314
- );
315
- }
316
- const rawPrivateKey = normalizedKey.slice(PRIVY_AUTHORIZATION_KEY_PREFIX.length);
317
- let derKey;
318
- try {
319
- derKey = Buffer.from(rawPrivateKey, "base64");
320
- } catch (cause) {
321
- throw new TxError(
322
- "PRIVY_AUTH_FAILED",
323
- "Invalid PRIVY_AUTHORIZATION_KEY format: expected wallet-auth:<base64-pkcs8-p256-private-key>",
324
- cause
325
- );
326
- }
327
- let keyObject;
328
- try {
329
- keyObject = createPrivateKey({
330
- key: derKey,
331
- format: "der",
332
- type: "pkcs8"
333
- });
334
- } catch (cause) {
335
- throw new TxError(
336
- "PRIVY_AUTH_FAILED",
337
- "Invalid PRIVY_AUTHORIZATION_KEY format: expected wallet-auth:<base64-pkcs8-p256-private-key>",
338
- cause
339
- );
340
- }
341
- if (keyObject.asymmetricKeyType !== "ec") {
342
- throw new TxError(
343
- "PRIVY_AUTH_FAILED",
344
- "Invalid PRIVY_AUTHORIZATION_KEY format: expected wallet-auth:<base64-pkcs8-p256-private-key>"
345
- );
346
- }
347
- const details = keyObject.asymmetricKeyDetails;
348
- const namedCurve = details !== void 0 && "namedCurve" in details ? details.namedCurve : void 0;
349
- if (namedCurve !== void 0 && namedCurve !== "prime256v1") {
350
- throw new TxError(
351
- "PRIVY_AUTH_FAILED",
352
- "Invalid PRIVY_AUTHORIZATION_KEY format: expected wallet-auth:<base64-pkcs8-p256-private-key>"
353
- );
354
- }
355
- return keyObject;
356
- }
357
- function createPrivyAuthorizationPayload(options) {
358
- const appId = options.appId.trim();
359
- if (appId.length === 0) {
360
- throw new TxError(
361
- "PRIVY_AUTH_FAILED",
362
- "Invalid PRIVY_APP_ID format: expected non-empty string"
363
- );
364
- }
365
- const url = options.url.trim().replace(/\/+$/, "");
366
- if (url.length === 0) {
367
- throw new TxError(
368
- "PRIVY_TRANSPORT_FAILED",
369
- "Failed to build Privy authorization payload: request URL is empty"
370
- );
371
- }
372
- return {
373
- version: 1,
374
- method: options.method,
375
- url,
376
- headers: {
377
- "privy-app-id": appId,
378
- ...options.idempotencyKey !== void 0 ? { "privy-idempotency-key": options.idempotencyKey } : {}
379
- },
380
- body: options.body
381
- };
382
- }
383
- function serializePrivyAuthorizationPayload(payload) {
384
- return canonicalizeJson(payload);
385
- }
386
- function generatePrivyAuthorizationSignature(payload, authorizationKey) {
387
- const privateKey = parsePrivyAuthorizationKey(authorizationKey);
388
- const serializedPayload = serializePrivyAuthorizationPayload(payload);
389
- const signature = signWithCrypto("sha256", Buffer.from(serializedPayload), privateKey);
390
- return signature.toString("base64");
391
- }
392
- function canonicalizeJson(value) {
393
- if (value === null) {
394
- return "null";
395
- }
396
- if (typeof value === "string" || typeof value === "boolean") {
397
- return JSON.stringify(value);
398
- }
399
- if (typeof value === "number") {
400
- if (!Number.isFinite(value)) {
401
- throw new TxError(
402
- "PRIVY_TRANSPORT_FAILED",
403
- "Failed to build Privy authorization payload: JSON payload contains a non-finite number"
404
- );
405
- }
406
- return JSON.stringify(value);
407
- }
408
- if (Array.isArray(value)) {
409
- return `[${value.map((item) => canonicalizeJson(item)).join(",")}]`;
410
- }
411
- if (typeof value === "object") {
412
- const record = value;
413
- const keys = Object.keys(record).sort((left, right) => left.localeCompare(right));
414
- const entries = [];
415
- for (const key of keys) {
416
- const entryValue = record[key];
417
- if (entryValue === void 0) {
418
- continue;
419
- }
420
- entries.push(`${JSON.stringify(key)}:${canonicalizeJson(entryValue)}`);
421
- }
422
- return `{${entries.join(",")}}`;
423
- }
424
- throw new TxError(
425
- "PRIVY_TRANSPORT_FAILED",
426
- "Failed to build Privy authorization payload: JSON payload contains unsupported value type"
427
- );
428
- }
429
-
430
- // src/signers/privy-client.ts
431
- function createPrivyClient(options) {
432
- const appId = options.appId.trim();
433
- const walletId = options.walletId.trim();
434
- if (appId.length === 0) {
435
- throw new TxError(
436
- "PRIVY_AUTH_FAILED",
437
- "Invalid PRIVY_APP_ID format: expected non-empty string"
438
- );
439
- }
440
- if (walletId.length === 0) {
441
- throw new TxError(
442
- "PRIVY_AUTH_FAILED",
443
- "Invalid PRIVY_WALLET_ID format: expected non-empty string"
444
- );
445
- }
446
- const apiUrl = normalizePrivyApiUrl(options.apiUrl);
447
- const fetchImplementation = options.fetchImplementation ?? fetch;
448
- return {
449
- appId,
450
- walletId,
451
- apiUrl,
452
- async createRpcIntent(request, requestOptions) {
453
- const url = `${apiUrl}/v1/intents/wallets/${walletId}/rpc`;
454
- const payload = createPrivyAuthorizationPayload({
455
- appId,
456
- method: "POST",
457
- url,
458
- body: request,
459
- ...requestOptions?.idempotencyKey !== void 0 ? { idempotencyKey: requestOptions.idempotencyKey } : {}
460
- });
461
- const signature = generatePrivyAuthorizationSignature(payload, options.authorizationKey);
462
- return sendPrivyRequest({
463
- fetchImplementation,
464
- method: "POST",
465
- url,
466
- body: request,
467
- operation: "create rpc intent",
468
- headers: {
469
- "privy-app-id": appId,
470
- "privy-authorization-signature": signature,
471
- ...requestOptions?.idempotencyKey !== void 0 ? { "privy-idempotency-key": requestOptions.idempotencyKey } : {}
472
- }
473
- });
474
- },
475
- async getWallet() {
476
- const url = `${apiUrl}/v1/wallets/${walletId}`;
477
- return sendPrivyRequest({
478
- fetchImplementation,
479
- method: "GET",
480
- url,
481
- operation: "get wallet",
482
- headers: {
483
- "privy-app-id": appId
484
- }
485
- });
486
- },
487
- async getPolicy(policyId) {
488
- if (policyId.trim().length === 0) {
489
- throw new TxError(
490
- "PRIVY_TRANSPORT_FAILED",
491
- "Failed to build Privy policy lookup request: policy id is empty"
492
- );
493
- }
494
- const url = `${apiUrl}/v1/policies/${policyId}`;
495
- return sendPrivyRequest({
496
- fetchImplementation,
497
- method: "GET",
498
- url,
499
- operation: "get policy",
500
- headers: {
501
- "privy-app-id": appId
502
- }
503
- });
504
- }
505
- };
506
- }
507
- async function sendPrivyRequest(options) {
508
- let response;
509
- try {
510
- response = await options.fetchImplementation(options.url, {
511
- method: options.method,
512
- headers: {
513
- ...options.headers,
514
- ...options.body !== void 0 ? { "content-type": "application/json" } : {}
515
- },
516
- ...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {}
517
- });
518
- } catch (cause) {
519
- throw new TxError(
520
- "PRIVY_TRANSPORT_FAILED",
521
- `Privy ${options.operation} request failed: network error`,
522
- cause
523
- );
524
- }
525
- const payload = await parseJsonResponse(response, options.operation);
526
- if (!response.ok) {
527
- const message = extractPrivyErrorMessage(payload) ?? `HTTP ${response.status}`;
528
- if (response.status === 401 || response.status === 403) {
529
- throw new TxError(
530
- "PRIVY_AUTH_FAILED",
531
- `Privy authentication failed (${response.status}): ${message}`
532
- );
533
- }
534
- throw new TxError(
535
- "PRIVY_TRANSPORT_FAILED",
536
- `Privy ${options.operation} request failed (${response.status}): ${message}`
537
- );
538
- }
539
- if (!isRecord2(payload)) {
540
- throw new TxError(
541
- "PRIVY_TRANSPORT_FAILED",
542
- `Privy ${options.operation} request failed: invalid JSON response shape`
543
- );
544
- }
545
- return payload;
546
- }
547
- async function parseJsonResponse(response, operation) {
548
- const text = await response.text();
549
- if (text.trim().length === 0) {
550
- return void 0;
551
- }
552
- try {
553
- return JSON.parse(text);
554
- } catch (cause) {
555
- throw new TxError(
556
- "PRIVY_TRANSPORT_FAILED",
557
- `Privy ${operation} request failed: invalid JSON response`,
558
- cause
559
- );
560
- }
561
- }
562
- function isRecord2(value) {
563
- return typeof value === "object" && value !== null;
564
- }
565
- function extractPrivyErrorMessage(payload) {
566
- if (!isRecord2(payload)) {
567
- return void 0;
568
- }
569
- const directMessage = payload.message;
570
- if (typeof directMessage === "string" && directMessage.length > 0) {
571
- return directMessage;
572
- }
573
- const errorValue = payload.error;
574
- if (typeof errorValue === "string" && errorValue.length > 0) {
575
- return errorValue;
576
- }
577
- if (isRecord2(errorValue)) {
578
- const nestedMessage = errorValue.message;
579
- if (typeof nestedMessage === "string" && nestedMessage.length > 0) {
580
- return nestedMessage;
581
- }
582
- }
583
- return void 0;
584
- }
585
-
586
- // src/signers/privy.ts
587
- var REQUIRED_FIELDS = [
588
- "privyAppId",
589
- "privyWalletId",
590
- "privyAuthorizationKey"
591
- ];
592
- var APP_ID_REGEX = /^[A-Za-z0-9_-]{8,128}$/;
593
- var WALLET_ID_REGEX = /^[A-Za-z0-9_-]{8,128}$/;
594
- async function createPrivySigner(options) {
595
- const missing = REQUIRED_FIELDS.filter((field) => {
596
- const value = options[field];
597
- return typeof value !== "string" || value.trim().length === 0;
598
- });
599
- if (missing.length > 0) {
600
- const missingLabels = missing.map((field) => {
601
- if (field === "privyAppId") {
602
- return "PRIVY_APP_ID";
603
- }
604
- if (field === "privyWalletId") {
605
- return "PRIVY_WALLET_ID";
606
- }
607
- return "PRIVY_AUTHORIZATION_KEY";
608
- }).join(", ");
609
- throw new TxError(
610
- "PRIVY_AUTH_FAILED",
611
- `Privy signer requires configuration: missing ${missingLabels}`
612
- );
613
- }
614
- const appId = options.privyAppId?.trim() ?? "";
615
- const walletId = options.privyWalletId?.trim() ?? "";
616
- const authorizationKey = options.privyAuthorizationKey?.trim() ?? "";
617
- if (!APP_ID_REGEX.test(appId)) {
618
- throw new TxError(
619
- "PRIVY_AUTH_FAILED",
620
- "Invalid PRIVY_APP_ID format: expected 8-128 chars using letters, numbers, hyphen, or underscore"
621
- );
622
- }
623
- if (!WALLET_ID_REGEX.test(walletId)) {
624
- throw new TxError(
625
- "PRIVY_AUTH_FAILED",
626
- "Invalid PRIVY_WALLET_ID format: expected 8-128 chars using letters, numbers, hyphen, or underscore"
627
- );
628
- }
629
- parsePrivyAuthorizationKey(authorizationKey);
630
- const apiUrl = normalizePrivyApiUrl(options.privyApiUrl);
631
- const client = createPrivyClient({
632
- appId,
633
- walletId,
634
- authorizationKey,
635
- apiUrl
636
- });
637
- const account = await createPrivyAccount({
638
- client
639
- });
640
- return {
641
- provider: "privy",
642
- account,
643
- address: account.address,
644
- privy: {
645
- appId,
646
- walletId,
647
- apiUrl,
648
- client
649
- }
650
- };
651
- }
652
-
653
74
  // src/resolve-signer.ts
654
75
  function hasPrivyConfig(opts) {
655
76
  return opts.privyAppId !== void 0 || opts.privyWalletId !== void 0 || opts.privyAuthorizationKey !== void 0;
@@ -671,12 +92,13 @@ async function resolveSigner(opts) {
671
92
  });
672
93
  }
673
94
  if (opts.privy === true || hasPrivyConfig(opts)) {
674
- return createPrivySigner({
95
+ const privySigner = await createPrivySigner({
675
96
  ...opts.privyAppId !== void 0 ? { privyAppId: opts.privyAppId } : {},
676
97
  ...opts.privyWalletId !== void 0 ? { privyWalletId: opts.privyWalletId } : {},
677
98
  ...opts.privyAuthorizationKey !== void 0 ? { privyAuthorizationKey: opts.privyAuthorizationKey } : {},
678
99
  ...opts.privyApiUrl !== void 0 ? { privyApiUrl: opts.privyApiUrl } : {}
679
100
  });
101
+ return privySigner;
680
102
  }
681
103
  throw new TxError(
682
104
  "SIGNER_NOT_CONFIGURED",
@@ -719,6 +141,7 @@ function toSignerOptions(flags, env) {
719
141
  export {
720
142
  TxError,
721
143
  abstractMainnet,
144
+ attachPrivyPolicyContext,
722
145
  createAbstractClient,
723
146
  createKeystoreSigner,
724
147
  createPrivateKeySigner,
@@ -727,13 +150,18 @@ export {
727
150
  createPrivyClient,
728
151
  createPrivySigner,
729
152
  executeTx,
153
+ fetchPrivyPolicyVisibility,
730
154
  generatePrivyAuthorizationSignature,
155
+ getPrivyPolicyContext,
731
156
  normalizePrivyApiUrl,
157
+ normalizePrivyPolicy,
732
158
  parsePrivyAuthorizationKey,
159
+ preflightPrivyTransactionPolicy,
733
160
  resolveSigner,
734
161
  serializePrivyAuthorizationPayload,
735
162
  signerEnvSchema,
736
163
  signerFlagSchema,
164
+ toPrivyPolicyViolationError,
737
165
  toSignerOptions,
738
166
  toTxError
739
167
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectratools/tx-shared",
3
- "version": "0.4.3",
3
+ "version": "0.5.2",
4
4
  "description": "Shared transaction primitives, signer types, and chain config for spectra tools",
5
5
  "type": "module",
6
6
  "license": "MIT",