@distilled.cloud/coinbase 1.0.0-rc.1 → 1.0.0-rc.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.
@@ -0,0 +1,324 @@
1
+ /**
2
+ * CoinbaseProtocol — hand-written.
3
+ *
4
+ * Speaks the Coinbase CDP JSON protocol. The generic request/response
5
+ * machinery (trait-driven request building, recursive wire-name mapping)
6
+ * lives in `@distilled.cloud/core/protocol-http`; this module supplies what
7
+ * is Coinbase's own:
8
+ *
9
+ * ## Authentication
10
+ *
11
+ * The Coinbase CDP API uses per-request JWT bearer tokens. The JWT is signed
12
+ * with your CDP API Key Secret (ES256 or Ed25519) and includes:
13
+ *
14
+ * - `sub`: Your CDP API Key ID
15
+ * - `iss`: "cdp"
16
+ * - `aud`: ["cdp_service"]
17
+ * - `exp`: Current time + 120 seconds
18
+ * - `uri`: "METHOD host/path"
19
+ *
20
+ * Some sensitive wallet operations additionally document an `X-Wallet-Auth`
21
+ * header signed with your Wallet Secret (`Config.walletSecret`); like the
22
+ * distilled v0 client, this module does not generate that header.
23
+ *
24
+ * ## Error Handling
25
+ *
26
+ * Coinbase CDP errors have the shape:
27
+ * ```json
28
+ * {
29
+ * "errorType": "invalid_request",
30
+ * "errorMessage": "Invalid request.",
31
+ * "correlationId": "41deb8d59a9dc9a7-IAD",
32
+ * "errorLink": "https://docs.cdp.coinbase.com/api-reference/v2/errors#invalid-request"
33
+ * }
34
+ * ```
35
+ *
36
+ * Errors are handled globally (no per-operation error lists), dispatched
37
+ * first by `errorType`, then by HTTP status code.
38
+ */
39
+ import * as Effect from "effect/Effect";
40
+ import * as Layer from "effect/Layer";
41
+ import * as Redacted from "effect/Redacted";
42
+ import * as Schema from "effect/Schema";
43
+ import * as crypto from "node:crypto";
44
+ import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
45
+ import * as API from "@distilled.cloud/core/api";
46
+ import { buildRequest, mapKeys } from "@distilled.cloud/core/protocol-http";
47
+ import { unwrapRedactedDeep, wrapSensitive, } from "@distilled.cloud/core/protocol-rest";
48
+ import { HTTP_STATUS_MAP, } from "@distilled.cloud/core/errors";
49
+ import { parseRetryAfterForStatus } from "@distilled.cloud/core/retry-after";
50
+ import { Credentials } from "./credentials.js";
51
+ import { COINBASE_HTTP_STATUS_MAP, ERROR_TYPE_MAP, STANDARD_ERROR_TYPE_MAP, UnknownCoinbaseError, } from "./errors.js";
52
+ // Bridge: Protocol.decode is typed as Effect<unknown> (no error channel), but
53
+ // Coinbase failures are real typed errors that the operation's explicit
54
+ // `CoinbaseOpError` annotation re-surfaces. Fail with the instance and erase
55
+ // the error type here.
56
+ const fail = (e) => Effect.fail(e);
57
+ // ============================================================================
58
+ // JWT generation for Coinbase CDP API authentication
59
+ // ============================================================================
60
+ /**
61
+ * Base64url-encode a buffer.
62
+ */
63
+ const base64url = (buf) => Buffer.from(buf)
64
+ .toString("base64")
65
+ .replace(/\+/g, "-")
66
+ .replace(/\//g, "_")
67
+ .replace(/=+$/, "");
68
+ /**
69
+ * Generate a random hex nonce.
70
+ */
71
+ const randomNonce = () => crypto.randomBytes(16).toString("hex");
72
+ /**
73
+ * Detect key type and return the appropriate signing algorithm and key object.
74
+ */
75
+ const resolveSigningKey = (apiKeySecret) => {
76
+ // Try EC (ES256) first — PEM format
77
+ if (apiKeySecret.includes("-----BEGIN")) {
78
+ return {
79
+ algorithm: "ES256",
80
+ jwsAlg: "ES256",
81
+ key: crypto.createPrivateKey(apiKeySecret),
82
+ };
83
+ }
84
+ // Ed25519 — base64 encoded 64-byte key (32 seed + 32 public)
85
+ const keyBytes = Buffer.from(apiKeySecret, "base64");
86
+ if (keyBytes.length === 64) {
87
+ // Extract the 32-byte seed (private key)
88
+ const seed = keyBytes.subarray(0, 32);
89
+ // Import as Ed25519 private key using PKCS8 DER wrapping
90
+ // Ed25519 PKCS8 prefix: 302e020100300506032b657004220420
91
+ const pkcs8Prefix = Buffer.from("302e020100300506032b657004220420", "hex");
92
+ const pkcs8Der = Buffer.concat([pkcs8Prefix, seed]);
93
+ return {
94
+ algorithm: "EdDSA",
95
+ jwsAlg: "EdDSA",
96
+ key: crypto.createPrivateKey({
97
+ key: pkcs8Der,
98
+ format: "der",
99
+ type: "pkcs8",
100
+ }),
101
+ };
102
+ }
103
+ throw new Error("Unsupported CDP API Key Secret format. Expected EC PEM or Ed25519 base64.");
104
+ };
105
+ /**
106
+ * Generate a JWT bearer token for Coinbase CDP API authentication.
107
+ *
108
+ * The JWT includes:
109
+ * - header: { alg, kid, typ: "JWT", nonce }
110
+ * - payload: { sub, iss: "cdp", aud, nbf, exp, uri }
111
+ */
112
+ const generateJwt = (apiKeyId, apiKeySecret, method, uri) => {
113
+ const { jwsAlg, key } = resolveSigningKey(apiKeySecret);
114
+ const now = Math.floor(Date.now() / 1000);
115
+ const header = {
116
+ alg: jwsAlg,
117
+ kid: apiKeyId,
118
+ typ: "JWT",
119
+ nonce: randomNonce(),
120
+ };
121
+ const payload = {
122
+ sub: apiKeyId,
123
+ iss: "cdp",
124
+ aud: ["cdp_service"],
125
+ nbf: now,
126
+ exp: now + 120,
127
+ uri: `${method} ${uri}`,
128
+ };
129
+ const headerB64 = base64url(Buffer.from(JSON.stringify(header)));
130
+ const payloadB64 = base64url(Buffer.from(JSON.stringify(payload)));
131
+ const signingInput = `${headerB64}.${payloadB64}`;
132
+ let signature;
133
+ if (jwsAlg === "ES256") {
134
+ // ES256 uses SHA-256 with ECDSA, needs IEEE P1363 format (not DER)
135
+ const sign = crypto.createSign("SHA256");
136
+ sign.update(signingInput);
137
+ const derSig = sign.sign(key);
138
+ // Convert DER signature to IEEE P1363 (raw r||s) format
139
+ signature = derToP1363(derSig, 32);
140
+ }
141
+ else {
142
+ // EdDSA (Ed25519) uses sign directly
143
+ signature = Buffer.from(crypto.sign(null, Buffer.from(signingInput), key));
144
+ }
145
+ return `${signingInput}.${base64url(signature)}`;
146
+ };
147
+ /**
148
+ * Convert a DER-encoded ECDSA signature to IEEE P1363 (raw r||s) format.
149
+ * JWS requires P1363 format for ES256.
150
+ */
151
+ const derToP1363 = (derSig, componentLength) => {
152
+ // DER format: 30 <len> 02 <rLen> <r> 02 <sLen> <s>
153
+ let offset = 2; // skip 30 <len>
154
+ if (derSig[1] & 0x80)
155
+ offset += derSig[1] & 0x7f;
156
+ // Read r
157
+ offset++; // skip 02
158
+ const rLen = derSig[offset++];
159
+ const r = derSig.subarray(offset, offset + rLen);
160
+ offset += rLen;
161
+ // Read s
162
+ offset++; // skip 02
163
+ const sLen = derSig[offset++];
164
+ const s = derSig.subarray(offset, offset + sLen);
165
+ // Pad or trim to componentLength
166
+ const result = Buffer.alloc(componentLength * 2);
167
+ const rPadded = r.length > componentLength ? r.subarray(r.length - componentLength) : r;
168
+ const sPadded = s.length > componentLength ? s.subarray(s.length - componentLength) : s;
169
+ rPadded.copy(result, componentLength - rPadded.length);
170
+ sPadded.copy(result, componentLength * 2 - sPadded.length);
171
+ return result;
172
+ };
173
+ // ============================================================================
174
+ // Error response parsing
175
+ // ============================================================================
176
+ /**
177
+ * Coinbase CDP API Error Response Schema.
178
+ *
179
+ * All Coinbase CDP errors have the same envelope:
180
+ * { errorType, errorMessage, correlationId?, errorLink? }
181
+ */
182
+ const CoinbaseErrorResponse = Schema.Struct({
183
+ errorType: Schema.String,
184
+ errorMessage: Schema.String,
185
+ correlationId: Schema.optional(Schema.String),
186
+ errorLink: Schema.optional(Schema.String),
187
+ });
188
+ /**
189
+ * Match a Coinbase CDP API error response to the appropriate typed error
190
+ * class. Ported from the distilled v0 client's `matchError`.
191
+ *
192
+ * Dispatches errors by:
193
+ * 1. The `errorType` field for Coinbase-specific errors (e.g., "already_exists", "policy_violation")
194
+ * 2. The `errorType` field for standard errors mapped to core classes (e.g., "not_found" → NotFound)
195
+ * 3. Standard HTTP status codes mapped from core (400, 401, 403, 404, etc.)
196
+ * 4. Coinbase-specific HTTP status codes (402)
197
+ * 5. Falls back to UnknownCoinbaseError for unrecognized errors
198
+ *
199
+ * Error bodies carrying `isValid`/`success` keys are policy-validation
200
+ * results delivered with an error status — treated as success values
201
+ * (`Effect.succeed`) like the v0 client did.
202
+ */
203
+ const matchError = (status, errorBody, headers) => {
204
+ if (errorBody &&
205
+ typeof errorBody === "object" &&
206
+ ("isValid" in errorBody || "success" in errorBody)) {
207
+ return Effect.succeed(errorBody);
208
+ }
209
+ try {
210
+ const parsed = Schema.decodeUnknownSync(CoinbaseErrorResponse)(errorBody);
211
+ const errorProps = {
212
+ errorType: parsed.errorType,
213
+ errorMessage: parsed.errorMessage,
214
+ correlationId: parsed.correlationId,
215
+ errorLink: parsed.errorLink,
216
+ };
217
+ // 1. Match by Coinbase-specific error type first
218
+ const TypedErrorClass = ERROR_TYPE_MAP[parsed.errorType];
219
+ if (TypedErrorClass) {
220
+ return fail(new TypedErrorClass(errorProps));
221
+ }
222
+ // 2. Match standard error types to core HTTP error classes
223
+ // Maps error types like "not_found", "forbidden", "unauthorized",
224
+ // "invalid_request", "rate_limit_exceeded", "internal_server_error",
225
+ // "bad_gateway", "service_unavailable" to core HTTP error classes.
226
+ const StandardErrorClass = STANDARD_ERROR_TYPE_MAP[parsed.errorType];
227
+ if (StandardErrorClass) {
228
+ return fail(new StandardErrorClass({
229
+ message: parsed.errorMessage ?? "",
230
+ retryAfter: parseRetryAfterForStatus(status, headers),
231
+ }));
232
+ }
233
+ // 3. Fall back to HTTP status code mapping from core
234
+ const CoreErrorClass = HTTP_STATUS_MAP[status];
235
+ if (CoreErrorClass) {
236
+ return fail(new CoreErrorClass({
237
+ message: parsed.errorMessage ?? "",
238
+ retryAfter: parseRetryAfterForStatus(status, headers),
239
+ }));
240
+ }
241
+ // 4. Coinbase-specific HTTP status codes (402)
242
+ const CoinbaseErrorClass = COINBASE_HTTP_STATUS_MAP[status];
243
+ if (CoinbaseErrorClass) {
244
+ return fail(new CoinbaseErrorClass(errorProps));
245
+ }
246
+ // 5. Fall back to unknown error
247
+ return fail(new UnknownCoinbaseError({
248
+ ...errorProps,
249
+ body: errorBody,
250
+ }));
251
+ }
252
+ catch {
253
+ return fail(new UnknownCoinbaseError({ body: errorBody }));
254
+ }
255
+ };
256
+ // ============================================================================
257
+ // Protocol
258
+ // ============================================================================
259
+ // The protocol layer is memoized per process by `API.make`, so the build must
260
+ // not capture credentials — `encode` resolves Credentials from the calling
261
+ // fiber's context on every request instead. Like the error channel above,
262
+ // the requirement is erased at this boundary (Protocol effects are typed with
263
+ // no requirements) and reintroduced for callers by the generated
264
+ // `CoinbaseOpContext` annotations.
265
+ const encode = ({ input, inputAst, }) => Effect.gen(function* () {
266
+ // The Credentials service holds an effect — resolving it here (per
267
+ // request) picks up rotations. Its error channel is erased at this
268
+ // boundary; CoinbaseOpError reintroduces it for callers.
269
+ const resolveCredentials = yield* Credentials;
270
+ const creds = (yield* resolveCredentials);
271
+ // Sensitive input members accept string | Redacted<string>; the wire
272
+ // wants the raw string.
273
+ const request = buildRequest({
274
+ input: unwrapRedactedDeep(input),
275
+ inputAst,
276
+ baseUrl: creds.apiBaseUrl,
277
+ });
278
+ // JWT `uri` claim: "METHOD host/path" — label-substituted path, no query
279
+ // string (matches the v0 client: baseUrl.host + baseUrl.pathname +
280
+ // parts.path).
281
+ const url = new URL(request.url);
282
+ const jwt = generateJwt(creds.apiKeyId, Redacted.value(creds.apiKeySecret), request.method, `${url.host}${url.pathname}`);
283
+ return request.pipe(HttpClientRequest.setHeader("Authorization", `Bearer ${jwt}`));
284
+ });
285
+ const decode = ({ response, outputAst, }) => Effect.gen(function* () {
286
+ const text = (yield* response.text.pipe(Effect.orDie)) ?? "";
287
+ if (process.env.DISTILLED_DEBUG_HTTP) {
288
+ console.error(`[distilled] <- ${response.status} ${text.slice(0, 400)}`);
289
+ }
290
+ let json;
291
+ if (text.trim().length > 0) {
292
+ try {
293
+ json = JSON.parse(text);
294
+ }
295
+ catch {
296
+ json = text;
297
+ }
298
+ }
299
+ const status = response.status;
300
+ const headers = response.headers;
301
+ if (status >= 400) {
302
+ const result = yield* matchError(status, json, headers);
303
+ // isValid/success bodies are success values delivered with an error
304
+ // status — map them onto the output schema like a normal response.
305
+ return wrapSensitive(outputAst, mapKeys(outputAst, result, "decode"));
306
+ }
307
+ // No envelope: the response body IS the payload, mapped onto the output
308
+ // schema (wire names → TS names), with members marked T.SensitiveValue
309
+ // delivered as Redacted.
310
+ const body = json === undefined ? {} : json;
311
+ return wrapSensitive(outputAst, mapKeys(outputAst, body, "decode"));
312
+ });
313
+ /**
314
+ * Coinbase CDP protocol layer.
315
+ *
316
+ * Uses JWT bearer token authentication signed per request with your CDP API
317
+ * Key Secret.
318
+ */
319
+ export const CoinbaseProtocol = Layer.succeed(API.Protocol, API.Protocol.of({
320
+ // Erase encode's Credentials requirement (see comment above).
321
+ encode: (args) => encode(args),
322
+ decode,
323
+ }));
324
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
package/lib/retry.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Coinbase retry configuration.
3
+ *
4
+ * Defines the per-SDK `Retry` Context.Service tag that generated operations
5
+ * wire into `API.make({ retry: Retry.Retry })`. Callers can install a
6
+ * blanket retry policy at the layer level and have every Coinbase API call
7
+ * below it pick it up:
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import * as Coinbase from "@distilled.cloud/coinbase";
12
+ *
13
+ * myEffect.pipe(Coinbase.Retry.transient);
14
+ * Effect.provide(myEffect, Layer.succeed(Coinbase.Retry.Retry, customPolicy));
15
+ * ```
16
+ */
17
+ import * as Context from "effect/Context";
18
+ import * as Effect from "effect/Effect";
19
+ import { type Policy } from "@distilled.cloud/core/retry";
20
+ export { type Options, type Factory, type Policy, makeDefault, jittered, capped, throttlingOptions, transientOptions, throttlingFactory, transientFactory, } from "@distilled.cloud/core/retry";
21
+ declare const Retry_base: Context.ServiceClass<Retry, "CoinbaseRetry", Policy>;
22
+ /** Context tag for configuring retry behavior of Coinbase API calls. */
23
+ export declare class Retry extends Retry_base {
24
+ }
25
+ /** Provides a custom retry policy to every Coinbase API call below it. */
26
+ export declare const policy: (optionsOrFactory: Policy) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
27
+ /** Disables all automatic retries. */
28
+ export declare const none: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
29
+ /** Apply the throttling retry policy (retries throttling errors indefinitely). */
30
+ export declare const throttling: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
31
+ /** Apply the transient retry policy (retries all transient errors indefinitely). */
32
+ export declare const transient: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Retry>>;
33
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EACL,KAAK,MAAM,EAGZ,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,WAAW,EACX,QAAQ,EACR,MAAM,EACN,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;;AAErC,wEAAwE;AACxE,qBAAa,KAAM,SAAQ,UAAiD;CAAG;AAE/E,0EAA0E;AAC1E,eAAO,MAAM,MAAM,qBAAsB,MAAM,sFACS,CAAC;AAEzD,sCAAsC;AACtC,eAAO,MAAM,IAAI,mFAEhB,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,UAAU,mFAA4B,CAAC;AAEpD,oFAAoF;AACpF,eAAO,MAAM,SAAS,mFAA2B,CAAC"}
package/lib/retry.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Coinbase retry configuration.
3
+ *
4
+ * Defines the per-SDK `Retry` Context.Service tag that generated operations
5
+ * wire into `API.make({ retry: Retry.Retry })`. Callers can install a
6
+ * blanket retry policy at the layer level and have every Coinbase API call
7
+ * below it pick it up:
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import * as Coinbase from "@distilled.cloud/coinbase";
12
+ *
13
+ * myEffect.pipe(Coinbase.Retry.transient);
14
+ * Effect.provide(myEffect, Layer.succeed(Coinbase.Retry.Retry, customPolicy));
15
+ * ```
16
+ */
17
+ import * as Context from "effect/Context";
18
+ import * as Effect from "effect/Effect";
19
+ import * as Layer from "effect/Layer";
20
+ import { throttlingFactory, transientFactory, } from "@distilled.cloud/core/retry";
21
+ export { makeDefault, jittered, capped, throttlingOptions, transientOptions, throttlingFactory, transientFactory, } from "@distilled.cloud/core/retry";
22
+ /** Context tag for configuring retry behavior of Coinbase API calls. */
23
+ export class Retry extends Context.Service()("CoinbaseRetry") {
24
+ }
25
+ /** Provides a custom retry policy to every Coinbase API call below it. */
26
+ export const policy = (optionsOrFactory) => Effect.provide(Layer.succeed(Retry, optionsOrFactory));
27
+ /** Disables all automatic retries. */
28
+ export const none = Effect.provide(Layer.succeed(Retry, { while: () => false }));
29
+ /** Apply the throttling retry policy (retries throttling errors indefinitely). */
30
+ export const throttling = policy(throttlingFactory);
31
+ /** Apply the transient retry policy (retries all transient errors indefinitely). */
32
+ export const transient = policy(transientFactory);
33
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAEL,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAIL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,wEAAwE;AACxE,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,OAAO,EAAiB,CAAC,eAAe,CAAC;CAAG;AAE/E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,gBAAwB,EAAE,EAAE,CACjD,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAEzD,sCAAsC;AACtC,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAChC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,CAC7C,CAAC;AAEF,kFAAkF;AAClF,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAEpD,oFAAoF;AACpF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC"}