@palbase/web 7.3.4 → 7.3.6

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.
@@ -6,8 +6,8 @@ import {
6
6
  import {
7
7
  __configure,
8
8
  getRuntime
9
- } from "../chunk-PYJ3CMA2.js";
10
- import "../chunk-RAP37ILS.js";
9
+ } from "../chunk-SQWG3PTU.js";
10
+ import "../chunk-6DGCUHSO.js";
11
11
  import {
12
12
  environmentRefFromPublishableApiKey
13
13
  } from "../chunk-CFDU23TB.js";
@@ -180,6 +180,28 @@ function asPowChallenge(details) {
180
180
  return { id, prefix, difficulty };
181
181
  }
182
182
  var encoder = new TextEncoder();
183
+ var hasher = null;
184
+ async function digester() {
185
+ if (hasher) return hasher;
186
+ const runtime = globalThis;
187
+ const nodeish = runtime.process?.versions?.node !== void 0 || runtime.process?.versions?.bun !== void 0;
188
+ if (nodeish) {
189
+ try {
190
+ const mod = await import(
191
+ /* @vite-ignore */
192
+ `${"node:"}crypto`
193
+ );
194
+ if (typeof mod.createHash === "function") {
195
+ const createHash = mod.createHash;
196
+ hasher = (input) => new Uint8Array(createHash("sha256").update(input).digest());
197
+ return hasher;
198
+ }
199
+ } catch {
200
+ }
201
+ }
202
+ hasher = async (input) => new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(input)));
203
+ return hasher;
204
+ }
183
205
  var now = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
184
206
  function leadingZeroBits(hash) {
185
207
  let bits = 0;
@@ -196,14 +218,19 @@ var MAX_POW_DIFFICULTY = 24;
196
218
  function powBudget(difficulty) {
197
219
  return 8 * 2 ** difficulty;
198
220
  }
199
- var POW_DEADLINE_MS = 12e4;
221
+ var POW_TIME_BUDGET_MS = 12e4;
222
+ var CALIBRATION_WARMUP = 1024;
223
+ var CALIBRATION_END = 9216;
200
224
  async function solvePowChallenge(challenge, maxIterations = powBudget(challenge.difficulty), signal) {
201
225
  if (challenge.difficulty > MAX_POW_DIFFICULTY) {
202
226
  throw new Error(
203
227
  `proof-of-work: refusing difficulty ${challenge.difficulty}; this client attempts at most ${MAX_POW_DIFFICULTY}, which is the highest a Palbase stack issues`
204
228
  );
205
229
  }
206
- const deadline = now() + POW_DEADLINE_MS;
230
+ const digest = await digester();
231
+ let warmedAt = 0;
232
+ let calibrated = false;
233
+ let deadline = Number.POSITIVE_INFINITY;
207
234
  for (let nonce = 0; nonce < maxIterations; nonce++) {
208
235
  if ((nonce & 1023) === 0) {
209
236
  if (signal?.aborted) {
@@ -211,12 +238,27 @@ async function solvePowChallenge(challenge, maxIterations = powBudget(challenge.
211
238
  }
212
239
  if (now() > deadline) {
213
240
  throw new Error(
214
- `proof-of-work: gave up after ${POW_DEADLINE_MS / 1e3}s at difficulty ${challenge.difficulty} (${nonce} attempts)`
241
+ `proof-of-work: gave up on difficulty ${challenge.difficulty} after ${POW_TIME_BUDGET_MS / 1e3}s and ${nonce.toLocaleString()} attempts \u2014 the tail this run drew is longer than the allowance`
215
242
  );
216
243
  }
217
244
  }
218
- const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
219
- if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
245
+ if (nonce === CALIBRATION_WARMUP) {
246
+ warmedAt = now();
247
+ }
248
+ if (!calibrated && nonce === CALIBRATION_END) {
249
+ calibrated = true;
250
+ const elapsed = Math.max(now() - warmedAt, 1e-3);
251
+ const rate = (CALIBRATION_END - CALIBRATION_WARMUP) / (elapsed / 1e3);
252
+ const expectedMs = 2 ** challenge.difficulty / rate * 1e3;
253
+ if (expectedMs > POW_TIME_BUDGET_MS) {
254
+ throw new Error(
255
+ `proof-of-work: difficulty ${challenge.difficulty} needs about ${Math.round(expectedMs / 1e3)}s here (${Math.round(rate).toLocaleString()} digests/s) and this client allows ${POW_TIME_BUDGET_MS / 1e3}s; refusing before spending the time rather than after`
256
+ );
257
+ }
258
+ deadline = now() + (POW_TIME_BUDGET_MS - (now() - warmedAt));
259
+ }
260
+ const hash = await digest(challenge.prefix + nonce);
261
+ if (leadingZeroBits(hash) >= challenge.difficulty) {
220
262
  return {
221
263
  [POW_CHALLENGE_ID_HEADER]: challenge.id,
222
264
  [POW_NONCE_HEADER]: String(nonce)
@@ -9386,7 +9428,7 @@ function defaultSessionStorage(key) {
9386
9428
  }
9387
9429
 
9388
9430
  // src/version.ts
9389
- var VERSION = "7.3.4";
9431
+ var VERSION = "7.3.6";
9390
9432
 
9391
9433
  // src/runtime.ts
9392
9434
  function buildRuntime(config) {
@@ -9394,15 +9436,11 @@ function buildRuntime(config) {
9394
9436
  if (projectRef === "") {
9395
9437
  throw new Error("PalbeConfig.apiKey does not contain a valid publishable project identity");
9396
9438
  }
9397
- let runtimeURL;
9398
9439
  try {
9399
- runtimeURL = new URL(config.url);
9440
+ new URL(config.url);
9400
9441
  } catch {
9401
9442
  throw new Error("PalbeConfig.url must be a valid URL");
9402
9443
  }
9403
- if (runtimeURL.hostname.endsWith(".palbase.studio") && runtimeURL.hostname.split(".")[0] !== projectRef) {
9404
- throw new Error("PalbeConfig.url must match the project identity in apiKey for palbase.studio");
9405
- }
9406
9444
  const http = new HttpClient(config.apiKey, {
9407
9445
  url: config.url,
9408
9446
  headers: { "X-Client-Info": `palbe-web/${VERSION}`, ...config.headers }