@opensea/wallet-adapters 0.2.1 → 0.3.1
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 +38 -0
- package/dist/ethers.d.ts +1 -1
- package/dist/{index-DFTwYt_e.d.ts → index-jjHnOuwA.d.ts} +65 -2
- package/dist/index.d.ts +181 -13
- package/dist/index.js +173 -60
- package/dist/index.js.map +1 -1
- package/dist/viem.d.ts +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Provider-agnostic wallet adapters for signing and sending transactions across managed and local backends.
|
|
4
4
|
|
|
5
|
+
## Why wallet-adapters?
|
|
6
|
+
|
|
7
|
+
`@opensea/wallet-adapters` is the shared wallet layer used across the OpenSea developer toolchain. Every package that needs to sign transactions depends on the same `WalletAdapter` interface:
|
|
8
|
+
|
|
9
|
+
- [`@opensea/sdk`](https://github.com/ProjectOpenSea/opensea-js) — TypeScript SDK for buying, selling, and managing NFTs
|
|
10
|
+
- [`@opensea/cli`](https://github.com/ProjectOpenSea/opensea-cli) — command-line interface for the OpenSea API
|
|
11
|
+
- [`@opensea/tool-sdk`](https://github.com/ProjectOpenSea/tool-sdk) — SDK for building ERC-8257 AI agent tools
|
|
12
|
+
- [`opensea-skill`](https://github.com/ProjectOpenSea/opensea-skill) — modular AI agent skills for Claude, Devin, and other assistants
|
|
13
|
+
|
|
14
|
+
By implementing the `WalletAdapter` interface once, a new wallet provider automatically works everywhere — the CLI, the SDK, AI agent tool execution, and any future package that depends on this library.
|
|
15
|
+
|
|
5
16
|
## Features
|
|
6
17
|
|
|
7
18
|
- **Provider-agnostic interface** — unified `WalletAdapter` abstraction with capabilities declaration
|
|
@@ -151,6 +162,33 @@ wallet.onResponse = (method, result, durationMs) => {
|
|
|
151
162
|
}
|
|
152
163
|
```
|
|
153
164
|
|
|
165
|
+
## Adding a New Provider
|
|
166
|
+
|
|
167
|
+
To add a wallet provider, implement the `WalletAdapter` interface:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import type { WalletAdapter, WalletCapabilities } from "@opensea/wallet-adapters"
|
|
171
|
+
|
|
172
|
+
export class MyProviderAdapter implements WalletAdapter {
|
|
173
|
+
readonly name = "my-provider"
|
|
174
|
+
readonly capabilities: WalletCapabilities = {
|
|
175
|
+
signMessage: true,
|
|
176
|
+
signTypedData: true,
|
|
177
|
+
managedGas: true,
|
|
178
|
+
managedNonce: true,
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async getAddress(): Promise<string> { /* ... */ }
|
|
182
|
+
async sendTransaction(tx) { /* ... */ }
|
|
183
|
+
async signMessage(request) { /* ... */ }
|
|
184
|
+
async signTypedData(request) { /* ... */ }
|
|
185
|
+
|
|
186
|
+
static fromEnv(): MyProviderAdapter { /* ... */ }
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Then register it in the `createWalletFromEnv()` factory in `src/factory.ts` so the CLI and tool-sdk auto-detect it from environment variables.
|
|
191
|
+
|
|
154
192
|
## License
|
|
155
193
|
|
|
156
194
|
MIT
|
package/dist/ethers.d.ts
CHANGED
|
@@ -5,6 +5,61 @@
|
|
|
5
5
|
* Designed to be provider-agnostic and extensible for future signing
|
|
6
6
|
* capabilities (EIP-712, EIP-191, batch transactions, etc.).
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Provider-shaped wallet metadata used by the `opensea wallet info` CLI
|
|
10
|
+
* command and by callers auditing the security posture of an agent wallet.
|
|
11
|
+
*
|
|
12
|
+
* Each variant surfaces only what the provider's API actually exposes for
|
|
13
|
+
* the calling credentials. Fields whose absence indicates a hardening gap
|
|
14
|
+
* (no on-chain policy enforcement, no off-machine credential gating
|
|
15
|
+
* administrative changes, etc.) are intentionally surfaced as falsy values
|
|
16
|
+
* rather than hidden, so callers can warn the user.
|
|
17
|
+
*/
|
|
18
|
+
type WalletInfo = {
|
|
19
|
+
provider: "privy";
|
|
20
|
+
address: string;
|
|
21
|
+
chainType: string;
|
|
22
|
+
policyIds: string[];
|
|
23
|
+
ownerKeyId: string | null;
|
|
24
|
+
additionalSignerCount: number;
|
|
25
|
+
/**
|
|
26
|
+
* True iff the wallet has an `owner_id` set, in which case all
|
|
27
|
+
* `/v1/wallets/{id}/rpc` requests must carry an authorization
|
|
28
|
+
* signature from the owner's key quorum. False means the env app
|
|
29
|
+
* secret can sign and rewrite policy unilaterally.
|
|
30
|
+
*/
|
|
31
|
+
ownerEnforcesAuthKey: boolean;
|
|
32
|
+
} | {
|
|
33
|
+
provider: "turnkey";
|
|
34
|
+
address: string;
|
|
35
|
+
organizationId: string;
|
|
36
|
+
userId: string;
|
|
37
|
+
username: string;
|
|
38
|
+
/**
|
|
39
|
+
* True iff the calling API user is in the organization's root
|
|
40
|
+
* quorum. Root users bypass Turnkey's policy engine entirely, so a
|
|
41
|
+
* leaked root API key has the same blast radius as a raw private
|
|
42
|
+
* key — sign, mutate, export, all unconstrained.
|
|
43
|
+
*/
|
|
44
|
+
isRootUser: boolean;
|
|
45
|
+
} | {
|
|
46
|
+
provider: "fireblocks";
|
|
47
|
+
address: string;
|
|
48
|
+
vaultId: string;
|
|
49
|
+
/**
|
|
50
|
+
* Fireblocks does not expose API-user role via API. The CLI
|
|
51
|
+
* surfaces a static reminder to verify the role at the console.
|
|
52
|
+
*/
|
|
53
|
+
roleIntrospectable: false;
|
|
54
|
+
} | {
|
|
55
|
+
provider: "bankr";
|
|
56
|
+
address: string;
|
|
57
|
+
/**
|
|
58
|
+
* Bankr does not expose key-scope flags via API. The CLI surfaces
|
|
59
|
+
* a static reminder to verify scope at bankr.bot/api.
|
|
60
|
+
*/
|
|
61
|
+
scopeIntrospectable: false;
|
|
62
|
+
};
|
|
8
63
|
interface TransactionRequest {
|
|
9
64
|
to: string;
|
|
10
65
|
data: string;
|
|
@@ -53,8 +108,16 @@ interface WalletAdapter {
|
|
|
53
108
|
signMessage?(request: SignMessageRequest): Promise<string>;
|
|
54
109
|
/** Sign EIP-712 typed data. Throws if not supported. */
|
|
55
110
|
signTypedData?(request: SignTypedDataRequest): Promise<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Read-only metadata about the wallet's security posture. Used by the
|
|
113
|
+
* `opensea wallet info` CLI to surface hardening gaps (no policy, no
|
|
114
|
+
* authorization-key gating, root-user API key, etc.). Optional because
|
|
115
|
+
* not every adapter has a meaningful introspection surface — the
|
|
116
|
+
* private-key adapter, for instance, has nothing to report.
|
|
117
|
+
*/
|
|
118
|
+
getWalletInfo?(): Promise<WalletInfo>;
|
|
56
119
|
/** Optional RPC URL for read operations (gas estimation, nonce, etc.) */
|
|
57
|
-
getRpcUrl?(): string;
|
|
120
|
+
getRpcUrl?(): string | undefined;
|
|
58
121
|
/** Optional hook called before each adapter request (for metrics/logging) */
|
|
59
122
|
onRequest?: (method: string, params: unknown) => void;
|
|
60
123
|
/** Optional hook called after each adapter response (for metrics/logging) */
|
|
@@ -77,4 +140,4 @@ interface WalletCapabilities {
|
|
|
77
140
|
type WalletProvider = "privy" | "turnkey" | "fireblocks" | "bankr" | "private-key";
|
|
78
141
|
declare const WALLET_PROVIDERS: WalletProvider[];
|
|
79
142
|
|
|
80
|
-
export { type SignMessageRequest as S, type TransactionRequest as T, type WalletAdapter as W, type WalletCapabilities as a, type
|
|
143
|
+
export { type SignMessageRequest as S, type TransactionRequest as T, type WalletAdapter as W, type WalletCapabilities as a, type WalletInfo as b, type TransactionResult as c, type SignTypedDataRequest as d, type WalletProvider as e, WALLET_PROVIDERS as f };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { W as WalletAdapter, a as WalletCapabilities, T as TransactionRequest,
|
|
2
|
-
export {
|
|
1
|
+
import { W as WalletAdapter, a as WalletCapabilities, b as WalletInfo, T as TransactionRequest, c as TransactionResult, S as SignMessageRequest, d as SignTypedDataRequest, e as WalletProvider } from './index-jjHnOuwA.js';
|
|
2
|
+
export { f as WALLET_PROVIDERS } from './index-jjHnOuwA.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bankr wallet adapter.
|
|
@@ -7,6 +7,38 @@ export { e as WALLET_PROVIDERS } from './index-DFTwYt_e.js';
|
|
|
7
7
|
* Uses Bankr's Wallet API to sign and send transactions via a managed
|
|
8
8
|
* agent wallet. Authentication is done via API key in the X-API-Key header.
|
|
9
9
|
*
|
|
10
|
+
* # Security model
|
|
11
|
+
*
|
|
12
|
+
* This adapter is **signing-only by design.** It exposes only the
|
|
13
|
+
* primitives an agent needs: `getAddress`, `sendTransaction`,
|
|
14
|
+
* `signMessage`, `signTypedData`, and `getWalletInfo`. Future
|
|
15
|
+
* contributors: do not add scope-mutation or key-management surfaces
|
|
16
|
+
* here — Bankr does not expose them via API anyway, and adding
|
|
17
|
+
* adapter-side wrappers around dashboard ops would be a footgun.
|
|
18
|
+
*
|
|
19
|
+
* Effective hardening is done at the API key configuration level on
|
|
20
|
+
* bankr.bot/api, not in this adapter:
|
|
21
|
+
*
|
|
22
|
+
* 1. For monitoring-only agents, enable the key's `readOnly` flag —
|
|
23
|
+
* `/wallet/sign` and `/wallet/submit` will return 403.
|
|
24
|
+
*
|
|
25
|
+
* 2. For signing agents, set `allowedRecipients` (an EVM/Solana
|
|
26
|
+
* address allowlist) and `allowedIps` (CIDR allowlist) on the
|
|
27
|
+
* key. Disable `agentApiEnabled` if the agent does not need
|
|
28
|
+
* Bankr's prompt API.
|
|
29
|
+
*
|
|
30
|
+
* 3. Set per-key daily message limits at bankr.bot/api.
|
|
31
|
+
*
|
|
32
|
+
* 4. Bankr does not expose key-scope flags via API, so
|
|
33
|
+
* `getWalletInfo()` cannot verify these settings at runtime —
|
|
34
|
+
* `opensea wallet info` reminds the user to verify scope at the
|
|
35
|
+
* dashboard. Re-confirm after any key rotation.
|
|
36
|
+
*
|
|
37
|
+
* 5. Bankr keys cannot enforce aggregate dollar/ETH spend caps; daily
|
|
38
|
+
* message-quota limits are not the same thing. Use the hot/cold
|
|
39
|
+
* wallet float pattern documented in
|
|
40
|
+
* `packages/skill/opensea-wallet/references/wallet-funding.md`.
|
|
41
|
+
*
|
|
10
42
|
* Required environment variables:
|
|
11
43
|
* BANKR_API_KEY — Bankr API key with Wallet API access enabled
|
|
12
44
|
*
|
|
@@ -14,7 +46,7 @@ export { e as WALLET_PROVIDERS } from './index-DFTwYt_e.js';
|
|
|
14
46
|
* BANKR_API_BASE_URL — Override the Bankr API base URL
|
|
15
47
|
*
|
|
16
48
|
* @see https://docs.bankr.bot/agent-api/authentication
|
|
17
|
-
* @see https://docs.bankr.bot/
|
|
49
|
+
* @see https://docs.bankr.bot/agent-api/access-control
|
|
18
50
|
*/
|
|
19
51
|
|
|
20
52
|
interface BankrConfig {
|
|
@@ -33,6 +65,7 @@ declare class BankrAdapter implements WalletAdapter {
|
|
|
33
65
|
private get baseUrl();
|
|
34
66
|
private get authHeaders();
|
|
35
67
|
getAddress(): Promise<string>;
|
|
68
|
+
getWalletInfo(): Promise<WalletInfo>;
|
|
36
69
|
sendTransaction(tx: TransactionRequest): Promise<TransactionResult>;
|
|
37
70
|
signMessage(request: SignMessageRequest): Promise<string>;
|
|
38
71
|
signTypedData(request: SignTypedDataRequest): Promise<string>;
|
|
@@ -52,8 +85,43 @@ declare const CHAIN_TO_FIREBLOCKS_ASSET: Record<number, string>;
|
|
|
52
85
|
* Uses Fireblocks' REST API to sign and send transactions through their
|
|
53
86
|
* enterprise-grade MPC custody infrastructure.
|
|
54
87
|
*
|
|
88
|
+
* # Security model
|
|
89
|
+
*
|
|
90
|
+
* This adapter is **signing-only by design.** It exposes only the
|
|
91
|
+
* primitives an agent needs to sign and send transactions:
|
|
92
|
+
* `getAddress`, `sendTransaction`, `signMessage`, `signTypedData`, and
|
|
93
|
+
* `getWalletInfo`. Future contributors: **do not add
|
|
94
|
+
* `createTransactionAuthPolicy`, `updateUser`, `createApiUser`,
|
|
95
|
+
* `whitelistAddress`, or any other administrative endpoint to this
|
|
96
|
+
* adapter.** If they exist, an agent will find and use them.
|
|
97
|
+
*
|
|
98
|
+
* Effective hardening requires creating the API key with the **`Signer`
|
|
99
|
+
* role** and nothing broader:
|
|
100
|
+
*
|
|
101
|
+
* 1. Fireblocks supports nine API key roles: Admin, Signer,
|
|
102
|
+
* NCW_SIGNER, Non-Signing Admin, Approver, Editor, NCW_ADMIN,
|
|
103
|
+
* Viewer, and Security Auditor. Only `Signer` (or `NCW_SIGNER`)
|
|
104
|
+
* gives signing capability without governance access. Do not use
|
|
105
|
+
* `Admin` for an agent.
|
|
106
|
+
*
|
|
107
|
+
* 2. Fireblocks does not expose API-user role via API — there is no
|
|
108
|
+
* `/v1/users/me` introspection endpoint, and `GET /v1/users/{id}`
|
|
109
|
+
* itself requires admin role. `getWalletInfo()` therefore cannot
|
|
110
|
+
* verify the calling key's role at runtime; verify it manually at
|
|
111
|
+
* console.fireblocks.io and re-confirm whenever you rotate the key.
|
|
112
|
+
*
|
|
113
|
+
* 3. TAP changes require admin quorum approval at the console — a
|
|
114
|
+
* leaked Signer-role key cannot rewrite TAP. This is structurally
|
|
115
|
+
* stronger than Privy or Turnkey, but only if the key is actually
|
|
116
|
+
* `Signer` rather than `Admin`.
|
|
117
|
+
*
|
|
118
|
+
* 4. TAP rules cap per-tx values; aggregate (daily/weekly) caps are
|
|
119
|
+
* not a TAP primitive. Use the hot/cold wallet float pattern
|
|
120
|
+
* documented in
|
|
121
|
+
* `packages/skill/opensea-wallet/references/wallet-funding.md`.
|
|
122
|
+
*
|
|
55
123
|
* Required environment variables:
|
|
56
|
-
* FIREBLOCKS_API_KEY — Fireblocks API key
|
|
124
|
+
* FIREBLOCKS_API_KEY — Fireblocks API key (must be Signer role)
|
|
57
125
|
* FIREBLOCKS_API_SECRET — Fireblocks API secret (RSA private key, PEM-encoded)
|
|
58
126
|
* FIREBLOCKS_VAULT_ID — Fireblocks vault account ID
|
|
59
127
|
*
|
|
@@ -62,7 +130,8 @@ declare const CHAIN_TO_FIREBLOCKS_ASSET: Record<number, string>;
|
|
|
62
130
|
* FIREBLOCKS_ASSET_ID — Override the Fireblocks asset ID
|
|
63
131
|
* FIREBLOCKS_MAX_POLL_ATTEMPTS — Override max polling attempts (default: 60 = 120s)
|
|
64
132
|
*
|
|
65
|
-
* @see https://developers.fireblocks.com/docs/
|
|
133
|
+
* @see https://developers.fireblocks.com/docs/manage-api-keys
|
|
134
|
+
* @see https://developers.fireblocks.com/docs/manage-users
|
|
66
135
|
*/
|
|
67
136
|
|
|
68
137
|
interface FireblocksConfig {
|
|
@@ -88,6 +157,7 @@ declare class FireblocksAdapter implements WalletAdapter {
|
|
|
88
157
|
private hashBody;
|
|
89
158
|
private resolveAssetId;
|
|
90
159
|
getAddress(): Promise<string>;
|
|
160
|
+
getWalletInfo(): Promise<WalletInfo>;
|
|
91
161
|
sendTransaction(tx: TransactionRequest): Promise<TransactionResult>;
|
|
92
162
|
signMessage(request: SignMessageRequest): Promise<string>;
|
|
93
163
|
signTypedData(request: SignTypedDataRequest): Promise<string>;
|
|
@@ -106,15 +176,16 @@ declare class FireblocksAdapter implements WalletAdapter {
|
|
|
106
176
|
*
|
|
107
177
|
* Required environment variables:
|
|
108
178
|
* PRIVATE_KEY — Hex-encoded private key (with or without 0x prefix)
|
|
109
|
-
* RPC_URL — JSON-RPC endpoint for broadcasting and gas estimation
|
|
110
179
|
*
|
|
111
180
|
* Optional:
|
|
181
|
+
* RPC_URL — JSON-RPC endpoint for broadcasting and gas estimation
|
|
182
|
+
* (required only when sending transactions)
|
|
112
183
|
* WALLET_ADDRESS — Pre-computed address (skips derivation)
|
|
113
184
|
*/
|
|
114
185
|
|
|
115
186
|
interface PrivateKeyConfig {
|
|
116
187
|
privateKey: string;
|
|
117
|
-
rpcUrl
|
|
188
|
+
rpcUrl?: string;
|
|
118
189
|
address?: string;
|
|
119
190
|
}
|
|
120
191
|
declare class PrivateKeyAdapter implements WalletAdapter {
|
|
@@ -126,7 +197,7 @@ declare class PrivateKeyAdapter implements WalletAdapter {
|
|
|
126
197
|
private cachedAddress?;
|
|
127
198
|
constructor(config: PrivateKeyConfig);
|
|
128
199
|
static fromEnv(): PrivateKeyAdapter;
|
|
129
|
-
getRpcUrl(): string;
|
|
200
|
+
getRpcUrl(): string | undefined;
|
|
130
201
|
getAddress(): Promise<string>;
|
|
131
202
|
sendTransaction(tx: TransactionRequest): Promise<TransactionResult>;
|
|
132
203
|
signMessage(request: SignMessageRequest): Promise<string>;
|
|
@@ -141,16 +212,58 @@ declare class PrivateKeyAdapter implements WalletAdapter {
|
|
|
141
212
|
* Transactions are governed by Privy's programmable policy engine —
|
|
142
213
|
* policies are evaluated in a trusted execution environment before signing.
|
|
143
214
|
*
|
|
215
|
+
* # Security model
|
|
216
|
+
*
|
|
217
|
+
* This adapter is **signing-only by design.** It exposes only the
|
|
218
|
+
* primitives an agent needs to sign transactions and read wallet
|
|
219
|
+
* metadata: `getAddress`, `sendTransaction`, `signMessage`,
|
|
220
|
+
* `signTypedData`, and `getWalletInfo`. It deliberately does not, and
|
|
221
|
+
* should not, expose policy mutation, owner-key rotation, additional-
|
|
222
|
+
* signer changes, key export, or wallet deletion. Future contributors:
|
|
223
|
+
* **do not add `setPolicy`, `rotateOwner`, `addSigner`, or similar
|
|
224
|
+
* mutation methods to this adapter.** If they exist, an agent will find
|
|
225
|
+
* and use them — including raising its own spending cap.
|
|
226
|
+
*
|
|
227
|
+
* Effective hardening requires Privy-side configuration in addition to
|
|
228
|
+
* this adapter's defaults:
|
|
229
|
+
*
|
|
230
|
+
* 1. Create the wallet with an `owner_id` (a key quorum). The owner's
|
|
231
|
+
* private key MUST live outside the agent environment — on a
|
|
232
|
+
* trusted operator machine, in a hardware wallet, or in a separate
|
|
233
|
+
* vault. The owner gates all `PATCH /v1/wallets/{id}` and similar
|
|
234
|
+
* administrative operations.
|
|
235
|
+
*
|
|
236
|
+
* 2. Register the agent's signing key as an `additional_signer` on the
|
|
237
|
+
* wallet, with `override_policy_ids` set to the policy you want
|
|
238
|
+
* the agent to be subject to. The agent's signing key may live in
|
|
239
|
+
* env (`PRIVY_AUTH_SIGNING_KEY`) — it has signing power but cannot
|
|
240
|
+
* mutate policy, signers, or owner.
|
|
241
|
+
*
|
|
242
|
+
* 3. Apply a Privy policy that caps per-tx spend, allowlists
|
|
243
|
+
* contracts, and restricts chains. Policies are stateless per-tx
|
|
244
|
+
* evaluators — they cannot enforce aggregate (daily/weekly)
|
|
245
|
+
* caps. Use the hot/cold wallet float pattern documented in
|
|
246
|
+
* `packages/skill/opensea-wallet/references/wallet-funding.md`
|
|
247
|
+
* for aggregate ceilings.
|
|
248
|
+
*
|
|
144
249
|
* Required environment variables:
|
|
145
250
|
* PRIVY_APP_ID — Privy application ID
|
|
146
251
|
* PRIVY_APP_SECRET — Privy application secret
|
|
147
252
|
* PRIVY_WALLET_ID — Wallet ID to use for signing
|
|
148
253
|
*
|
|
149
254
|
* Optional:
|
|
150
|
-
* PRIVY_API_BASE_URL
|
|
255
|
+
* PRIVY_API_BASE_URL — Override the Privy API base URL
|
|
256
|
+
* PRIVY_AUTH_SIGNING_KEY — Base64-encoded PKCS8 P-256 private key for
|
|
257
|
+
* an `additional_signer` on this wallet. When
|
|
258
|
+
* set, the adapter signs every POST /rpc
|
|
259
|
+
* request with it and attaches the
|
|
260
|
+
* `privy-authorization-signature` header.
|
|
261
|
+
* Required when the wallet has an `owner_id`
|
|
262
|
+
* set; ignored when it does not.
|
|
151
263
|
*
|
|
152
|
-
* @see https://docs.privy.io/wallets/wallets
|
|
264
|
+
* @see https://docs.privy.io/wallets/wallets
|
|
153
265
|
* @see https://docs.privy.io/controls/policies/overview
|
|
266
|
+
* @see https://docs.privy.io/controls/authorization-keys/overview
|
|
154
267
|
*/
|
|
155
268
|
|
|
156
269
|
interface PrivyConfig {
|
|
@@ -158,6 +271,15 @@ interface PrivyConfig {
|
|
|
158
271
|
appSecret: string;
|
|
159
272
|
walletId: string;
|
|
160
273
|
baseUrl?: string;
|
|
274
|
+
/**
|
|
275
|
+
* Optional base64-encoded PKCS8 P-256 authorization private key.
|
|
276
|
+
* When set, every POST /v1/wallets/{id}/rpc request is signed with it
|
|
277
|
+
* and the resulting signature is attached as
|
|
278
|
+
* `privy-authorization-signature`. Use this when the wallet has an
|
|
279
|
+
* `owner_id` configured and the agent's key is registered as an
|
|
280
|
+
* `additional_signer`.
|
|
281
|
+
*/
|
|
282
|
+
authSigningKey?: string;
|
|
161
283
|
}
|
|
162
284
|
declare class PrivyAdapter implements WalletAdapter {
|
|
163
285
|
readonly name = "privy";
|
|
@@ -169,8 +291,16 @@ declare class PrivyAdapter implements WalletAdapter {
|
|
|
169
291
|
constructor(config: PrivyConfig);
|
|
170
292
|
static fromEnv(): PrivyAdapter;
|
|
171
293
|
private get baseUrl();
|
|
172
|
-
private get
|
|
294
|
+
private get basicAuthHeaders();
|
|
295
|
+
/**
|
|
296
|
+
* Build headers for a POST /rpc call, including the authorization
|
|
297
|
+
* signature when `authSigningKey` is configured. Lazy-imports
|
|
298
|
+
* `@privy-io/node` so users who don't enable auth-key signing don't
|
|
299
|
+
* need the optional peer dependency installed.
|
|
300
|
+
*/
|
|
301
|
+
private rpcHeaders;
|
|
173
302
|
getAddress(): Promise<string>;
|
|
303
|
+
getWalletInfo(): Promise<WalletInfo>;
|
|
174
304
|
sendTransaction(tx: TransactionRequest): Promise<TransactionResult>;
|
|
175
305
|
signMessage(request: SignMessageRequest): Promise<string>;
|
|
176
306
|
signTypedData(request: SignTypedDataRequest): Promise<string>;
|
|
@@ -183,6 +313,42 @@ declare class PrivyAdapter implements WalletAdapter {
|
|
|
183
313
|
* signing infrastructure. Authentication uses Turnkey's stamp scheme:
|
|
184
314
|
* each request body is hashed and signed with a P-256 ECDSA key.
|
|
185
315
|
*
|
|
316
|
+
* # Security model
|
|
317
|
+
*
|
|
318
|
+
* This adapter is **signing-only by design.** It exposes only the
|
|
319
|
+
* primitives an agent needs to sign transactions and read user
|
|
320
|
+
* metadata: `getAddress`, `sendTransaction`, `signMessage`,
|
|
321
|
+
* `signTypedData`, and `getWalletInfo`. Future contributors: **do not
|
|
322
|
+
* add `createPolicy`, `deletePolicy`, `createApiKeys`, `updateUser`,
|
|
323
|
+
* `exportWallet`, or any other administrative activity submission to
|
|
324
|
+
* this adapter.** If they exist, an agent will find and use them.
|
|
325
|
+
*
|
|
326
|
+
* Effective hardening requires creating the API user as a **non-root
|
|
327
|
+
* user** with a tightly scoped sign-only policy:
|
|
328
|
+
*
|
|
329
|
+
* 1. Root users in Turnkey bypass the policy engine entirely. A
|
|
330
|
+
* leaked root-user API key has the same blast radius as a raw
|
|
331
|
+
* private key — it can sign anything, mutate any policy, mint new
|
|
332
|
+
* wallets, and export keys. Do not use a root user as the agent's
|
|
333
|
+
* API user.
|
|
334
|
+
*
|
|
335
|
+
* 2. Create a non-root API user, then attach a policy that allows
|
|
336
|
+
* only `ACTIVITY_TYPE_SIGN_TRANSACTION_V2` (and
|
|
337
|
+
* `ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2` if EIP-712 is needed) for
|
|
338
|
+
* the wallet addresses the agent should be able to sign for.
|
|
339
|
+
* Default-deny on everything else; Turnkey policies default to
|
|
340
|
+
* deny so this is mostly a matter of writing the allowlist.
|
|
341
|
+
*
|
|
342
|
+
* 3. Note that Turnkey policies are stateless per-activity
|
|
343
|
+
* evaluators — they cannot enforce aggregate (daily/weekly) caps.
|
|
344
|
+
* Use the hot/cold wallet float pattern documented in
|
|
345
|
+
* `packages/skill/opensea-wallet/references/wallet-funding.md`
|
|
346
|
+
* for aggregate ceilings.
|
|
347
|
+
*
|
|
348
|
+
* `getWalletInfo()` calls `whoami` and `get_organization` to surface
|
|
349
|
+
* whether the API user is in the root quorum, so `opensea wallet info`
|
|
350
|
+
* can warn loudly if the agent is running as root.
|
|
351
|
+
*
|
|
186
352
|
* Required environment variables:
|
|
187
353
|
* TURNKEY_API_PUBLIC_KEY — Turnkey API public key (hex-encoded)
|
|
188
354
|
* TURNKEY_API_PRIVATE_KEY — Turnkey API private key (hex-encoded P-256)
|
|
@@ -194,7 +360,8 @@ declare class PrivyAdapter implements WalletAdapter {
|
|
|
194
360
|
* TURNKEY_API_BASE_URL — Override the Turnkey API base URL
|
|
195
361
|
* TURNKEY_PRIVATE_KEY_ID — Turnkey private key ID (for signing with a specific key)
|
|
196
362
|
*
|
|
197
|
-
* @see https://docs.turnkey.com/
|
|
363
|
+
* @see https://docs.turnkey.com/concepts/policies/overview
|
|
364
|
+
* @see https://docs.turnkey.com/concepts/users/best-practices
|
|
198
365
|
*/
|
|
199
366
|
|
|
200
367
|
interface TurnkeyConfig {
|
|
@@ -219,6 +386,7 @@ declare class TurnkeyAdapter implements WalletAdapter {
|
|
|
219
386
|
private stamp;
|
|
220
387
|
private signedRequest;
|
|
221
388
|
getAddress(): Promise<string>;
|
|
389
|
+
getWalletInfo(): Promise<WalletInfo>;
|
|
222
390
|
sendTransaction(tx: TransactionRequest): Promise<TransactionResult>;
|
|
223
391
|
signMessage(request: SignMessageRequest): Promise<string>;
|
|
224
392
|
signTypedData(request: SignTypedDataRequest): Promise<string>;
|
|
@@ -238,4 +406,4 @@ declare function createWalletFromEnv(): WalletAdapter;
|
|
|
238
406
|
declare function createWalletForProvider(provider: WalletProvider): WalletAdapter;
|
|
239
407
|
declare function detectProvider(): WalletProvider | null;
|
|
240
408
|
|
|
241
|
-
export { BankrAdapter, type BankrConfig, CHAIN_TO_FIREBLOCKS_ASSET, FireblocksAdapter, type FireblocksConfig, PrivateKeyAdapter, type PrivateKeyConfig, PrivyAdapter, type PrivyConfig, SignMessageRequest, SignTypedDataRequest, TransactionRequest, TransactionResult, TurnkeyAdapter, type TurnkeyConfig, WalletAdapter, WalletCapabilities, WalletProvider, createWalletForProvider, createWalletFromEnv, detectProvider };
|
|
409
|
+
export { BankrAdapter, type BankrConfig, CHAIN_TO_FIREBLOCKS_ASSET, FireblocksAdapter, type FireblocksConfig, PrivateKeyAdapter, type PrivateKeyConfig, PrivyAdapter, type PrivyConfig, SignMessageRequest, SignTypedDataRequest, TransactionRequest, TransactionResult, TurnkeyAdapter, type TurnkeyConfig, WalletAdapter, WalletCapabilities, WalletInfo, WalletProvider, createWalletForProvider, createWalletFromEnv, detectProvider };
|