@cowriepay/sdk 0.1.0
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 +99 -0
- package/dist/index.cjs +475 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2934 -0
- package/dist/index.d.ts +2934 -0
- package/dist/index.js +424 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
// src/core/signer.ts
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
function sha256Hex(input) {
|
|
4
|
+
return crypto.createHash("sha256").update(input ?? "", "utf8").digest("hex");
|
|
5
|
+
}
|
|
6
|
+
function buildRequestSigningString(params) {
|
|
7
|
+
const { timestamp, method, path, bodyHash } = params;
|
|
8
|
+
return `${timestamp}.${method.toUpperCase()}.${path}.${bodyHash}`;
|
|
9
|
+
}
|
|
10
|
+
function signRequest(params) {
|
|
11
|
+
const signingString = buildRequestSigningString({
|
|
12
|
+
timestamp: params.timestamp,
|
|
13
|
+
method: params.method,
|
|
14
|
+
path: params.path,
|
|
15
|
+
bodyHash: sha256Hex(params.rawBody ?? "")
|
|
16
|
+
});
|
|
17
|
+
return crypto.createHmac("sha256", params.secret).update(signingString).digest("hex");
|
|
18
|
+
}
|
|
19
|
+
function buildAuthHeaders(params) {
|
|
20
|
+
const timestamp = params.timestamp ?? Math.floor(Date.now() / 1e3).toString();
|
|
21
|
+
const signature = signRequest({
|
|
22
|
+
secret: params.secret,
|
|
23
|
+
timestamp,
|
|
24
|
+
method: params.method,
|
|
25
|
+
path: params.path,
|
|
26
|
+
rawBody: params.rawBody
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
"X-CowriePay-Key": params.apiKey,
|
|
30
|
+
"X-CowriePay-Timestamp": timestamp,
|
|
31
|
+
"X-CowriePay-Signature": signature
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/core/errors.ts
|
|
36
|
+
var CowriePayError = class extends Error {
|
|
37
|
+
/** Machine-readable error code from the envelope (e.g. `INVALID_SIGNATURE`), or a synthetic one. */
|
|
38
|
+
code;
|
|
39
|
+
/** HTTP status, or 0 for transport/connection errors. */
|
|
40
|
+
status;
|
|
41
|
+
/** The `X-CowriePay-Request-Id` / delivery id, when present, for support. */
|
|
42
|
+
requestId;
|
|
43
|
+
/** The parsed response body, when there was one. */
|
|
44
|
+
body;
|
|
45
|
+
constructor(params) {
|
|
46
|
+
super(params.message);
|
|
47
|
+
this.name = new.target.name;
|
|
48
|
+
this.code = params.code;
|
|
49
|
+
this.status = params.status;
|
|
50
|
+
this.requestId = params.requestId;
|
|
51
|
+
this.body = params.body;
|
|
52
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var AuthenticationError = class extends CowriePayError {
|
|
56
|
+
};
|
|
57
|
+
var PermissionError = class extends CowriePayError {
|
|
58
|
+
};
|
|
59
|
+
var NotFoundError = class extends CowriePayError {
|
|
60
|
+
};
|
|
61
|
+
var InvalidRequestError = class extends CowriePayError {
|
|
62
|
+
};
|
|
63
|
+
var RateLimitError = class extends CowriePayError {
|
|
64
|
+
};
|
|
65
|
+
var ApiError = class extends CowriePayError {
|
|
66
|
+
};
|
|
67
|
+
var ConnectionError = class extends CowriePayError {
|
|
68
|
+
};
|
|
69
|
+
function errorFromResponse(status, body, requestId) {
|
|
70
|
+
const code = body?.error?.code ?? httpFallbackCode(status);
|
|
71
|
+
const message = body?.error?.message ?? `CowriePay API error (HTTP ${status})`;
|
|
72
|
+
const params = { message, code, status, requestId, body };
|
|
73
|
+
if (status === 401) return new AuthenticationError(params);
|
|
74
|
+
if (status === 403) return new PermissionError(params);
|
|
75
|
+
if (status === 404) return new NotFoundError(params);
|
|
76
|
+
if (status === 429) return new RateLimitError(params);
|
|
77
|
+
if (status >= 500) return new ApiError(params);
|
|
78
|
+
return new InvalidRequestError(params);
|
|
79
|
+
}
|
|
80
|
+
function httpFallbackCode(status) {
|
|
81
|
+
if (status === 401) return "UNAUTHORIZED";
|
|
82
|
+
if (status === 403) return "FORBIDDEN";
|
|
83
|
+
if (status === 404) return "NOT_FOUND";
|
|
84
|
+
if (status === 429) return "RATE_LIMITED";
|
|
85
|
+
if (status >= 500) return "SERVER_ERROR";
|
|
86
|
+
return "BAD_REQUEST";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/core/client.ts
|
|
90
|
+
var DEFAULT_BASE_URL = "https://api.cowriepay.io";
|
|
91
|
+
var API_PREFIX = "/v2";
|
|
92
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
93
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
94
|
+
function resolveBaseUrl(cfg) {
|
|
95
|
+
return cfg.baseUrl ? cfg.baseUrl.replace(/\/$/, "") : DEFAULT_BASE_URL;
|
|
96
|
+
}
|
|
97
|
+
function encodeQuery(query) {
|
|
98
|
+
if (!query) return "";
|
|
99
|
+
const parts = [];
|
|
100
|
+
for (const [k, v] of Object.entries(query)) {
|
|
101
|
+
if (v === void 0 || v === null) continue;
|
|
102
|
+
parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
|
|
103
|
+
}
|
|
104
|
+
return parts.length ? `?${parts.join("&")}` : "";
|
|
105
|
+
}
|
|
106
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
107
|
+
function backoffMs(attempt, baseMs) {
|
|
108
|
+
const delay = Math.min(baseMs * 2 ** attempt, 8e3);
|
|
109
|
+
return delay + Math.floor(Math.random() * 250);
|
|
110
|
+
}
|
|
111
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
112
|
+
var HttpClient = class {
|
|
113
|
+
cfg;
|
|
114
|
+
baseUrl;
|
|
115
|
+
doFetch;
|
|
116
|
+
constructor(cfg) {
|
|
117
|
+
if (!cfg.apiKey || !cfg.apiSecret) {
|
|
118
|
+
throw new CowriePayError({ message: "apiKey and apiSecret are required", code: "CONFIG_ERROR", status: 0 });
|
|
119
|
+
}
|
|
120
|
+
this.cfg = cfg;
|
|
121
|
+
this.baseUrl = resolveBaseUrl(cfg);
|
|
122
|
+
const f = cfg.fetch ?? globalThis.fetch;
|
|
123
|
+
if (!f) {
|
|
124
|
+
throw new CowriePayError({
|
|
125
|
+
message: "global fetch is unavailable: use Node 18+ or pass config.fetch",
|
|
126
|
+
code: "CONFIG_ERROR",
|
|
127
|
+
status: 0
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
this.doFetch = f;
|
|
131
|
+
}
|
|
132
|
+
async request(opts) {
|
|
133
|
+
const fullPath = `${API_PREFIX}${opts.path}${encodeQuery(opts.query)}`;
|
|
134
|
+
const rawBody = opts.body === void 0 ? "" : JSON.stringify(opts.body);
|
|
135
|
+
const canRetry = opts.method === "GET" || Boolean(opts.idempotencyKey);
|
|
136
|
+
const maxRetries = this.cfg.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
137
|
+
let attempt = 0;
|
|
138
|
+
for (; ; ) {
|
|
139
|
+
try {
|
|
140
|
+
const res = await this.sendOnce(opts, fullPath, rawBody);
|
|
141
|
+
if (RETRYABLE_STATUS.has(res.status) && canRetry && attempt < maxRetries) {
|
|
142
|
+
attempt += 1;
|
|
143
|
+
await sleep(backoffMs(attempt, this.cfg.retryBaseMs ?? 1e3));
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
return await this.parse(res);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (err instanceof CowriePayError) throw err;
|
|
149
|
+
if (canRetry && attempt < maxRetries) {
|
|
150
|
+
attempt += 1;
|
|
151
|
+
await sleep(backoffMs(attempt, this.cfg.retryBaseMs ?? 1e3));
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
throw new ConnectionError({
|
|
155
|
+
message: `request to ${fullPath} failed: ${err?.message ?? String(err)}`,
|
|
156
|
+
code: "CONNECTION_ERROR",
|
|
157
|
+
status: 0
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async sendOnce(opts, fullPath, rawBody) {
|
|
163
|
+
const auth = buildAuthHeaders({
|
|
164
|
+
apiKey: this.cfg.apiKey,
|
|
165
|
+
secret: this.cfg.apiSecret,
|
|
166
|
+
method: opts.method,
|
|
167
|
+
path: fullPath,
|
|
168
|
+
rawBody
|
|
169
|
+
});
|
|
170
|
+
const headers = {
|
|
171
|
+
...auth,
|
|
172
|
+
Accept: "application/json",
|
|
173
|
+
"User-Agent": "cowriepay-node"
|
|
174
|
+
};
|
|
175
|
+
if (opts.body !== void 0) headers["Content-Type"] = "application/json";
|
|
176
|
+
if (opts.idempotencyKey) headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
177
|
+
const timeout = this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
178
|
+
const ac = new AbortController();
|
|
179
|
+
const timer = setTimeout(() => ac.abort(), timeout);
|
|
180
|
+
if (opts.signal) opts.signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
181
|
+
try {
|
|
182
|
+
return await this.doFetch(`${this.baseUrl}${fullPath}`, {
|
|
183
|
+
method: opts.method,
|
|
184
|
+
headers,
|
|
185
|
+
body: opts.body === void 0 ? void 0 : rawBody,
|
|
186
|
+
signal: ac.signal
|
|
187
|
+
});
|
|
188
|
+
} finally {
|
|
189
|
+
clearTimeout(timer);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async parse(res) {
|
|
193
|
+
const requestId = res.headers.get("x-cowriepay-request-id") ?? res.headers.get("x-cowriepay-delivery") ?? void 0;
|
|
194
|
+
const text = await res.text();
|
|
195
|
+
const json = text ? safeJson(text) : void 0;
|
|
196
|
+
if (!res.ok) {
|
|
197
|
+
throw errorFromResponse(res.status, json, requestId);
|
|
198
|
+
}
|
|
199
|
+
return json ?? {};
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
function safeJson(text) {
|
|
203
|
+
try {
|
|
204
|
+
return JSON.parse(text);
|
|
205
|
+
} catch {
|
|
206
|
+
return { error: { code: "INVALID_JSON", message: text.slice(0, 500) } };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/core/webhooks.ts
|
|
211
|
+
import crypto2 from "crypto";
|
|
212
|
+
var PREFIX = "sha256=";
|
|
213
|
+
function normalizeSignature(header) {
|
|
214
|
+
const raw = header.startsWith(PREFIX) ? header.slice(PREFIX.length) : header;
|
|
215
|
+
return raw.trim().toLowerCase();
|
|
216
|
+
}
|
|
217
|
+
function timingSafeHexEqual(a, b) {
|
|
218
|
+
if (a.length !== b.length) return false;
|
|
219
|
+
const ba = Buffer.from(a, "utf8");
|
|
220
|
+
const bb = Buffer.from(b, "utf8");
|
|
221
|
+
return crypto2.timingSafeEqual(ba, bb);
|
|
222
|
+
}
|
|
223
|
+
function computeWebhookSignature(secret, timestamp, rawBody) {
|
|
224
|
+
return crypto2.createHmac("sha256", secret).update(`${timestamp}.${rawBody ?? ""}`).digest("hex");
|
|
225
|
+
}
|
|
226
|
+
function verifyWebhook(opts) {
|
|
227
|
+
const rawBody = Buffer.isBuffer(opts.payload) ? opts.payload.toString("utf8") : opts.payload;
|
|
228
|
+
const secrets = Array.isArray(opts.secrets) ? opts.secrets : [opts.secrets];
|
|
229
|
+
if (secrets.length === 0) return false;
|
|
230
|
+
if (typeof opts.toleranceSeconds === "number") {
|
|
231
|
+
const now = opts.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
232
|
+
const ts = Number.parseInt(opts.timestamp, 10);
|
|
233
|
+
if (!Number.isFinite(ts) || Math.abs(now - ts) > opts.toleranceSeconds) return false;
|
|
234
|
+
}
|
|
235
|
+
const provided = [normalizeSignature(opts.signatureHeader)];
|
|
236
|
+
if (opts.previousSignatureHeader) provided.push(normalizeSignature(opts.previousSignatureHeader));
|
|
237
|
+
for (const secret of secrets) {
|
|
238
|
+
const expected = computeWebhookSignature(secret, opts.timestamp, rawBody);
|
|
239
|
+
for (const sig of provided) {
|
|
240
|
+
if (timingSafeHexEqual(sig, expected)) return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/resources.ts
|
|
247
|
+
function q(query) {
|
|
248
|
+
return query;
|
|
249
|
+
}
|
|
250
|
+
var Base = class {
|
|
251
|
+
constructor(http) {
|
|
252
|
+
this.http = http;
|
|
253
|
+
}
|
|
254
|
+
req(opts) {
|
|
255
|
+
return this.http.request(opts);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
var Health = class extends Base {
|
|
259
|
+
check() {
|
|
260
|
+
return this.req({ method: "GET", path: "/health" });
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
var Wallets = class extends Base {
|
|
264
|
+
create(body, opts = {}) {
|
|
265
|
+
return this.req({ method: "POST", path: "/wallets", body, ...opts });
|
|
266
|
+
}
|
|
267
|
+
list(query) {
|
|
268
|
+
return this.req({ method: "GET", path: "/wallets", query: q(query) });
|
|
269
|
+
}
|
|
270
|
+
get(id) {
|
|
271
|
+
return this.req({ method: "GET", path: `/wallets/${encodeURIComponent(id)}` });
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
var Customers = class extends Base {
|
|
275
|
+
create(body, opts = {}) {
|
|
276
|
+
return this.req({ method: "POST", path: "/customers", body, ...opts });
|
|
277
|
+
}
|
|
278
|
+
list(query) {
|
|
279
|
+
return this.req({ method: "GET", path: "/customers", query: q(query) });
|
|
280
|
+
}
|
|
281
|
+
get(id) {
|
|
282
|
+
return this.req({ method: "GET", path: `/customers/${encodeURIComponent(id)}` });
|
|
283
|
+
}
|
|
284
|
+
update(id, body) {
|
|
285
|
+
return this.req({ method: "PATCH", path: `/customers/${encodeURIComponent(id)}`, body });
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
var Transactions = class extends Base {
|
|
289
|
+
list(query) {
|
|
290
|
+
return this.req({ method: "GET", path: "/transactions", query: q(query) });
|
|
291
|
+
}
|
|
292
|
+
listDeposits(query) {
|
|
293
|
+
return this.req({ method: "GET", path: "/transactions/deposits", query: q(query) });
|
|
294
|
+
}
|
|
295
|
+
getDeposit(id) {
|
|
296
|
+
return this.req({ method: "GET", path: `/transactions/deposits/${encodeURIComponent(id)}` });
|
|
297
|
+
}
|
|
298
|
+
listWithdrawals(query) {
|
|
299
|
+
return this.req({ method: "GET", path: "/transactions/withdrawals", query: q(query) });
|
|
300
|
+
}
|
|
301
|
+
balances() {
|
|
302
|
+
return this.req({ method: "GET", path: "/transactions/balances" });
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
var Withdrawals = class extends Base {
|
|
306
|
+
create(body, opts = {}) {
|
|
307
|
+
return this.req({ method: "POST", path: "/withdrawals", body, ...opts });
|
|
308
|
+
}
|
|
309
|
+
list(query) {
|
|
310
|
+
return this.req({ method: "GET", path: "/withdrawals", query: q(query) });
|
|
311
|
+
}
|
|
312
|
+
get(id) {
|
|
313
|
+
return this.req({ method: "GET", path: `/withdrawals/${encodeURIComponent(id)}` });
|
|
314
|
+
}
|
|
315
|
+
cancel(id) {
|
|
316
|
+
return this.req({ method: "DELETE", path: `/withdrawals/${encodeURIComponent(id)}` });
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
var Fees = class extends Base {
|
|
320
|
+
quote(body) {
|
|
321
|
+
return this.req({ method: "POST", path: "/fees/quote", body });
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
var Webhooks = class extends Base {
|
|
325
|
+
create(body, opts = {}) {
|
|
326
|
+
return this.req({ method: "POST", path: "/webhooks", body, ...opts });
|
|
327
|
+
}
|
|
328
|
+
list(query) {
|
|
329
|
+
return this.req({ method: "GET", path: "/webhooks", query: q(query) });
|
|
330
|
+
}
|
|
331
|
+
update(id, body) {
|
|
332
|
+
return this.req({ method: "PATCH", path: `/webhooks/${encodeURIComponent(id)}`, body });
|
|
333
|
+
}
|
|
334
|
+
delete(id) {
|
|
335
|
+
return this.req({ method: "DELETE", path: `/webhooks/${encodeURIComponent(id)}` });
|
|
336
|
+
}
|
|
337
|
+
rotateSecret(id) {
|
|
338
|
+
return this.req({ method: "POST", path: `/webhooks/${encodeURIComponent(id)}/rotate-secret` });
|
|
339
|
+
}
|
|
340
|
+
listDeliveries(id, query) {
|
|
341
|
+
return this.req({ method: "GET", path: `/webhooks/${encodeURIComponent(id)}/deliveries`, query: q(query) });
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
var ApiKeys = class extends Base {
|
|
345
|
+
create(body, opts = {}) {
|
|
346
|
+
return this.req({ method: "POST", path: "/api-keys", body, ...opts });
|
|
347
|
+
}
|
|
348
|
+
list(query) {
|
|
349
|
+
return this.req({ method: "GET", path: "/api-keys", query: q(query) });
|
|
350
|
+
}
|
|
351
|
+
revoke(id) {
|
|
352
|
+
return this.req({ method: "DELETE", path: `/api-keys/${encodeURIComponent(id)}` });
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
function buildResources(http) {
|
|
356
|
+
return {
|
|
357
|
+
health: new Health(http),
|
|
358
|
+
wallets: new Wallets(http),
|
|
359
|
+
customers: new Customers(http),
|
|
360
|
+
transactions: new Transactions(http),
|
|
361
|
+
withdrawals: new Withdrawals(http),
|
|
362
|
+
fees: new Fees(http),
|
|
363
|
+
webhooks: new Webhooks(http),
|
|
364
|
+
apiKeys: new ApiKeys(http)
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/index.ts
|
|
369
|
+
var CowriePay = class {
|
|
370
|
+
/** The signed HTTP transport. Every resource method calls through this. */
|
|
371
|
+
http;
|
|
372
|
+
health;
|
|
373
|
+
wallets;
|
|
374
|
+
customers;
|
|
375
|
+
transactions;
|
|
376
|
+
withdrawals;
|
|
377
|
+
fees;
|
|
378
|
+
webhooks;
|
|
379
|
+
apiKeys;
|
|
380
|
+
constructor(config) {
|
|
381
|
+
this.http = new HttpClient(config);
|
|
382
|
+
const r = buildResources(this.http);
|
|
383
|
+
this.health = r.health;
|
|
384
|
+
this.wallets = r.wallets;
|
|
385
|
+
this.customers = r.customers;
|
|
386
|
+
this.transactions = r.transactions;
|
|
387
|
+
this.withdrawals = r.withdrawals;
|
|
388
|
+
this.fees = r.fees;
|
|
389
|
+
this.webhooks = r.webhooks;
|
|
390
|
+
this.apiKeys = r.apiKeys;
|
|
391
|
+
}
|
|
392
|
+
/** Low-level escape hatch: issue a signed request to any `/v2` path. */
|
|
393
|
+
request(opts) {
|
|
394
|
+
return this.http.request(opts);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Verify an incoming webhook against your endpoint secret(s). Pass the RAW request body, the
|
|
398
|
+
* `X-CowriePay-Signature` header, and the `X-CowriePay-Timestamp` header. During a secret rotation,
|
|
399
|
+
* pass both the new and previous secrets.
|
|
400
|
+
*/
|
|
401
|
+
static verifyWebhook(opts) {
|
|
402
|
+
return verifyWebhook(opts);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
var index_default = CowriePay;
|
|
406
|
+
export {
|
|
407
|
+
ApiError,
|
|
408
|
+
AuthenticationError,
|
|
409
|
+
ConnectionError,
|
|
410
|
+
CowriePay,
|
|
411
|
+
CowriePayError,
|
|
412
|
+
InvalidRequestError,
|
|
413
|
+
NotFoundError,
|
|
414
|
+
PermissionError,
|
|
415
|
+
RateLimitError,
|
|
416
|
+
buildAuthHeaders,
|
|
417
|
+
buildRequestSigningString,
|
|
418
|
+
computeWebhookSignature,
|
|
419
|
+
index_default as default,
|
|
420
|
+
sha256Hex,
|
|
421
|
+
signRequest,
|
|
422
|
+
verifyWebhook
|
|
423
|
+
};
|
|
424
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/signer.ts","../src/core/errors.ts","../src/core/client.ts","../src/core/webhooks.ts","../src/resources.ts","../src/index.ts"],"sourcesContent":["import crypto from 'node:crypto';\n\n/**\n * Canonical HMAC request signing for the CowriePay Developer API (`/v2`).\n *\n * This implements the documented CowriePay request-signing recipe (https://docs.cowriepay.io). It is\n * proven identical to the server by the shared golden vectors in `vectors/conformance.json` and,\n * end-to-end, by the sandbox contract test. Do NOT \"improve\" the shape here without updating the\n * published spec and the vectors in lockstep.\n *\n * signing_string = `${timestamp}.${METHOD}.${path}.${bodyHash}`\n * signature = HMAC_SHA256(secret, signing_string) → lowercase hex\n *\n * - timestamp : unix seconds, also sent as `X-CowriePay-Timestamp`; server accepts ±300s.\n * - METHOD : upper-cased HTTP method.\n * - path : the FULL request target exactly as sent, incl. the `/v2` prefix AND query string.\n * - bodyHash : lowercase SHA-256 hex of the RAW body bytes; sha256('') when there is no body.\n */\n\n/** Lowercase SHA-256 hex of a UTF-8 string. */\nexport function sha256Hex(input: string): string {\n return crypto.createHash('sha256').update(input ?? '', 'utf8').digest('hex');\n}\n\n/** Assemble the canonical signing string from an already-hashed body. */\nexport function buildRequestSigningString(params: {\n timestamp: string;\n method: string;\n path: string;\n bodyHash: string;\n}): string {\n const { timestamp, method, path, bodyHash } = params;\n return `${timestamp}.${method.toUpperCase()}.${path}.${bodyHash}`;\n}\n\nexport interface SignedHeaders {\n 'X-CowriePay-Key': string;\n 'X-CowriePay-Timestamp': string;\n 'X-CowriePay-Signature': string;\n}\n\n/** Compute the request signature (lowercase hex) from the raw body string. */\nexport function signRequest(params: {\n secret: string;\n timestamp: string;\n method: string;\n /** Full path incl. `/v2` and query string. */\n path: string;\n /** Raw request body string; '' for no body. */\n rawBody: string;\n}): string {\n const signingString = buildRequestSigningString({\n timestamp: params.timestamp,\n method: params.method,\n path: params.path,\n bodyHash: sha256Hex(params.rawBody ?? ''),\n });\n return crypto.createHmac('sha256', params.secret).update(signingString).digest('hex');\n}\n\n/** Build the three auth headers for a request. `timestamp` defaults to now (unix seconds). */\nexport function buildAuthHeaders(params: {\n apiKey: string;\n secret: string;\n method: string;\n path: string;\n rawBody: string;\n timestamp?: string;\n}): SignedHeaders {\n const timestamp = params.timestamp ?? Math.floor(Date.now() / 1000).toString();\n const signature = signRequest({\n secret: params.secret,\n timestamp,\n method: params.method,\n path: params.path,\n rawBody: params.rawBody,\n });\n return {\n 'X-CowriePay-Key': params.apiKey,\n 'X-CowriePay-Timestamp': timestamp,\n 'X-CowriePay-Signature': signature,\n };\n}\n","/**\n * Typed errors mapped from the CowriePay error envelope: { \"error\": { \"code\", \"message\", ... } }\n * (cowriepay-core `Error` schema). One base class carries the machine-readable `code` + HTTP status;\n * a few subclasses exist for the codes callers most often branch on.\n */\n\nexport interface CowriePayErrorBody {\n error?: { code?: string; message?: string; [k: string]: unknown };\n}\n\nexport class CowriePayError extends Error {\n /** Machine-readable error code from the envelope (e.g. `INVALID_SIGNATURE`), or a synthetic one. */\n readonly code: string;\n /** HTTP status, or 0 for transport/connection errors. */\n readonly status: number;\n /** The `X-CowriePay-Request-Id` / delivery id, when present, for support. */\n readonly requestId?: string;\n /** The parsed response body, when there was one. */\n readonly body?: CowriePayErrorBody;\n\n constructor(params: {\n message: string;\n code: string;\n status: number;\n requestId?: string;\n body?: CowriePayErrorBody;\n }) {\n super(params.message);\n this.name = new.target.name;\n this.code = params.code;\n this.status = params.status;\n this.requestId = params.requestId;\n this.body = params.body;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401: signing/auth problem (INVALID_SIGNATURE, TIMESTAMP_EXPIRED, REPLAY_DETECTED, MISSING_AUTH_HEADERS). */\nexport class AuthenticationError extends CowriePayError {}\n/** 403: the API key lacks the required scope (INSUFFICIENT_SCOPE). */\nexport class PermissionError extends CowriePayError {}\n/** 404: not found, or a feature disabled for the workspace (FEATURE_NOT_AVAILABLE, NOT_FOUND). */\nexport class NotFoundError extends CowriePayError {}\n/** 409 / 422 idempotency conflicts (IDEMPOTENCY_CONFLICT, IDEMPOTENCY_MISMATCH) and other 4xx. */\nexport class InvalidRequestError extends CowriePayError {}\n/** 429: rate limited. */\nexport class RateLimitError extends CowriePayError {}\n/** 5xx: server-side error (retryable). */\nexport class ApiError extends CowriePayError {}\n/** Network/transport failure before any HTTP status (retryable). status = 0. */\nexport class ConnectionError extends CowriePayError {}\n\n/** Build the right typed error from an HTTP status + parsed body. */\nexport function errorFromResponse(\n status: number,\n body: CowriePayErrorBody | undefined,\n requestId?: string,\n): CowriePayError {\n const code = body?.error?.code ?? httpFallbackCode(status);\n const message = body?.error?.message ?? `CowriePay API error (HTTP ${status})`;\n const params = { message, code, status, requestId, body };\n if (status === 401) return new AuthenticationError(params);\n if (status === 403) return new PermissionError(params);\n if (status === 404) return new NotFoundError(params);\n if (status === 429) return new RateLimitError(params);\n if (status >= 500) return new ApiError(params);\n return new InvalidRequestError(params);\n}\n\nfunction httpFallbackCode(status: number): string {\n if (status === 401) return 'UNAUTHORIZED';\n if (status === 403) return 'FORBIDDEN';\n if (status === 404) return 'NOT_FOUND';\n if (status === 429) return 'RATE_LIMITED';\n if (status >= 500) return 'SERVER_ERROR';\n return 'BAD_REQUEST';\n}\n","import { buildAuthHeaders } from './signer.js';\nimport { CowriePayError, ConnectionError, errorFromResponse } from './errors.js';\n\nconst DEFAULT_BASE_URL = 'https://api.cowriepay.io';\n\nconst API_PREFIX = '/v2';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\nexport interface CowriePayConfig {\n /**\n * Public API key id: `cpk_live_...` (Live / mainnet) or `cpk_test_...` (Sandbox / testnet). The key\n * selects the network on the server; there is a single base URL for both, you never switch hosts to\n * test. Swap the prefix to go from Sandbox to Live.\n */\n apiKey: string;\n /** The API key secret. Never logged. */\n apiSecret: string;\n /**\n * Base URL override (e.g. a dev host `https://api-dev.cowriepay.io`). Defaults to\n * `https://api.cowriepay.io` for both Sandbox and Live.\n */\n baseUrl?: string;\n /** Per-request timeout in ms (default 30_000). */\n timeoutMs?: number;\n /** Max automatic retries for idempotent/keyed requests on 429/5xx/network (default 2). */\n maxRetries?: number;\n /** Base backoff in ms; delay ≈ min(base·2^attempt, 8000) + jitter (default 1000). */\n retryBaseMs?: number;\n /** Injectable fetch (tests); defaults to global fetch (Node 18+). */\n fetch?: typeof fetch;\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n /** Resource path WITHOUT the `/v2` prefix, e.g. `/wallets` or `/wallets/${id}`. */\n path: string;\n query?: Record<string, string | number | boolean | undefined | null>;\n body?: unknown;\n /** Idempotency-Key for mutating requests; also makes the request safe to auto-retry. */\n idempotencyKey?: string;\n /** AbortSignal to cancel from the caller. */\n signal?: AbortSignal;\n}\n\nfunction resolveBaseUrl(cfg: CowriePayConfig): string {\n return cfg.baseUrl ? cfg.baseUrl.replace(/\\/$/, '') : DEFAULT_BASE_URL;\n}\n\nfunction encodeQuery(query: RequestOptions['query']): string {\n if (!query) return '';\n const parts: string[] = [];\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);\n }\n return parts.length ? `?${parts.join('&')}` : '';\n}\n\nconst RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);\n\nfunction backoffMs(attempt: number, baseMs: number): number {\n const delay = Math.min(baseMs * 2 ** attempt, 8000);\n return delay + Math.floor(Math.random() * 250); // jitter\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n/**\n * The signed HTTP transport shared by every resource method. Handles: canonical signing (full `/v2`\n * path + query + raw body), JSON encoding, timeouts, typed-error mapping, and safe retries (idempotent\n * methods, or any request carrying an Idempotency-Key).\n */\nexport class HttpClient {\n private readonly cfg: CowriePayConfig;\n private readonly baseUrl: string;\n private readonly doFetch: typeof fetch;\n\n constructor(cfg: CowriePayConfig) {\n if (!cfg.apiKey || !cfg.apiSecret) {\n throw new CowriePayError({ message: 'apiKey and apiSecret are required', code: 'CONFIG_ERROR', status: 0 });\n }\n this.cfg = cfg;\n this.baseUrl = resolveBaseUrl(cfg);\n const f = cfg.fetch ?? globalThis.fetch;\n if (!f) {\n throw new CowriePayError({\n message: 'global fetch is unavailable: use Node 18+ or pass config.fetch',\n code: 'CONFIG_ERROR',\n status: 0,\n });\n }\n this.doFetch = f;\n }\n\n async request<T>(opts: RequestOptions): Promise<T> {\n const fullPath = `${API_PREFIX}${opts.path}${encodeQuery(opts.query)}`;\n const rawBody = opts.body === undefined ? '' : JSON.stringify(opts.body);\n const canRetry = opts.method === 'GET' || Boolean(opts.idempotencyKey);\n const maxRetries = this.cfg.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n let attempt = 0;\n // one initial try + up to maxRetries retries (only when canRetry)\n for (;;) {\n try {\n const res = await this.sendOnce(opts, fullPath, rawBody);\n if (RETRYABLE_STATUS.has(res.status) && canRetry && attempt < maxRetries) {\n attempt += 1;\n await sleep(backoffMs(attempt, this.cfg.retryBaseMs ?? 1000));\n continue;\n }\n return await this.parse<T>(res);\n } catch (err) {\n if (err instanceof CowriePayError) throw err; // already-typed (e.g. parse produced it)\n // transport/network/timeout error\n if (canRetry && attempt < maxRetries) {\n attempt += 1;\n await sleep(backoffMs(attempt, this.cfg.retryBaseMs ?? 1000));\n continue;\n }\n throw new ConnectionError({\n message: `request to ${fullPath} failed: ${(err as Error)?.message ?? String(err)}`,\n code: 'CONNECTION_ERROR',\n status: 0,\n });\n }\n }\n }\n\n private async sendOnce(opts: RequestOptions, fullPath: string, rawBody: string): Promise<Response> {\n const auth = buildAuthHeaders({\n apiKey: this.cfg.apiKey,\n secret: this.cfg.apiSecret,\n method: opts.method,\n path: fullPath,\n rawBody,\n });\n const headers: Record<string, string> = {\n ...auth,\n Accept: 'application/json',\n 'User-Agent': 'cowriepay-node',\n };\n if (opts.body !== undefined) headers['Content-Type'] = 'application/json';\n if (opts.idempotencyKey) headers['Idempotency-Key'] = opts.idempotencyKey;\n\n const timeout = this.cfg.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeout);\n if (opts.signal) opts.signal.addEventListener('abort', () => ac.abort(), { once: true });\n try {\n return await this.doFetch(`${this.baseUrl}${fullPath}`, {\n method: opts.method,\n headers,\n body: opts.body === undefined ? undefined : rawBody,\n signal: ac.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async parse<T>(res: Response): Promise<T> {\n const requestId = res.headers.get('x-cowriepay-request-id') ?? res.headers.get('x-cowriepay-delivery') ?? undefined;\n const text = await res.text();\n const json = text ? safeJson(text) : undefined;\n if (!res.ok) {\n throw errorFromResponse(res.status, json as never, requestId);\n }\n return (json ?? {}) as T;\n }\n}\n\nfunction safeJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return { error: { code: 'INVALID_JSON', message: text.slice(0, 500) } };\n }\n}\n","import crypto from 'node:crypto';\n\n/**\n * Webhook signature verification: implements the documented CowriePay webhook signing scheme\n * (https://docs.cowriepay.io), proven by the shared golden vectors in `vectors/conformance.json`.\n *\n * The server sends, on every delivery:\n * X-CowriePay-Signature: sha256=<hex> (current secret)\n * X-CowriePay-Signature-Previous: sha256=<hex> (previous secret, ONLY during rotation overlap)\n * X-CowriePay-Timestamp: <unix seconds>\n * X-CowriePay-Event: <EVENT_NAME>\n * X-CowriePay-Delivery: <delivery id>\n *\n * where hex = HMAC_SHA256(secret, `${timestamp}.${rawBody}`).\n *\n * Verify against the RAW received body bytes (never a re-serialized object) and use a constant-time\n * comparison. During a secret rotation, pass BOTH the new and previous secrets (or both signature\n * headers) so no delivery is rejected while you roll the secret.\n */\n\nconst PREFIX = 'sha256=';\n\n/** Strip an optional `sha256=` prefix; return the lowercased hex. */\nfunction normalizeSignature(header: string): string {\n const raw = header.startsWith(PREFIX) ? header.slice(PREFIX.length) : header;\n return raw.trim().toLowerCase();\n}\n\n/** Constant-time hex compare (length-safe: unequal lengths short-circuit to false). */\nfunction timingSafeHexEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n const ba = Buffer.from(a, 'utf8');\n const bb = Buffer.from(b, 'utf8');\n // lengths are equal here, so timingSafeEqual is safe\n return crypto.timingSafeEqual(ba, bb);\n}\n\n/** Compute the expected webhook signature hex for a (secret, timestamp, rawBody). */\nexport function computeWebhookSignature(secret: string, timestamp: string, rawBody: string): string {\n return crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody ?? ''}`).digest('hex');\n}\n\nexport interface VerifyWebhookOptions {\n /** The raw request body EXACTLY as received (string or Buffer). */\n payload: string | Buffer;\n /** The `X-CowriePay-Signature` header value (with or without the `sha256=` prefix). */\n signatureHeader: string;\n /** The `X-CowriePay-Timestamp` header value (unix seconds). */\n timestamp: string;\n /**\n * One or more signing secrets to accept. Pass BOTH current and previous during a rotation overlap.\n * A single string is also accepted.\n */\n secrets: string | string[];\n /**\n * Optional: also try the `X-CowriePay-Signature-Previous` header (rotation). Convenience for callers\n * that forward both headers rather than both secrets.\n */\n previousSignatureHeader?: string;\n /**\n * Optional replay guard: reject if `Date.now()` is more than `toleranceSeconds` away from the\n * signed timestamp. Omit to skip the freshness check (verify signature only).\n */\n toleranceSeconds?: number;\n /** Injectable clock (unix seconds) for tests; defaults to real time. */\n nowSeconds?: number;\n}\n\n/**\n * Verify a CowriePay webhook. Returns true iff at least one (secret × provided-signature) pair matches\n * and (when `toleranceSeconds` is set) the timestamp is fresh. Never throws on a bad signature.\n */\nexport function verifyWebhook(opts: VerifyWebhookOptions): boolean {\n const rawBody = Buffer.isBuffer(opts.payload) ? opts.payload.toString('utf8') : opts.payload;\n const secrets = Array.isArray(opts.secrets) ? opts.secrets : [opts.secrets];\n if (secrets.length === 0) return false;\n\n if (typeof opts.toleranceSeconds === 'number') {\n const now = opts.nowSeconds ?? Math.floor(Date.now() / 1000);\n const ts = Number.parseInt(opts.timestamp, 10);\n if (!Number.isFinite(ts) || Math.abs(now - ts) > opts.toleranceSeconds) return false;\n }\n\n const provided = [normalizeSignature(opts.signatureHeader)];\n if (opts.previousSignatureHeader) provided.push(normalizeSignature(opts.previousSignatureHeader));\n\n for (const secret of secrets) {\n const expected = computeWebhookSignature(secret, opts.timestamp, rawBody);\n for (const sig of provided) {\n if (timingSafeHexEqual(sig, expected)) return true;\n }\n }\n return false;\n}\n","import type { HttpClient, RequestOptions } from './core/client.js';\nimport type { components, operations } from './generated/types.js';\n\n// ── Type helpers: derive request/response/query types straight from the generated operations ────────\ntype Op = operations;\ntype JsonOf<T> = T extends { content: { 'application/json': infer B } } ? B : void;\n\n/** The 2xx JSON response body for an operation (void for 204/no-content). */\nexport type Result<K extends keyof Op> = Op[K] extends { responses: infer R }\n ? 200 extends keyof R\n ? JsonOf<R[200]>\n : 201 extends keyof R\n ? JsonOf<R[201]>\n : void\n : void;\n\n/** The JSON request body for an operation. */\nexport type Body<K extends keyof Op> = Op[K] extends { requestBody: { content: { 'application/json': infer B } } }\n ? B\n : Op[K] extends { requestBody?: { content: { 'application/json': infer B } } }\n ? B\n : never;\n\n/** The query parameters for an operation. */\nexport type Query<K extends keyof Op> = Op[K] extends { parameters: { query?: infer Q } }\n ? NonNullable<Q>\n : never;\n\n// Friendly re-exports of the domain schemas (generated from the spec).\nexport type Wallet = components['schemas']['Wallet'];\nexport type WalletDetail = components['schemas']['WalletDetail'];\nexport type Customer = components['schemas']['Customer'];\nexport type Deposit = components['schemas']['Deposit'];\nexport type Withdrawal = components['schemas']['Withdrawal'];\nexport type WithdrawalTransaction = components['schemas']['WithdrawalTransaction'];\nexport type Balance = components['schemas']['Balance'];\nexport type FeeQuote = components['schemas']['FeeQuote'];\nexport type WebhookEndpoint = components['schemas']['WebhookEndpoint'];\nexport type WebhookDelivery = components['schemas']['WebhookDelivery'];\nexport type ApiKey = components['schemas']['ApiKey'];\n\n/** Options accepted by mutating (create) calls. */\nexport interface WriteOptions {\n /** Idempotency-Key: makes the write safe to auto-retry and dedupes duplicate submissions. */\n idempotencyKey?: string;\n signal?: AbortSignal;\n}\n\nfunction q(query: unknown): RequestOptions['query'] {\n return query as RequestOptions['query'];\n}\n\nclass Base {\n constructor(protected readonly http: HttpClient) {}\n protected req<K extends keyof Op>(opts: RequestOptions): Promise<Result<K>> {\n return this.http.request<Result<K>>(opts);\n }\n}\n\n// ── Resources ───────────────────────────────────────────────────────────────────────────────────\nexport class Health extends Base {\n check() {\n return this.req<'getHealth'>({ method: 'GET', path: '/health' });\n }\n}\n\nexport class Wallets extends Base {\n create(body: Body<'createWallet'>, opts: WriteOptions = {}) {\n return this.req<'createWallet'>({ method: 'POST', path: '/wallets', body, ...opts });\n }\n list(query?: Query<'listWallets'>) {\n return this.req<'listWallets'>({ method: 'GET', path: '/wallets', query: q(query) });\n }\n get(id: string) {\n return this.req<'getWallet'>({ method: 'GET', path: `/wallets/${encodeURIComponent(id)}` });\n }\n}\n\nexport class Customers extends Base {\n create(body: Body<'createCustomer'>, opts: WriteOptions = {}) {\n return this.req<'createCustomer'>({ method: 'POST', path: '/customers', body, ...opts });\n }\n list(query?: Query<'listCustomers'>) {\n return this.req<'listCustomers'>({ method: 'GET', path: '/customers', query: q(query) });\n }\n get(id: string) {\n return this.req<'getCustomer'>({ method: 'GET', path: `/customers/${encodeURIComponent(id)}` });\n }\n update(id: string, body: Body<'updateCustomer'>) {\n return this.req<'updateCustomer'>({ method: 'PATCH', path: `/customers/${encodeURIComponent(id)}`, body });\n }\n}\n\nexport class Transactions extends Base {\n list(query?: Query<'listTransactions'>) {\n return this.req<'listTransactions'>({ method: 'GET', path: '/transactions', query: q(query) });\n }\n listDeposits(query?: Query<'listDeposits'>) {\n return this.req<'listDeposits'>({ method: 'GET', path: '/transactions/deposits', query: q(query) });\n }\n getDeposit(id: string) {\n return this.req<'getDeposit'>({ method: 'GET', path: `/transactions/deposits/${encodeURIComponent(id)}` });\n }\n listWithdrawals(query?: Query<'listTransactionWithdrawals'>) {\n return this.req<'listTransactionWithdrawals'>({ method: 'GET', path: '/transactions/withdrawals', query: q(query) });\n }\n balances() {\n return this.req<'getBalances'>({ method: 'GET', path: '/transactions/balances' });\n }\n}\n\nexport class Withdrawals extends Base {\n create(body: Body<'createWithdrawal'>, opts: WriteOptions = {}) {\n return this.req<'createWithdrawal'>({ method: 'POST', path: '/withdrawals', body, ...opts });\n }\n list(query?: Query<'listWithdrawals'>) {\n return this.req<'listWithdrawals'>({ method: 'GET', path: '/withdrawals', query: q(query) });\n }\n get(id: string) {\n return this.req<'getWithdrawal'>({ method: 'GET', path: `/withdrawals/${encodeURIComponent(id)}` });\n }\n cancel(id: string) {\n return this.req<'cancelWithdrawal'>({ method: 'DELETE', path: `/withdrawals/${encodeURIComponent(id)}` });\n }\n}\n\nexport class Fees extends Base {\n quote(body: Body<'quoteFee'>) {\n return this.req<'quoteFee'>({ method: 'POST', path: '/fees/quote', body });\n }\n}\n\nexport class Webhooks extends Base {\n create(body: Body<'createWebhookEndpoint'>, opts: WriteOptions = {}) {\n return this.req<'createWebhookEndpoint'>({ method: 'POST', path: '/webhooks', body, ...opts });\n }\n list(query?: Query<'listWebhookEndpoints'>) {\n return this.req<'listWebhookEndpoints'>({ method: 'GET', path: '/webhooks', query: q(query) });\n }\n update(id: string, body: Body<'updateWebhookEndpoint'>) {\n return this.req<'updateWebhookEndpoint'>({ method: 'PATCH', path: `/webhooks/${encodeURIComponent(id)}`, body });\n }\n delete(id: string) {\n return this.req<'deleteWebhookEndpoint'>({ method: 'DELETE', path: `/webhooks/${encodeURIComponent(id)}` });\n }\n rotateSecret(id: string) {\n return this.req<'rotateWebhookSecret'>({ method: 'POST', path: `/webhooks/${encodeURIComponent(id)}/rotate-secret` });\n }\n listDeliveries(id: string, query?: Query<'listWebhookDeliveries'>) {\n return this.req<'listWebhookDeliveries'>({ method: 'GET', path: `/webhooks/${encodeURIComponent(id)}/deliveries`, query: q(query) });\n }\n}\n\nexport class ApiKeys extends Base {\n create(body: Body<'createApiKey'>, opts: WriteOptions = {}) {\n return this.req<'createApiKey'>({ method: 'POST', path: '/api-keys', body, ...opts });\n }\n list(query?: Query<'listApiKeys'>) {\n return this.req<'listApiKeys'>({ method: 'GET', path: '/api-keys', query: q(query) });\n }\n revoke(id: string) {\n return this.req<'revokeApiKey'>({ method: 'DELETE', path: `/api-keys/${encodeURIComponent(id)}` });\n }\n}\n\n/** All typed resource namespaces, bound to one signed HTTP client. */\nexport interface Resources {\n health: Health;\n wallets: Wallets;\n customers: Customers;\n transactions: Transactions;\n withdrawals: Withdrawals;\n fees: Fees;\n webhooks: Webhooks;\n apiKeys: ApiKeys;\n}\n\nexport function buildResources(http: HttpClient): Resources {\n return {\n health: new Health(http),\n wallets: new Wallets(http),\n customers: new Customers(http),\n transactions: new Transactions(http),\n withdrawals: new Withdrawals(http),\n fees: new Fees(http),\n webhooks: new Webhooks(http),\n apiKeys: new ApiKeys(http),\n };\n}\n","import { HttpClient, type CowriePayConfig, type RequestOptions } from './core/client.js';\nimport { verifyWebhook, type VerifyWebhookOptions } from './core/webhooks.js';\nimport {\n buildResources,\n Health,\n Wallets,\n Customers,\n Transactions,\n Withdrawals,\n Fees,\n Webhooks,\n ApiKeys,\n} from './resources.js';\n\nexport { verifyWebhook } from './core/webhooks.js';\nexport type { VerifyWebhookOptions } from './core/webhooks.js';\nexport { computeWebhookSignature } from './core/webhooks.js';\nexport { signRequest, buildAuthHeaders, sha256Hex, buildRequestSigningString } from './core/signer.js';\nexport type { SignedHeaders } from './core/signer.js';\nexport type { CowriePayConfig, RequestOptions } from './core/client.js';\nexport {\n CowriePayError,\n AuthenticationError,\n PermissionError,\n NotFoundError,\n InvalidRequestError,\n RateLimitError,\n ApiError,\n ConnectionError,\n} from './core/errors.js';\nexport type {\n Wallet,\n WalletDetail,\n Customer,\n Deposit,\n Withdrawal,\n WithdrawalTransaction,\n Balance,\n FeeQuote,\n WebhookEndpoint,\n WebhookDelivery,\n ApiKey,\n WriteOptions,\n Resources,\n Result,\n Body,\n Query,\n} from './resources.js';\nexport type { components, operations, paths } from './generated/types.js';\n\n/**\n * The CowriePay Developer API client.\n *\n * ```ts\n * import { CowriePay } from '@cowriepay/sdk';\n * const cowriepay = new CowriePay({ apiKey: process.env.CPK_KEY!, apiSecret: process.env.CPK_SECRET! });\n * // Same base URL for Sandbox and Live; the key selects the network server-side\n * // (cpk_test_ -> testnet/Sandbox, cpk_live_ -> mainnet/Live).\n * ```\n *\n * Typed resource namespaces are attached: `cowriepay.wallets.create(...)`,\n * `cowriepay.withdrawals.list(...)`, `cowriepay.transactions.balances()`, etc.\n */\nexport class CowriePay {\n /** The signed HTTP transport. Every resource method calls through this. */\n readonly http: HttpClient;\n\n readonly health: Health;\n readonly wallets: Wallets;\n readonly customers: Customers;\n readonly transactions: Transactions;\n readonly withdrawals: Withdrawals;\n readonly fees: Fees;\n readonly webhooks: Webhooks;\n readonly apiKeys: ApiKeys;\n\n constructor(config: CowriePayConfig) {\n this.http = new HttpClient(config);\n const r = buildResources(this.http);\n this.health = r.health;\n this.wallets = r.wallets;\n this.customers = r.customers;\n this.transactions = r.transactions;\n this.withdrawals = r.withdrawals;\n this.fees = r.fees;\n this.webhooks = r.webhooks;\n this.apiKeys = r.apiKeys;\n }\n\n /** Low-level escape hatch: issue a signed request to any `/v2` path. */\n request<T = unknown>(opts: RequestOptions): Promise<T> {\n return this.http.request<T>(opts);\n }\n\n /**\n * Verify an incoming webhook against your endpoint secret(s). Pass the RAW request body, the\n * `X-CowriePay-Signature` header, and the `X-CowriePay-Timestamp` header. During a secret rotation,\n * pass both the new and previous secrets.\n */\n static verifyWebhook(opts: VerifyWebhookOptions): boolean {\n return verifyWebhook(opts);\n }\n}\n\nexport default CowriePay;\n"],"mappings":"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","names":["crypto"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cowriepay/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official CowriePay Node/TypeScript SDK: signed Developer API client + webhook verification.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"module": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"gen:types": "openapi-typescript ../../spec/openapi.yaml -o src/generated/types.ts",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^22.9.0",
|
|
35
|
+
"openapi-typescript": "^7.4.0",
|
|
36
|
+
"tsup": "^8.3.0",
|
|
37
|
+
"typescript": "^5.6.0",
|
|
38
|
+
"vitest": "^4.1.9"
|
|
39
|
+
},
|
|
40
|
+
"overrides": {
|
|
41
|
+
"esbuild": "^0.25.0"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://gitlab.com/cowriex_com_public/cowriepay-sdks#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://gitlab.com/cowriex_com_public/cowriepay-sdks/-/issues"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://gitlab.com/cowriex_com_public/cowriepay-sdks.git"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"cowriepay",
|
|
56
|
+
"stablecoin",
|
|
57
|
+
"wallet-as-a-service",
|
|
58
|
+
"waas",
|
|
59
|
+
"payments",
|
|
60
|
+
"usdt",
|
|
61
|
+
"tron",
|
|
62
|
+
"africa"
|
|
63
|
+
]
|
|
64
|
+
}
|