@spectratools/tx-shared 0.4.1 → 0.4.3
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/README.md +2 -2
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +120 -6
- package/dist/index.js +585 -9
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ export PRIVY_WALLET_ID="..."
|
|
|
56
56
|
export PRIVY_AUTHORIZATION_KEY="..."
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
> Privy signer
|
|
59
|
+
> Privy signer resolution now performs wallet address lookup and exposes a Privy-backed account helper for `eth_sendTransaction` intents. Additional signing methods (for example `personal_sign` and typed-data) are tracked in [issue #117](https://github.com/spectra-the-bot/spectra-tools/issues/117).
|
|
60
60
|
|
|
61
61
|
## `resolveSigner()` usage
|
|
62
62
|
|
|
@@ -185,7 +185,7 @@ try {
|
|
|
185
185
|
- ensure keystore is valid V3 JSON
|
|
186
186
|
- **`PRIVY_AUTH_FAILED`**
|
|
187
187
|
- verify all `PRIVY_*` variables are set
|
|
188
|
-
-
|
|
188
|
+
- check signer/owner policy constraints for the Privy wallet
|
|
189
189
|
- **`GAS_ESTIMATION_FAILED` / `TX_REVERTED`**
|
|
190
190
|
- validate function args and `value`
|
|
191
191
|
- run with `dryRun: true` first
|
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';
|
|
1
|
+
type TxErrorCode = 'INSUFFICIENT_FUNDS' | 'NONCE_CONFLICT' | 'TX_REVERTED' | 'GAS_ESTIMATION_FAILED' | 'SIGNER_NOT_CONFIGURED' | 'KEYSTORE_DECRYPT_FAILED' | 'PRIVY_AUTH_FAILED' | 'PRIVY_TRANSPORT_FAILED';
|
|
2
2
|
declare class TxError extends Error {
|
|
3
3
|
readonly code: TxErrorCode;
|
|
4
4
|
constructor(code: TxErrorCode, message: string, cause?: unknown);
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export { TxError, TxErrorCode, toTxError } from './errors.js';
|
|
|
4
4
|
export { abstractMainnet, createAbstractClient } from './chain.js';
|
|
5
5
|
export { DryRunResult, ExecuteTxOptions, executeTx } from './execute-tx.js';
|
|
6
6
|
import { z } from 'incur';
|
|
7
|
-
import 'viem';
|
|
7
|
+
import { Account, Address, Hex, Hash } from 'viem';
|
|
8
|
+
import { KeyObject } from 'node:crypto';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Resolve the active signer provider using deterministic precedence:
|
|
@@ -18,6 +19,7 @@ declare const signerFlagSchema: z.ZodObject<{
|
|
|
18
19
|
keystore: z.ZodOptional<z.ZodString>;
|
|
19
20
|
password: z.ZodOptional<z.ZodString>;
|
|
20
21
|
privy: z.ZodDefault<z.ZodBoolean>;
|
|
22
|
+
'privy-api-url': z.ZodOptional<z.ZodString>;
|
|
21
23
|
}, z.core.$strip>;
|
|
22
24
|
/** Shared signer-related environment variables for write-capable commands. */
|
|
23
25
|
declare const signerEnvSchema: z.ZodObject<{
|
|
@@ -26,6 +28,7 @@ declare const signerEnvSchema: z.ZodObject<{
|
|
|
26
28
|
PRIVY_APP_ID: z.ZodOptional<z.ZodString>;
|
|
27
29
|
PRIVY_WALLET_ID: z.ZodOptional<z.ZodString>;
|
|
28
30
|
PRIVY_AUTHORIZATION_KEY: z.ZodOptional<z.ZodString>;
|
|
31
|
+
PRIVY_API_URL: z.ZodOptional<z.ZodString>;
|
|
29
32
|
}, z.core.$strip>;
|
|
30
33
|
type SignerFlags = z.infer<typeof signerFlagSchema>;
|
|
31
34
|
type SignerEnv = z.infer<typeof signerEnvSchema>;
|
|
@@ -57,17 +60,128 @@ interface KeystoreSignerOptions {
|
|
|
57
60
|
*/
|
|
58
61
|
declare function createKeystoreSigner(options: KeystoreSignerOptions): TxSigner;
|
|
59
62
|
|
|
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
|
+
type PrivyNumberish = bigint | number | string;
|
|
115
|
+
interface PrivySendTransactionRequest {
|
|
116
|
+
to?: Address;
|
|
117
|
+
data?: Hex;
|
|
118
|
+
value?: PrivyNumberish;
|
|
119
|
+
nonce?: PrivyNumberish;
|
|
120
|
+
gas?: PrivyNumberish;
|
|
121
|
+
gasPrice?: PrivyNumberish;
|
|
122
|
+
maxFeePerGas?: PrivyNumberish;
|
|
123
|
+
maxPriorityFeePerGas?: PrivyNumberish;
|
|
124
|
+
chainId?: PrivyNumberish;
|
|
125
|
+
type?: number;
|
|
126
|
+
}
|
|
127
|
+
type PrivyAccount = Extract<Account, {
|
|
128
|
+
type: 'json-rpc';
|
|
129
|
+
}> & {
|
|
130
|
+
sendTransaction: (request: PrivySendTransactionRequest) => Promise<Hash>;
|
|
131
|
+
};
|
|
132
|
+
interface CreatePrivyAccountOptions {
|
|
133
|
+
client: PrivyClient;
|
|
134
|
+
chainId?: number;
|
|
135
|
+
}
|
|
136
|
+
declare function createPrivyAccount(options: CreatePrivyAccountOptions): Promise<PrivyAccount>;
|
|
137
|
+
|
|
138
|
+
type PrivyAuthorizationMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
139
|
+
interface PrivyAuthorizationPayloadHeaders {
|
|
140
|
+
'privy-app-id': string;
|
|
141
|
+
'privy-idempotency-key'?: string;
|
|
142
|
+
}
|
|
143
|
+
interface PrivyAuthorizationPayload<TBody extends Record<string, unknown>> {
|
|
144
|
+
version: 1;
|
|
145
|
+
method: PrivyAuthorizationMethod;
|
|
146
|
+
url: string;
|
|
147
|
+
headers: PrivyAuthorizationPayloadHeaders;
|
|
148
|
+
body: TBody;
|
|
149
|
+
}
|
|
150
|
+
interface CreatePrivyAuthorizationPayloadOptions<TBody extends Record<string, unknown>> {
|
|
151
|
+
appId: string;
|
|
152
|
+
method: PrivyAuthorizationMethod;
|
|
153
|
+
url: string;
|
|
154
|
+
body: TBody;
|
|
155
|
+
idempotencyKey?: string;
|
|
156
|
+
}
|
|
157
|
+
declare function normalizePrivyApiUrl(apiUrl?: string): string;
|
|
158
|
+
declare function parsePrivyAuthorizationKey(authorizationKey: string): KeyObject;
|
|
159
|
+
declare function createPrivyAuthorizationPayload<TBody extends Record<string, unknown>>(options: CreatePrivyAuthorizationPayloadOptions<TBody>): PrivyAuthorizationPayload<TBody>;
|
|
160
|
+
declare function serializePrivyAuthorizationPayload(payload: PrivyAuthorizationPayload<Record<string, unknown>>): string;
|
|
161
|
+
declare function generatePrivyAuthorizationSignature(payload: PrivyAuthorizationPayload<Record<string, unknown>>, authorizationKey: string): string;
|
|
162
|
+
|
|
60
163
|
interface PrivySignerOptions {
|
|
61
164
|
privyAppId?: string;
|
|
62
165
|
privyWalletId?: string;
|
|
63
166
|
privyAuthorizationKey?: string;
|
|
167
|
+
privyApiUrl?: string;
|
|
168
|
+
}
|
|
169
|
+
interface PrivySigner extends TxSigner {
|
|
170
|
+
account: PrivyAccount;
|
|
171
|
+
provider: 'privy';
|
|
172
|
+
privy: {
|
|
173
|
+
appId: string;
|
|
174
|
+
walletId: string;
|
|
175
|
+
apiUrl: string;
|
|
176
|
+
client: PrivyClient;
|
|
177
|
+
};
|
|
64
178
|
}
|
|
65
179
|
/**
|
|
66
|
-
* Privy signer
|
|
180
|
+
* Create a Privy signer envelope with reusable transport and request-signing primitives.
|
|
67
181
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
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.
|
|
70
184
|
*/
|
|
71
|
-
declare function createPrivySigner(options: PrivySignerOptions): Promise<
|
|
185
|
+
declare function createPrivySigner(options: PrivySignerOptions): Promise<PrivySigner>;
|
|
72
186
|
|
|
73
|
-
export { type KeystoreSignerOptions, type PrivySignerOptions, type SignerEnv, type SignerFlags, SignerOptions, TxSigner, createKeystoreSigner, createPrivateKeySigner, createPrivySigner, resolveSigner, signerEnvSchema, signerFlagSchema, toSignerOptions };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -57,14 +57,545 @@ function createKeystoreSigner(options) {
|
|
|
57
57
|
return { account, address: account.address, provider: "keystore" };
|
|
58
58
|
}
|
|
59
59
|
|
|
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
|
+
|
|
60
586
|
// src/signers/privy.ts
|
|
61
587
|
var REQUIRED_FIELDS = [
|
|
62
588
|
"privyAppId",
|
|
63
589
|
"privyWalletId",
|
|
64
590
|
"privyAuthorizationKey"
|
|
65
591
|
];
|
|
592
|
+
var APP_ID_REGEX = /^[A-Za-z0-9_-]{8,128}$/;
|
|
593
|
+
var WALLET_ID_REGEX = /^[A-Za-z0-9_-]{8,128}$/;
|
|
66
594
|
async function createPrivySigner(options) {
|
|
67
|
-
const missing = REQUIRED_FIELDS.filter((field) =>
|
|
595
|
+
const missing = REQUIRED_FIELDS.filter((field) => {
|
|
596
|
+
const value = options[field];
|
|
597
|
+
return typeof value !== "string" || value.trim().length === 0;
|
|
598
|
+
});
|
|
68
599
|
if (missing.length > 0) {
|
|
69
600
|
const missingLabels = missing.map((field) => {
|
|
70
601
|
if (field === "privyAppId") {
|
|
@@ -80,10 +611,43 @@ async function createPrivySigner(options) {
|
|
|
80
611
|
`Privy signer requires configuration: missing ${missingLabels}`
|
|
81
612
|
);
|
|
82
613
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
)
|
|
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
|
+
};
|
|
87
651
|
}
|
|
88
652
|
|
|
89
653
|
// src/resolve-signer.ts
|
|
@@ -110,7 +674,8 @@ async function resolveSigner(opts) {
|
|
|
110
674
|
return createPrivySigner({
|
|
111
675
|
...opts.privyAppId !== void 0 ? { privyAppId: opts.privyAppId } : {},
|
|
112
676
|
...opts.privyWalletId !== void 0 ? { privyWalletId: opts.privyWalletId } : {},
|
|
113
|
-
...opts.privyAuthorizationKey !== void 0 ? { privyAuthorizationKey: opts.privyAuthorizationKey } : {}
|
|
677
|
+
...opts.privyAuthorizationKey !== void 0 ? { privyAuthorizationKey: opts.privyAuthorizationKey } : {},
|
|
678
|
+
...opts.privyApiUrl !== void 0 ? { privyApiUrl: opts.privyApiUrl } : {}
|
|
114
679
|
});
|
|
115
680
|
}
|
|
116
681
|
throw new TxError(
|
|
@@ -125,18 +690,21 @@ var signerFlagSchema = z.object({
|
|
|
125
690
|
"private-key": z.string().optional().describe("Raw private key (0x-prefixed 32-byte hex) for signing transactions"),
|
|
126
691
|
keystore: z.string().optional().describe("Path to an encrypted V3 keystore JSON file"),
|
|
127
692
|
password: z.string().optional().describe("Keystore password (non-interactive mode)"),
|
|
128
|
-
privy: z.boolean().default(false).describe("Use Privy server wallet signer mode")
|
|
693
|
+
privy: z.boolean().default(false).describe("Use Privy server wallet signer mode"),
|
|
694
|
+
"privy-api-url": z.string().optional().describe("Override Privy API base URL (defaults to https://api.privy.io)")
|
|
129
695
|
});
|
|
130
696
|
var signerEnvSchema = z.object({
|
|
131
697
|
PRIVATE_KEY: z.string().optional().describe("Raw private key (0x-prefixed 32-byte hex)"),
|
|
132
698
|
KEYSTORE_PASSWORD: z.string().optional().describe("Password for decrypting --keystore"),
|
|
133
699
|
PRIVY_APP_ID: z.string().optional().describe("Privy app id used to authorize wallet intents"),
|
|
134
700
|
PRIVY_WALLET_ID: z.string().optional().describe("Privy wallet id used for transaction intents"),
|
|
135
|
-
PRIVY_AUTHORIZATION_KEY: z.string().optional().describe("Privy authorization private key used to sign intent requests")
|
|
701
|
+
PRIVY_AUTHORIZATION_KEY: z.string().optional().describe("Privy authorization private key used to sign intent requests"),
|
|
702
|
+
PRIVY_API_URL: z.string().optional().describe("Optional Privy API base URL override (default https://api.privy.io)")
|
|
136
703
|
});
|
|
137
704
|
function toSignerOptions(flags, env) {
|
|
138
705
|
const privateKey = flags["private-key"] ?? env.PRIVATE_KEY;
|
|
139
706
|
const keystorePassword = flags.password ?? env.KEYSTORE_PASSWORD;
|
|
707
|
+
const privyApiUrl = flags["privy-api-url"] ?? env.PRIVY_API_URL;
|
|
140
708
|
return {
|
|
141
709
|
...privateKey !== void 0 ? { privateKey } : {},
|
|
142
710
|
...flags.keystore !== void 0 ? { keystorePath: flags.keystore } : {},
|
|
@@ -144,7 +712,8 @@ function toSignerOptions(flags, env) {
|
|
|
144
712
|
...flags.privy ? { privy: true } : {},
|
|
145
713
|
...env.PRIVY_APP_ID !== void 0 ? { privyAppId: env.PRIVY_APP_ID } : {},
|
|
146
714
|
...env.PRIVY_WALLET_ID !== void 0 ? { privyWalletId: env.PRIVY_WALLET_ID } : {},
|
|
147
|
-
...env.PRIVY_AUTHORIZATION_KEY !== void 0 ? { privyAuthorizationKey: env.PRIVY_AUTHORIZATION_KEY } : {}
|
|
715
|
+
...env.PRIVY_AUTHORIZATION_KEY !== void 0 ? { privyAuthorizationKey: env.PRIVY_AUTHORIZATION_KEY } : {},
|
|
716
|
+
...privyApiUrl !== void 0 ? { privyApiUrl } : {}
|
|
148
717
|
};
|
|
149
718
|
}
|
|
150
719
|
export {
|
|
@@ -153,9 +722,16 @@ export {
|
|
|
153
722
|
createAbstractClient,
|
|
154
723
|
createKeystoreSigner,
|
|
155
724
|
createPrivateKeySigner,
|
|
725
|
+
createPrivyAccount,
|
|
726
|
+
createPrivyAuthorizationPayload,
|
|
727
|
+
createPrivyClient,
|
|
156
728
|
createPrivySigner,
|
|
157
729
|
executeTx,
|
|
730
|
+
generatePrivyAuthorizationSignature,
|
|
731
|
+
normalizePrivyApiUrl,
|
|
732
|
+
parsePrivyAuthorizationKey,
|
|
158
733
|
resolveSigner,
|
|
734
|
+
serializePrivyAuthorizationPayload,
|
|
159
735
|
signerEnvSchema,
|
|
160
736
|
signerFlagSchema,
|
|
161
737
|
toSignerOptions,
|
package/dist/types.d.ts
CHANGED