@keldra/sdk 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  TypeScript SDK for the Keldra relay API.
4
4
 
5
+ ## Security
6
+
7
+ - Use this SDK with a server-side API key only.
8
+ - Never ship `kk_...` keys in browser/client bundles.
9
+ - Keep `KELDRA_API_KEY` in backend environment variables.
10
+
5
11
  ## Install
6
12
 
7
13
  ```bash
@@ -26,7 +32,7 @@ npm install @keldra/sdk viem
26
32
  ```ts
27
33
  import { KeldraClient } from "@keldra/sdk";
28
34
 
29
- const client = KeldraClient.create("kk_your_api_key");
35
+ const client = KeldraClient.fromEnv();
30
36
  const result = await client.relay("ethereum", signedTxHex);
31
37
  const limits = await client.limits();
32
38
  const usage = await client.usage("2026-02-01", "2026-02-20");
@@ -52,6 +58,32 @@ import { KeldraClient } from "@keldra/sdk";
52
58
  const client = KeldraClient.fromEnv();
53
59
  ```
54
60
 
61
+ ## Backend Proxy Example (Next.js)
62
+
63
+ Keep Keldra calls on your server route:
64
+
65
+ ```ts
66
+ // app/api/relay/route.ts
67
+ import { NextRequest, NextResponse } from "next/server";
68
+ import { KeldraClient } from "@keldra/sdk";
69
+
70
+ const client = KeldraClient.fromEnv();
71
+
72
+ export async function POST(req: NextRequest) {
73
+ const body = await req.json();
74
+ const { chain, signedTx } = body as { chain: "ethereum"; signedTx: string };
75
+
76
+ if (!chain || !signedTx) {
77
+ return NextResponse.json({ error: "chain and signedTx are required" }, { status: 400 });
78
+ }
79
+
80
+ const relay = await client.relay(chain, signedTx);
81
+ return NextResponse.json(relay);
82
+ }
83
+ ```
84
+
85
+ Frontend calls your backend endpoint, not Keldra directly.
86
+
55
87
  ## Encrypted Transport
56
88
 
57
89
  ```ts
package/dist/index.cjs CHANGED
@@ -166,6 +166,9 @@ var DEFAULT_POLL_INTERVAL_MS = 2e3;
166
166
  var MAX_POLL_INTERVAL_MS = 15e3;
167
167
  var DEFAULT_API_KEY_ENV = "KELDRA_API_KEY";
168
168
  var DEFAULT_GATEWAY_ENV = "KELDRA_GATEWAY_URL";
169
+ function isBrowserRuntime() {
170
+ return typeof window !== "undefined" && typeof document !== "undefined";
171
+ }
169
172
  var KeldraClient = class _KeldraClient {
170
173
 
171
174
 
@@ -179,6 +182,11 @@ var KeldraClient = class _KeldraClient {
179
182
  if (!config.apiKey) {
180
183
  throw KeldraError.config("apiKey is required");
181
184
  }
185
+ if (isBrowserRuntime() && config.apiKey.startsWith("kk_")) {
186
+ throw KeldraError.config(
187
+ "Do not use a Keldra API key in browser code. Move SDK calls to your backend."
188
+ );
189
+ }
182
190
  this.http = new HttpClient(config.apiKey);
183
191
  this.gatewayUrl = (_nullishCoalesce(config.gatewayUrl, () => ( DEFAULT_GATEWAY_URL))).replace(
184
192
  /\/$/,
@@ -195,6 +203,11 @@ var KeldraClient = class _KeldraClient {
195
203
  return new _KeldraClient({ apiKey });
196
204
  }
197
205
  static fromEnv(env = _nullishCoalesce(_optionalChain([globalThis, 'access', _2 => _2.process, 'optionalAccess', _3 => _3.env]), () => ( {})), options) {
206
+ if (isBrowserRuntime()) {
207
+ throw KeldraError.config(
208
+ "KeldraClient.fromEnv() is server-only. Load KELDRA_API_KEY on your backend."
209
+ );
210
+ }
198
211
  const apiKeyName = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.apiKeyEnv]), () => ( DEFAULT_API_KEY_ENV));
199
212
  const gatewayUrlName = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.gatewayUrlEnv]), () => ( DEFAULT_GATEWAY_ENV));
200
213
  const apiKey = env[apiKeyName];
package/dist/index.js CHANGED
@@ -166,6 +166,9 @@ var DEFAULT_POLL_INTERVAL_MS = 2e3;
166
166
  var MAX_POLL_INTERVAL_MS = 15e3;
167
167
  var DEFAULT_API_KEY_ENV = "KELDRA_API_KEY";
168
168
  var DEFAULT_GATEWAY_ENV = "KELDRA_GATEWAY_URL";
169
+ function isBrowserRuntime() {
170
+ return typeof window !== "undefined" && typeof document !== "undefined";
171
+ }
169
172
  var KeldraClient = class _KeldraClient {
170
173
  http;
171
174
  gatewayUrl;
@@ -179,6 +182,11 @@ var KeldraClient = class _KeldraClient {
179
182
  if (!config.apiKey) {
180
183
  throw KeldraError.config("apiKey is required");
181
184
  }
185
+ if (isBrowserRuntime() && config.apiKey.startsWith("kk_")) {
186
+ throw KeldraError.config(
187
+ "Do not use a Keldra API key in browser code. Move SDK calls to your backend."
188
+ );
189
+ }
182
190
  this.http = new HttpClient(config.apiKey);
183
191
  this.gatewayUrl = (config.gatewayUrl ?? DEFAULT_GATEWAY_URL).replace(
184
192
  /\/$/,
@@ -195,6 +203,11 @@ var KeldraClient = class _KeldraClient {
195
203
  return new _KeldraClient({ apiKey });
196
204
  }
197
205
  static fromEnv(env = globalThis.process?.env ?? {}, options) {
206
+ if (isBrowserRuntime()) {
207
+ throw KeldraError.config(
208
+ "KeldraClient.fromEnv() is server-only. Load KELDRA_API_KEY on your backend."
209
+ );
210
+ }
198
211
  const apiKeyName = options?.apiKeyEnv ?? DEFAULT_API_KEY_ENV;
199
212
  const gatewayUrlName = options?.gatewayUrlEnv ?? DEFAULT_GATEWAY_ENV;
200
213
  const apiKey = env[apiKeyName];
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "@keldra/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "TypeScript SDK for Keldra relay API",
5
5
  "license": "MIT",
6
6
  "author": "Keldra",
7
- "homepage": "https://keldra.network",
7
+ "homepage": "https://github.com/jperth86/keldra-sdk#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/jperth86/keldra-sdk.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/jperth86/keldra-sdk/issues"
14
+ },
8
15
  "keywords": [
9
16
  "keldra",
10
17
  "relay",