@solana/keychain-cdp 0.0.0 → 0.6.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.
@@ -0,0 +1,463 @@
1
+ import { assertIsAddress } from '@solana/addresses';
2
+ import { getBase16Decoder, getBase58Encoder, getBase64Encoder } from '@solana/codecs-strings';
3
+ import { assertSignatureValid, base64UrlDecoder, createSignatureDictionary, extractSignatureFromWireTransaction, SignerErrorCode, throwSignerError, } from '@solana/keychain-core';
4
+ import { createKeyPairFromBytes } from '@solana/keys';
5
+ import { getBase64EncodedWireTransaction, } from '@solana/transactions';
6
+ export async function createCdpSigner(config) {
7
+ return await CdpSigner.create(config);
8
+ }
9
+ // --- Module-level constants ---
10
+ const CDP_DEFAULT_BASE_URL = 'https://api.cdp.coinbase.com';
11
+ const CDP_BASE_PATH = '/platform/v2/solana/accounts';
12
+ let base16Decoder;
13
+ let base58Encoder;
14
+ let base64Encoder;
15
+ let utf8Decoder;
16
+ let utf8Encoder;
17
+ function sortJson(value) {
18
+ if (value === null || typeof value !== 'object')
19
+ return value;
20
+ if (Array.isArray(value))
21
+ return value.map(sortJson);
22
+ const obj = value;
23
+ const sorted = {};
24
+ for (const key of Object.keys(obj).sort()) {
25
+ sorted[key] = sortJson(obj[key]);
26
+ }
27
+ return sorted;
28
+ }
29
+ async function computeReqHash(body) {
30
+ base16Decoder || (base16Decoder = getBase16Decoder());
31
+ const json = JSON.stringify(sortJson(body));
32
+ utf8Encoder || (utf8Encoder = new TextEncoder());
33
+ const data = utf8Encoder.encode(json);
34
+ const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', data);
35
+ return base16Decoder.decode(new Uint8Array(hashBuffer));
36
+ }
37
+ async function signJwt(header, payload, privateKey, algorithm) {
38
+ utf8Encoder || (utf8Encoder = new TextEncoder());
39
+ const headerB64 = base64UrlDecoder(utf8Encoder.encode(JSON.stringify(header)));
40
+ const payloadB64 = base64UrlDecoder(utf8Encoder.encode(JSON.stringify(payload)));
41
+ const signingInput = `${headerB64}.${payloadB64}`;
42
+ const inputBytes = utf8Encoder.encode(signingInput);
43
+ let sigBuffer;
44
+ if (algorithm === 'EdDSA') {
45
+ sigBuffer = await globalThis.crypto.subtle.sign('Ed25519', privateKey, inputBytes);
46
+ }
47
+ else {
48
+ // ES256: ECDSA with P-256 + SHA-256; Web Crypto returns IEEE P1363 (r||s) format
49
+ sigBuffer = await globalThis.crypto.subtle.sign({ hash: 'SHA-256', name: 'ECDSA' }, privateKey, inputBytes);
50
+ }
51
+ return `${signingInput}.${base64UrlDecoder(new Uint8Array(sigBuffer))}`;
52
+ }
53
+ async function createAuthJwt(apiKeyId, apiKey, host, method, path) {
54
+ const now = Math.floor(Date.now() / 1000);
55
+ const header = {
56
+ alg: 'EdDSA',
57
+ kid: apiKeyId,
58
+ nonce: globalThis.crypto.randomUUID().replace(/-/g, ''),
59
+ typ: 'JWT',
60
+ };
61
+ const payload = {
62
+ exp: now + 120,
63
+ iat: now,
64
+ iss: 'cdp',
65
+ nbf: now,
66
+ sub: apiKeyId,
67
+ uris: [`${method} ${host}${path}`],
68
+ };
69
+ return await signJwt(header, payload, apiKey, 'EdDSA');
70
+ }
71
+ async function createWalletJwt(walletKey, host, method, path, body) {
72
+ const now = Math.floor(Date.now() / 1000);
73
+ const payload = {
74
+ exp: now + 120,
75
+ iat: now,
76
+ jti: globalThis.crypto.randomUUID(),
77
+ nbf: now,
78
+ uris: [`${method} ${host}${path}`],
79
+ };
80
+ if (shouldIncludeReqHash(body)) {
81
+ payload['reqHash'] = await computeReqHash(body);
82
+ }
83
+ const header = { alg: 'ES256', typ: 'JWT' };
84
+ return await signJwt(header, payload, walletKey, 'ES256');
85
+ }
86
+ // --- Key loading ---
87
+ /**
88
+ * Load the Ed25519 CDP API key from a base64-encoded 64-byte secret (seed || pubkey).
89
+ *
90
+ * Uses `createKeyPairFromBytes` from `@solana/keys`, which validates that the
91
+ * public key bytes match the seed — equivalent to the Rust `validate_ed25519_keypair_bytes`
92
+ * check. This also ensures all crypto uses the Web Crypto API for cross-runtime support.
93
+ */
94
+ async function loadApiKey(cdpApiKeySecret) {
95
+ let keyPair;
96
+ try {
97
+ base64Encoder || (base64Encoder = getBase64Encoder());
98
+ const bytes = base64Encoder.encode(cdpApiKeySecret);
99
+ // createKeyPairFromBytes validates:
100
+ // - input is exactly 64 bytes (seed || pubkey)
101
+ // - the public key bytes match the seed (signs test data and verifies)
102
+ keyPair = await createKeyPairFromBytes(bytes);
103
+ }
104
+ catch (error) {
105
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
106
+ cause: error,
107
+ message: 'Invalid cdpApiKeySecret: must be a base64-encoded 64-byte Ed25519 key (seed || pubkey) where the public key matches the seed',
108
+ });
109
+ }
110
+ return keyPair.privateKey;
111
+ }
112
+ async function loadWalletKey(walletSecret) {
113
+ try {
114
+ base64Encoder || (base64Encoder = getBase64Encoder());
115
+ const der = base64Encoder.encode(walletSecret);
116
+ return await globalThis.crypto.subtle.importKey('pkcs8', der, { name: 'ECDSA', namedCurve: 'P-256' }, false, [
117
+ 'sign',
118
+ ]);
119
+ }
120
+ catch (error) {
121
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
122
+ cause: error,
123
+ message: 'Failed to load P-256 PKCS#8 key from cdpWalletSecret',
124
+ });
125
+ }
126
+ }
127
+ /**
128
+ * CDP-based Solana signer using Coinbase Developer Platform's managed key infrastructure.
129
+ *
130
+ * Makes direct HTTP calls to the CDP REST API — no vendor SDK required.
131
+ * Authentication uses two JWTs per signing request:
132
+ * - `Authorization: Bearer <jwt>` — signed with the CDP API private key (Ed25519)
133
+ * - `X-Wallet-Auth: <jwt>` — signed with the wallet secret (always ES256)
134
+ *
135
+ * The CDP account address must be provided at construction time.
136
+ * Use CDP's API or dashboard to create a Solana account first.
137
+ *
138
+ * Use the static `create()` factory to construct an instance — it validates the
139
+ * Ed25519 key pair (seed↔pubkey match) and loads both keys asynchronously.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const signer = await CdpSigner.create({
144
+ * cdpApiKeyId: process.env.CDP_API_KEY_ID!,
145
+ * cdpApiKeySecret: process.env.CDP_API_KEY_SECRET!,
146
+ * cdpWalletSecret: process.env.CDP_WALLET_SECRET!,
147
+ * address: process.env.CDP_SOLANA_ADDRESS!,
148
+ * });
149
+ * const signed = await signTransactionMessageWithSigners(transactionMessage, [signer]);
150
+ * ```
151
+ *
152
+ * @deprecated Prefer `createCdpSigner()`. Class export will be removed in a future version.
153
+ */
154
+ export class CdpSigner {
155
+ constructor(config) {
156
+ this.address = config.address;
157
+ this.apiKeyId = config.apiKeyId;
158
+ this.apiKey = config.apiKey;
159
+ this.walletKey = config.walletKey;
160
+ this.baseUrl = config.baseUrl;
161
+ this.apiHost = config.apiHost;
162
+ this.requestDelayMs = config.requestDelayMs;
163
+ }
164
+ /**
165
+ * Create and initialize a CdpSigner.
166
+ *
167
+ * Validates the Ed25519 API key (seed↔pubkey match via `createKeyPairFromBytes`)
168
+ * and loads the P-256 wallet key. Both keys are loaded in parallel.
169
+ * @deprecated Use `createCdpSigner()` instead.
170
+ */
171
+ static async create(config) {
172
+ if (!config.cdpApiKeyId) {
173
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
174
+ message: 'Missing required cdpApiKeyId field',
175
+ });
176
+ }
177
+ if (!config.cdpApiKeySecret) {
178
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
179
+ message: 'Missing required cdpApiKeySecret field',
180
+ });
181
+ }
182
+ if (!config.cdpWalletSecret) {
183
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
184
+ message: 'Missing required cdpWalletSecret field',
185
+ });
186
+ }
187
+ if (!config.address) {
188
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
189
+ message: 'Missing required address field',
190
+ });
191
+ }
192
+ let address;
193
+ try {
194
+ assertIsAddress(config.address);
195
+ address = config.address;
196
+ }
197
+ catch (error) {
198
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
199
+ cause: error,
200
+ message: 'Invalid Solana address format',
201
+ });
202
+ }
203
+ const baseUrl = normalizeBaseUrl(config.baseUrl ?? CDP_DEFAULT_BASE_URL);
204
+ let apiHost;
205
+ try {
206
+ apiHost = new URL(baseUrl).host;
207
+ }
208
+ catch (error) {
209
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
210
+ cause: error,
211
+ message: `Invalid baseUrl: ${baseUrl}`,
212
+ });
213
+ }
214
+ const requestDelayMs = config.requestDelayMs ?? 0;
215
+ if (requestDelayMs < 0) {
216
+ throwSignerError(SignerErrorCode.CONFIG_ERROR, {
217
+ message: 'requestDelayMs must not be negative',
218
+ });
219
+ }
220
+ if (requestDelayMs > 3000) {
221
+ console.warn('requestDelayMs is greater than 3000ms, this may result in blockhash expiration errors for signing messages/transactions');
222
+ }
223
+ const [apiKey, walletKey] = await Promise.all([
224
+ loadApiKey(config.cdpApiKeySecret),
225
+ loadWalletKey(config.cdpWalletSecret),
226
+ ]);
227
+ return new CdpSigner({
228
+ address,
229
+ apiHost,
230
+ apiKey,
231
+ apiKeyId: config.cdpApiKeyId,
232
+ baseUrl,
233
+ requestDelayMs,
234
+ walletKey,
235
+ });
236
+ }
237
+ async delay(index) {
238
+ if (this.requestDelayMs > 0 && index > 0) {
239
+ await new Promise(resolve => setTimeout(resolve, index * this.requestDelayMs));
240
+ }
241
+ }
242
+ decodeMessageBytes(messageBytes) {
243
+ try {
244
+ utf8Decoder || (utf8Decoder = new TextDecoder('utf-8', { fatal: true }));
245
+ return utf8Decoder.decode(messageBytes);
246
+ }
247
+ catch (error) {
248
+ throwSignerError(SignerErrorCode.SERIALIZATION_ERROR, {
249
+ cause: error,
250
+ message: 'CDP signMessage requires a valid UTF-8 message',
251
+ });
252
+ }
253
+ }
254
+ async buildPostHeaders(path, body) {
255
+ const [authJwt, walletJwt] = await Promise.all([
256
+ createAuthJwt(this.apiKeyId, this.apiKey, this.apiHost, 'POST', path),
257
+ createWalletJwt(this.walletKey, this.apiHost, 'POST', path, body),
258
+ ]);
259
+ return new Headers({
260
+ Authorization: `Bearer ${authJwt}`,
261
+ 'Content-Type': 'application/json',
262
+ 'X-Wallet-Auth': walletJwt,
263
+ });
264
+ }
265
+ async buildGetHeaders(path) {
266
+ const authJwt = await createAuthJwt(this.apiKeyId, this.apiKey, this.apiHost, 'GET', path);
267
+ return new Headers({
268
+ Authorization: `Bearer ${authJwt}`,
269
+ });
270
+ }
271
+ /**
272
+ * Sign a UTF-8 message string using the CDP API.
273
+ * @returns The 64-byte Ed25519 signature.
274
+ */
275
+ async callSignMessage(message) {
276
+ const path = `${CDP_BASE_PATH}/${this.address}/sign/message`;
277
+ const url = `${this.baseUrl}${path}`;
278
+ const body = { message };
279
+ const headers = await this.buildPostHeaders(path, body);
280
+ let response;
281
+ try {
282
+ response = await fetch(url, {
283
+ body: JSON.stringify(body),
284
+ headers,
285
+ method: 'POST',
286
+ });
287
+ }
288
+ catch (error) {
289
+ throwSignerError(SignerErrorCode.HTTP_ERROR, {
290
+ cause: error,
291
+ message: 'CDP signMessage network request failed',
292
+ url,
293
+ });
294
+ }
295
+ if (!response.ok) {
296
+ const errorText = await response.text().catch(() => 'Failed to read error response');
297
+ throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
298
+ message: `CDP signMessage API error: ${response.status}`,
299
+ response: errorText,
300
+ status: response.status,
301
+ });
302
+ }
303
+ let data;
304
+ try {
305
+ data = (await response.json());
306
+ }
307
+ catch (error) {
308
+ throwSignerError(SignerErrorCode.PARSING_ERROR, {
309
+ cause: error,
310
+ message: 'Failed to parse CDP signMessage response',
311
+ });
312
+ }
313
+ // CDP returns a base58-encoded Ed25519 signature
314
+ base58Encoder || (base58Encoder = getBase58Encoder());
315
+ const signatureBytes = base58Encoder.encode(data.signature);
316
+ if (signatureBytes.length !== 64) {
317
+ throwSignerError(SignerErrorCode.SIGNING_FAILED, {
318
+ message: `Invalid signature length: expected 64 bytes, got ${signatureBytes.length}`,
319
+ });
320
+ }
321
+ return signatureBytes;
322
+ }
323
+ /**
324
+ * Sign a base64-encoded wire transaction using the CDP API.
325
+ * @returns The fully-signed wire transaction (base64-encoded).
326
+ */
327
+ async callSignTransaction(wireTransaction) {
328
+ const path = `${CDP_BASE_PATH}/${this.address}/sign/transaction`;
329
+ const url = `${this.baseUrl}${path}`;
330
+ const body = { transaction: wireTransaction };
331
+ const headers = await this.buildPostHeaders(path, body);
332
+ let response;
333
+ try {
334
+ response = await fetch(url, {
335
+ body: JSON.stringify(body),
336
+ headers,
337
+ method: 'POST',
338
+ });
339
+ }
340
+ catch (error) {
341
+ throwSignerError(SignerErrorCode.HTTP_ERROR, {
342
+ cause: error,
343
+ message: 'CDP signTransaction network request failed',
344
+ url,
345
+ });
346
+ }
347
+ if (!response.ok) {
348
+ const errorText = await response.text().catch(() => 'Failed to read error response');
349
+ throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
350
+ message: `CDP signTransaction API error: ${response.status}`,
351
+ response: errorText,
352
+ status: response.status,
353
+ });
354
+ }
355
+ let data;
356
+ try {
357
+ data = (await response.json());
358
+ }
359
+ catch (error) {
360
+ throwSignerError(SignerErrorCode.PARSING_ERROR, {
361
+ cause: error,
362
+ message: 'Failed to parse CDP signTransaction response',
363
+ });
364
+ }
365
+ return data.signedTransaction;
366
+ }
367
+ /**
368
+ * Sign multiple messages using the CDP API.
369
+ * Message bytes are decoded as UTF-8 before sending to the CDP signMessage endpoint.
370
+ */
371
+ async signMessages(messages) {
372
+ return await Promise.all(messages.map(async (message, index) => {
373
+ await this.delay(index);
374
+ const utf8Message = this.decodeMessageBytes(message.content);
375
+ const signatureBytes = await this.callSignMessage(utf8Message);
376
+ await assertSignatureValid({
377
+ data: message.content,
378
+ signature: signatureBytes,
379
+ signerAddress: this.address,
380
+ });
381
+ return createSignatureDictionary({
382
+ signature: signatureBytes,
383
+ signerAddress: this.address,
384
+ });
385
+ }));
386
+ }
387
+ /**
388
+ * Sign multiple transactions using the CDP API.
389
+ * Returns the signature extracted from the fully-signed wire transaction.
390
+ */
391
+ async signTransactions(transactions) {
392
+ return await Promise.all(transactions.map(async (transaction, index) => {
393
+ await this.delay(index);
394
+ const wireTransaction = getBase64EncodedWireTransaction(transaction);
395
+ const signedWireTx = await this.callSignTransaction(wireTransaction);
396
+ const sigDict = extractSignatureFromWireTransaction({
397
+ base64WireTransaction: signedWireTx,
398
+ signerAddress: this.address,
399
+ });
400
+ const signatureBytes = Object.values(sigDict)[0];
401
+ if (!signatureBytes) {
402
+ throwSignerError(SignerErrorCode.SIGNING_FAILED, {
403
+ address: this.address,
404
+ message: 'No signature bytes found in extracted signature dictionary',
405
+ });
406
+ }
407
+ await assertSignatureValid({
408
+ data: transaction.messageBytes,
409
+ signature: signatureBytes,
410
+ signerAddress: this.address,
411
+ });
412
+ return sigDict;
413
+ }));
414
+ }
415
+ /**
416
+ * Check if the CDP API is reachable and this specific account is accessible.
417
+ */
418
+ async isAvailable() {
419
+ const path = `${CDP_BASE_PATH}/${this.address}`;
420
+ const headers = await this.buildGetHeaders(path);
421
+ let response;
422
+ try {
423
+ response = await fetch(`${this.baseUrl}${path}`, {
424
+ headers,
425
+ method: 'GET',
426
+ });
427
+ }
428
+ catch {
429
+ return false;
430
+ }
431
+ return response.ok;
432
+ }
433
+ }
434
+ function normalizeBaseUrl(baseUrl) {
435
+ let normalized = baseUrl.trim();
436
+ if (normalized.endsWith('/platform')) {
437
+ normalized = normalized.slice(0, -'/platform'.length);
438
+ }
439
+ else if (normalized.endsWith('/platform/')) {
440
+ normalized = normalized.slice(0, -'/platform/'.length);
441
+ }
442
+ if (normalized.endsWith('/')) {
443
+ normalized = normalized.slice(0, -1);
444
+ }
445
+ return normalized;
446
+ }
447
+ function shouldIncludeReqHash(body) {
448
+ if (body === undefined || body === null) {
449
+ return false;
450
+ }
451
+ if (typeof body !== 'object') {
452
+ return true;
453
+ }
454
+ if (Array.isArray(body)) {
455
+ return body.length > 0;
456
+ }
457
+ const entries = Object.entries(body);
458
+ if (entries.length === 0) {
459
+ return false;
460
+ }
461
+ return entries.some(([, value]) => value !== undefined);
462
+ }
463
+ //# sourceMappingURL=cdp-signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp-signer.js","sourceRoot":"","sources":["../src/cdp-signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { CdpSigner, createCdpSigner } from './cdp-signer.js';
2
+ export type { CdpSignerConfig } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { CdpSigner, createCdpSigner } from './cdp-signer.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Configuration for creating a CdpSigner
3
+ */
4
+ export interface CdpSignerConfig {
5
+ /**
6
+ * The Solana account address managed by CDP.
7
+ */
8
+ address: string;
9
+ /**
10
+ * Optional custom CDP API base URL.
11
+ * Defaults to https://api.cdp.coinbase.com
12
+ */
13
+ baseUrl?: string;
14
+ /**
15
+ * CDP API key ID.
16
+ * Used as the `apiKeyId` when authenticating with the CDP API.
17
+ */
18
+ cdpApiKeyId: string;
19
+ /**
20
+ * CDP API private key.
21
+ * Base64-encoded Ed25519 key (64 bytes: seed || pubkey).
22
+ * Used as the `apiKeySecret` when authenticating with the CDP API.
23
+ */
24
+ cdpApiKeySecret: string;
25
+ /**
26
+ * CDP Wallet Secret.
27
+ * Required for signing operations (POST requests to signing endpoints).
28
+ * A base64-encoded PKCS#8 DER EC (P-256) private key.
29
+ */
30
+ cdpWalletSecret: string;
31
+ /**
32
+ * Optional delay in ms between concurrent signing requests to avoid rate limits.
33
+ * Default: 0 (no delay)
34
+ */
35
+ requestDelayMs?: number;
36
+ }
37
+ /** Response from the CDP signMessage endpoint. */
38
+ export interface SignMessageResponse {
39
+ /** Base58-encoded Ed25519 signature. */
40
+ signature: string;
41
+ }
42
+ /** Response from the CDP signTransaction endpoint. */
43
+ export interface SignTransactionResponse {
44
+ /** Base64-encoded signed wire transaction. */
45
+ signedTransaction: string;
46
+ }
47
+ /** Response from the CDP getAccount endpoint. */
48
+ export interface AccountResponse {
49
+ /** Solana account address (base58). */
50
+ address: string;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,kDAAkD;AAClD,MAAM,WAAW,mBAAmB;IAChC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,sDAAsD;AACtD,MAAM,WAAW,uBAAuB;IACpC,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC5B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,11 +1,68 @@
1
1
  {
2
2
  "name": "@solana/keychain-cdp",
3
- "version": "0.0.0",
4
- "description": "",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
3
+ "author": "Solana Foundation",
4
+ "version": "0.6.1",
5
+ "description": "Coinbase Developer Platform (CDP) signer for Solana transactions",
6
+ "license": "MIT",
7
+ "repository": "https://github.com/solana-foundation/solana-keychain",
8
+ "keywords": [
9
+ "solana",
10
+ "signing",
11
+ "wallet",
12
+ "cdp",
13
+ "coinbase"
14
+ ],
15
+ "type": "module",
16
+ "engines": {
17
+ "node": ">=19"
18
+ },
19
+ "sideEffects": false,
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src"
31
+ ],
32
+ "dependencies": {
33
+ "@solana/keychain-core": "0.6.1"
34
+ },
35
+ "peerDependencies": {
36
+ "@solana/addresses": ">=6.0.1",
37
+ "@solana/codecs-strings": ">=6.0.1",
38
+ "@solana/keys": ">=6.0.1",
39
+ "@solana/signers": ">=6.0.1",
40
+ "@solana/transactions": ">=6.0.1"
8
41
  },
9
- "author": "",
10
- "license": "ISC"
11
- }
42
+ "devDependencies": {
43
+ "@solana/addresses": "^6.0.1",
44
+ "@solana/codecs-strings": "^6.0.1",
45
+ "@solana/keys": "^6.0.1",
46
+ "@solana/signers": "^6.0.1",
47
+ "@solana/transactions": "^6.0.1",
48
+ "@solana-program/memo": "^0.11.0",
49
+ "@solana/kit": "^6.0.1",
50
+ "dotenv": "^17.2.3",
51
+ "@solana/keychain-test-utils": "0.6.1"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ },
56
+ "scripts": {
57
+ "build": "tsc --build",
58
+ "clean": "rm -rf dist *.tsbuildinfo",
59
+ "test": "vitest run",
60
+ "test:unit": "vitest run --config ../../vitest.config.unit.ts",
61
+ "test:integration": "vitest run --config ../../vitest.config.integration.ts",
62
+ "test:watch": "vitest",
63
+ "test:watch:unit": "vitest --config ../../vitest.config.unit.ts",
64
+ "test:watch:integration": "vitest --config ../../vitest.config.integration.ts",
65
+ "typecheck": "tsc --noEmit",
66
+ "test:treeshakability": "agadoo dist/index.js"
67
+ }
68
+ }
@@ -0,0 +1,19 @@
1
+ import { runSignerIntegrationTest } from '@solana/keychain-test-utils';
2
+ import { config } from 'dotenv';
3
+ import { describe, it } from 'vitest';
4
+
5
+ import { getConfig } from './setup.js';
6
+
7
+ config();
8
+
9
+ describe('CdpSigner Integration', () => {
10
+ it.skipIf(!process.env.CDP_API_KEY_ID)('signs transactions with real API', async () => {
11
+ await runSignerIntegrationTest(await getConfig(['signTransaction']));
12
+ });
13
+ it.skipIf(!process.env.CDP_API_KEY_ID)('signs messages with real API', async () => {
14
+ await runSignerIntegrationTest(await getConfig(['signMessage']));
15
+ });
16
+ it.skipIf(!process.env.CDP_API_KEY_ID)('simulates transactions with real API', async () => {
17
+ await runSignerIntegrationTest(await getConfig(['simulateTransaction']));
18
+ });
19
+ });