@orangecheck/me-client 0.8.1 → 0.11.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/dist/index.d.mts CHANGED
@@ -1,6 +1,28 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
 
4
+ type Scope = 'bitcoin_address' | 'email' | 'attest_tier' | 'display_name';
5
+ interface GrantedOptions {
6
+ project_key: string;
7
+ signal?: AbortSignal;
8
+ }
9
+ interface GrantedResult {
10
+ sub: string;
11
+ scopes_granted: Scope[];
12
+ scopes: Partial<Record<Scope, string>>;
13
+ }
14
+ declare function granted(options: GrantedOptions): Promise<GrantedResult>;
15
+ interface RequestOptions {
16
+ project_key: string;
17
+ return_to: string;
18
+ origin?: string;
19
+ }
20
+ declare function request(scopes: Scope[], options: RequestOptions): never;
21
+ declare const scope: {
22
+ granted: typeof granted;
23
+ request: typeof request;
24
+ };
25
+
4
26
  interface VerifyResult {
5
27
  ok: boolean;
6
28
  reason?: string;
@@ -18,10 +40,10 @@ interface VerifyOptions {
18
40
  jwk?: OcPublicJwk;
19
41
  jwksCacheTtlMs?: number;
20
42
  }
21
- declare function verify(rawBody: string | Uint8Array, sigHex: string, kid: string, options?: VerifyOptions): Promise<VerifyResult>;
43
+ declare function verify$1(rawBody: string | Uint8Array, sigHex: string, kid: string, options?: VerifyOptions): Promise<VerifyResult>;
22
44
  declare function fetchJwksForce(issuer?: string): Promise<void>;
23
45
  declare const webhook: {
24
- verify: typeof verify;
46
+ verify: typeof verify$1;
25
47
  fetchJwks: typeof fetchJwksForce;
26
48
  };
27
49
 
@@ -152,8 +174,57 @@ interface FireEventOptions {
152
174
  metadata?: Record<string, unknown>;
153
175
  }
154
176
  declare function fire(options: FireEventOptions): Promise<BillableEvent>;
177
+ interface BatchEventInput {
178
+ subtype: EventSubtype;
179
+ payment_amount_sats?: number;
180
+ action_label?: string;
181
+ note?: string;
182
+ idempotency_key?: string;
183
+ }
184
+ type BatchEventResult = {
185
+ index: number;
186
+ status: 'recorded';
187
+ event: BillableEvent;
188
+ } | {
189
+ index: number;
190
+ status: 'duplicate';
191
+ event: BillableEvent;
192
+ } | {
193
+ index: number;
194
+ status: 'rejected';
195
+ reason: string;
196
+ };
197
+ interface FireBatchOptions {
198
+ project_key: string;
199
+ events: BatchEventInput[];
200
+ }
201
+ interface FireBatchResponse {
202
+ ok: boolean;
203
+ results: BatchEventResult[];
204
+ escrow_mode: 'simulation' | 'live';
205
+ simulation_mode_note?: string;
206
+ }
207
+ declare function fireBatch(options: FireBatchOptions): Promise<FireBatchResponse>;
208
+ interface VerifyEventResult {
209
+ ok: boolean;
210
+ issues: Array<{
211
+ field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing';
212
+ expected: number | null;
213
+ actual: number | null;
214
+ message: string;
215
+ }>;
216
+ expected: {
217
+ gross_fee_sats: number;
218
+ platform_fee_sats: number;
219
+ user_earned_sats: number;
220
+ site_rebate_sats: number;
221
+ } | null;
222
+ }
223
+ declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number): VerifyEventResult;
155
224
  declare const event: {
156
225
  fire: typeof fire;
226
+ fireBatch: typeof fireBatch;
227
+ verify: typeof verify;
157
228
  };
158
229
 
159
230
  interface OcSignInButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onError'> {
@@ -218,12 +289,14 @@ declare const oc: {
218
289
  };
219
290
  event: {
220
291
  fire: (options: FireEventOptions) => Promise<BillableEvent>;
292
+ fireBatch: (options: FireBatchOptions) => Promise<FireBatchResponse>;
293
+ verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number) => VerifyEventResult;
221
294
  };
222
295
  config: {
223
296
  validate: (cfg: IntegratorPriceConfig) => ValidationResult;
224
297
  };
225
298
  webhook: {
226
- verify: typeof verify;
299
+ verify: typeof verify$1;
227
300
  fetchJwks: typeof fetchJwksForce;
228
301
  };
229
302
  federations: {
@@ -232,6 +305,10 @@ declare const oc: {
232
305
  get: (slug: string) => Promise<Federation | null>;
233
306
  defaultLive: () => Promise<Federation | null>;
234
307
  };
308
+ scope: {
309
+ granted: (options: GrantedOptions) => Promise<GrantedResult>;
310
+ request: typeof request;
311
+ };
235
312
  };
236
313
 
237
- export { type AttestTier, type BillableEvent, type ClassASubtype, type ClassBSubtype, type ClassCSubtype, type ComputedFees, type EventClass, type EventSubtype, type Federation, type FederationStatus, type FireEventOptions, type IntegratorEventConfig, type IntegratorPriceConfig, MIN_INTEGRATOR_PRICE_SATS, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PLATFORM_FEE_POLICY, type PaymentAuthorizeOptions, type PaymentResult, type Session, type SessionPolicy, type SignInOptions, type SigningMethod, type SiteFeeShape, type TelemetryEvent, type ValidationResult, type VerifyOptions, type VerifyResult, clearBearerToken, computeFees, config, event, federations, getBearerToken, getOrigin, oc, onTelemetry, payment, session, setBearerToken, setOrigin, validateIntegratorConfig, webhook };
314
+ export { type AttestTier, type BillableEvent, type ClassASubtype, type ClassBSubtype, type ClassCSubtype, type ComputedFees, type EventClass, type EventSubtype, type Federation, type FederationStatus, type FireEventOptions, type GrantedOptions, type GrantedResult, type IntegratorEventConfig, type IntegratorPriceConfig, MIN_INTEGRATOR_PRICE_SATS, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PLATFORM_FEE_POLICY, type PaymentAuthorizeOptions, type PaymentResult, type RequestOptions, type Scope, type Session, type SessionPolicy, type SignInOptions, type SigningMethod, type SiteFeeShape, type TelemetryEvent, type ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, clearBearerToken, computeFees, config, event, federations, getBearerToken, getOrigin, oc, onTelemetry, payment, scope, session, setBearerToken, setOrigin, validateIntegratorConfig, webhook };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,28 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
 
4
+ type Scope = 'bitcoin_address' | 'email' | 'attest_tier' | 'display_name';
5
+ interface GrantedOptions {
6
+ project_key: string;
7
+ signal?: AbortSignal;
8
+ }
9
+ interface GrantedResult {
10
+ sub: string;
11
+ scopes_granted: Scope[];
12
+ scopes: Partial<Record<Scope, string>>;
13
+ }
14
+ declare function granted(options: GrantedOptions): Promise<GrantedResult>;
15
+ interface RequestOptions {
16
+ project_key: string;
17
+ return_to: string;
18
+ origin?: string;
19
+ }
20
+ declare function request(scopes: Scope[], options: RequestOptions): never;
21
+ declare const scope: {
22
+ granted: typeof granted;
23
+ request: typeof request;
24
+ };
25
+
4
26
  interface VerifyResult {
5
27
  ok: boolean;
6
28
  reason?: string;
@@ -18,10 +40,10 @@ interface VerifyOptions {
18
40
  jwk?: OcPublicJwk;
19
41
  jwksCacheTtlMs?: number;
20
42
  }
21
- declare function verify(rawBody: string | Uint8Array, sigHex: string, kid: string, options?: VerifyOptions): Promise<VerifyResult>;
43
+ declare function verify$1(rawBody: string | Uint8Array, sigHex: string, kid: string, options?: VerifyOptions): Promise<VerifyResult>;
22
44
  declare function fetchJwksForce(issuer?: string): Promise<void>;
23
45
  declare const webhook: {
24
- verify: typeof verify;
46
+ verify: typeof verify$1;
25
47
  fetchJwks: typeof fetchJwksForce;
26
48
  };
27
49
 
@@ -152,8 +174,57 @@ interface FireEventOptions {
152
174
  metadata?: Record<string, unknown>;
153
175
  }
154
176
  declare function fire(options: FireEventOptions): Promise<BillableEvent>;
177
+ interface BatchEventInput {
178
+ subtype: EventSubtype;
179
+ payment_amount_sats?: number;
180
+ action_label?: string;
181
+ note?: string;
182
+ idempotency_key?: string;
183
+ }
184
+ type BatchEventResult = {
185
+ index: number;
186
+ status: 'recorded';
187
+ event: BillableEvent;
188
+ } | {
189
+ index: number;
190
+ status: 'duplicate';
191
+ event: BillableEvent;
192
+ } | {
193
+ index: number;
194
+ status: 'rejected';
195
+ reason: string;
196
+ };
197
+ interface FireBatchOptions {
198
+ project_key: string;
199
+ events: BatchEventInput[];
200
+ }
201
+ interface FireBatchResponse {
202
+ ok: boolean;
203
+ results: BatchEventResult[];
204
+ escrow_mode: 'simulation' | 'live';
205
+ simulation_mode_note?: string;
206
+ }
207
+ declare function fireBatch(options: FireBatchOptions): Promise<FireBatchResponse>;
208
+ interface VerifyEventResult {
209
+ ok: boolean;
210
+ issues: Array<{
211
+ field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing';
212
+ expected: number | null;
213
+ actual: number | null;
214
+ message: string;
215
+ }>;
216
+ expected: {
217
+ gross_fee_sats: number;
218
+ platform_fee_sats: number;
219
+ user_earned_sats: number;
220
+ site_rebate_sats: number;
221
+ } | null;
222
+ }
223
+ declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number): VerifyEventResult;
155
224
  declare const event: {
156
225
  fire: typeof fire;
226
+ fireBatch: typeof fireBatch;
227
+ verify: typeof verify;
157
228
  };
158
229
 
159
230
  interface OcSignInButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onError'> {
@@ -218,12 +289,14 @@ declare const oc: {
218
289
  };
219
290
  event: {
220
291
  fire: (options: FireEventOptions) => Promise<BillableEvent>;
292
+ fireBatch: (options: FireBatchOptions) => Promise<FireBatchResponse>;
293
+ verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number) => VerifyEventResult;
221
294
  };
222
295
  config: {
223
296
  validate: (cfg: IntegratorPriceConfig) => ValidationResult;
224
297
  };
225
298
  webhook: {
226
- verify: typeof verify;
299
+ verify: typeof verify$1;
227
300
  fetchJwks: typeof fetchJwksForce;
228
301
  };
229
302
  federations: {
@@ -232,6 +305,10 @@ declare const oc: {
232
305
  get: (slug: string) => Promise<Federation | null>;
233
306
  defaultLive: () => Promise<Federation | null>;
234
307
  };
308
+ scope: {
309
+ granted: (options: GrantedOptions) => Promise<GrantedResult>;
310
+ request: typeof request;
311
+ };
235
312
  };
236
313
 
237
- export { type AttestTier, type BillableEvent, type ClassASubtype, type ClassBSubtype, type ClassCSubtype, type ComputedFees, type EventClass, type EventSubtype, type Federation, type FederationStatus, type FireEventOptions, type IntegratorEventConfig, type IntegratorPriceConfig, MIN_INTEGRATOR_PRICE_SATS, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PLATFORM_FEE_POLICY, type PaymentAuthorizeOptions, type PaymentResult, type Session, type SessionPolicy, type SignInOptions, type SigningMethod, type SiteFeeShape, type TelemetryEvent, type ValidationResult, type VerifyOptions, type VerifyResult, clearBearerToken, computeFees, config, event, federations, getBearerToken, getOrigin, oc, onTelemetry, payment, session, setBearerToken, setOrigin, validateIntegratorConfig, webhook };
314
+ export { type AttestTier, type BillableEvent, type ClassASubtype, type ClassBSubtype, type ClassCSubtype, type ComputedFees, type EventClass, type EventSubtype, type Federation, type FederationStatus, type FireEventOptions, type GrantedOptions, type GrantedResult, type IntegratorEventConfig, type IntegratorPriceConfig, MIN_INTEGRATOR_PRICE_SATS, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PLATFORM_FEE_POLICY, type PaymentAuthorizeOptions, type PaymentResult, type RequestOptions, type Scope, type Session, type SessionPolicy, type SignInOptions, type SigningMethod, type SiteFeeShape, type TelemetryEvent, type ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, clearBearerToken, computeFees, config, event, federations, getBearerToken, getOrigin, oc, onTelemetry, payment, scope, session, setBearerToken, setOrigin, validateIntegratorConfig, webhook };
package/dist/index.js CHANGED
@@ -131,7 +131,7 @@ async function invalidate(sessionId) {
131
131
  }
132
132
  var session = { create, refresh, invalidate };
133
133
  function OcSignInButton({
134
- scope,
134
+ scope: scope2,
135
135
  sessionPolicy,
136
136
  returnTo,
137
137
  onSignin,
@@ -152,7 +152,7 @@ function OcSignInButton({
152
152
  if (event2.defaultPrevented) return;
153
153
  setPending(true);
154
154
  try {
155
- const result = await session.create({ scope, sessionPolicy, returnTo });
155
+ const result = await session.create({ scope: scope2, sessionPolicy, returnTo });
156
156
  onSignin?.(result);
157
157
  } catch (err) {
158
158
  onSignInError?.(err instanceof Error ? err : new Error(String(err)));
@@ -212,21 +212,6 @@ async function authorize(opts) {
212
212
  }
213
213
  var payment = { authorize };
214
214
 
215
- // src/event.ts
216
- async function fire(options) {
217
- if (!options.project_key) {
218
- throw new Error("event.fire requires project_key");
219
- }
220
- if (!options.subtype) {
221
- throw new Error("event.fire requires subtype");
222
- }
223
- return api("/api/integrator/event", {
224
- method: "POST",
225
- body: options
226
- });
227
- }
228
- var event = { fire };
229
-
230
215
  // src/types.ts
231
216
  var PLATFORM_FEE_POLICY = {
232
217
  /** Fraction of every gross_fee that OC retains. */
@@ -296,6 +281,122 @@ function validateIntegratorConfig(cfg) {
296
281
  return { ok: errors.length === 0, errors };
297
282
  }
298
283
 
284
+ // src/event.ts
285
+ async function fire(options) {
286
+ if (!options.project_key) {
287
+ throw new Error("event.fire requires project_key");
288
+ }
289
+ if (!options.subtype) {
290
+ throw new Error("event.fire requires subtype");
291
+ }
292
+ return api("/api/integrator/event", {
293
+ method: "POST",
294
+ body: options
295
+ });
296
+ }
297
+ async function fireBatch(options) {
298
+ if (!options.project_key) {
299
+ throw new Error("event.fireBatch requires project_key");
300
+ }
301
+ if (!Array.isArray(options.events) || options.events.length === 0) {
302
+ throw new Error("event.fireBatch requires at least one event");
303
+ }
304
+ if (options.events.length > 100) {
305
+ throw new Error(
306
+ `event.fireBatch \xB7 max 100 events per call (got ${options.events.length}). Split client-side.`
307
+ );
308
+ }
309
+ return api("/api/integrator/event/batch", {
310
+ method: "POST",
311
+ body: options
312
+ });
313
+ }
314
+ function verify(envelope, config2, payment_amount_sats) {
315
+ const issues = [];
316
+ const eventCfg = config2.events[envelope.subtype];
317
+ if (!eventCfg) {
318
+ return {
319
+ ok: false,
320
+ expected: null,
321
+ issues: [
322
+ {
323
+ field: "subtype_unconfigured",
324
+ expected: null,
325
+ actual: null,
326
+ message: `subtype ${envelope.subtype} is not configured on integrator ${config2.project_key}`
327
+ }
328
+ ]
329
+ };
330
+ }
331
+ if (!eventCfg.enabled) {
332
+ return {
333
+ ok: false,
334
+ expected: null,
335
+ issues: [
336
+ {
337
+ field: "subtype_disabled",
338
+ expected: null,
339
+ actual: null,
340
+ message: `subtype ${envelope.subtype} is disabled on integrator ${config2.project_key} but the envelope was billed`
341
+ }
342
+ ]
343
+ };
344
+ }
345
+ if (eventCfg.site_pays.kind === "percent_of_amount" && payment_amount_sats == null) {
346
+ return {
347
+ ok: false,
348
+ expected: null,
349
+ issues: [
350
+ {
351
+ field: "percent_amount_missing",
352
+ expected: null,
353
+ actual: null,
354
+ message: `subtype ${envelope.subtype} is percent_of_amount-priced; payment_amount_sats is required to verify`
355
+ }
356
+ ]
357
+ };
358
+ }
359
+ const expected = computeFees(eventCfg, payment_amount_sats);
360
+ if (envelope.gross_fee_sats !== expected.gross_fee_sats) {
361
+ issues.push({
362
+ field: "gross_fee_sats",
363
+ expected: expected.gross_fee_sats,
364
+ actual: envelope.gross_fee_sats,
365
+ message: `gross_fee_sats mismatch \xB7 expected ${expected.gross_fee_sats}, recorded ${envelope.gross_fee_sats}`
366
+ });
367
+ }
368
+ if (envelope.platform_fee_sats !== expected.platform_fee_sats) {
369
+ issues.push({
370
+ field: "platform_fee_sats",
371
+ expected: expected.platform_fee_sats,
372
+ actual: envelope.platform_fee_sats,
373
+ message: `platform_fee_sats mismatch \xB7 expected ${expected.platform_fee_sats}, recorded ${envelope.platform_fee_sats}`
374
+ });
375
+ }
376
+ if (envelope.user_earned_sats !== expected.user_earned_sats) {
377
+ issues.push({
378
+ field: "user_earned_sats",
379
+ expected: expected.user_earned_sats,
380
+ actual: envelope.user_earned_sats,
381
+ message: `user_earned_sats mismatch \xB7 expected ${expected.user_earned_sats}, recorded ${envelope.user_earned_sats}`
382
+ });
383
+ }
384
+ if (envelope.site_rebate_sats !== expected.site_rebate_sats) {
385
+ issues.push({
386
+ field: "site_rebate_sats",
387
+ expected: expected.site_rebate_sats,
388
+ actual: envelope.site_rebate_sats,
389
+ message: `site_rebate_sats mismatch \xB7 expected ${expected.site_rebate_sats}, recorded ${envelope.site_rebate_sats}`
390
+ });
391
+ }
392
+ return {
393
+ ok: issues.length === 0,
394
+ expected,
395
+ issues
396
+ };
397
+ }
398
+ var event = { fire, fireBatch, verify };
399
+
299
400
  // src/config.ts
300
401
  function validate(cfg) {
301
402
  return validateIntegratorConfig(cfg);
@@ -600,7 +701,7 @@ async function verifyEd25519(key, sig, msg) {
600
701
  return false;
601
702
  }
602
703
  }
603
- async function verify(rawBody, sigHex, kid, options = {}) {
704
+ async function verify2(rawBody, sigHex, kid, options = {}) {
604
705
  if (!sigHex) return { ok: false, reason: "missing signature" };
605
706
  if (!kid) return { ok: false, reason: "missing kid" };
606
707
  const sig = hexToBytes(sigHex);
@@ -639,7 +740,7 @@ async function fetchJwksForce(issuer = DEFAULT_ISSUER) {
639
740
  jwksCache.delete(issuer);
640
741
  await fetchJwks(issuer, DEFAULT_TTL_MS);
641
742
  }
642
- var webhook = { verify, fetchJwks: fetchJwksForce };
743
+ var webhook = { verify: verify2, fetchJwks: fetchJwksForce };
643
744
 
644
745
  // src/federations.ts
645
746
  async function list() {
@@ -660,8 +761,59 @@ async function defaultLive() {
660
761
  }
661
762
  var federations = { list, live, get, defaultLive };
662
763
 
764
+ // src/scope.ts
765
+ var VALID_SCOPES = [
766
+ "bitcoin_address",
767
+ "email",
768
+ "attest_tier",
769
+ "display_name"
770
+ ];
771
+ async function granted(options) {
772
+ if (!options.project_key) {
773
+ throw new Error("oc.scope.granted: project_key is required");
774
+ }
775
+ const r = await api(
776
+ `/api/integrator/scopes/${encodeURIComponent(options.project_key)}`,
777
+ { method: "GET", signal: options.signal }
778
+ );
779
+ return {
780
+ sub: r.sub,
781
+ scopes_granted: r.scopes_granted,
782
+ scopes: r.scopes
783
+ };
784
+ }
785
+ function request(scopes, options) {
786
+ if (!options.project_key) {
787
+ throw new Error("oc.scope.request: project_key is required");
788
+ }
789
+ if (!options.return_to) {
790
+ throw new Error("oc.scope.request: return_to is required");
791
+ }
792
+ if (!Array.isArray(scopes) || scopes.length === 0) {
793
+ throw new Error("oc.scope.request: scopes must be a non-empty array");
794
+ }
795
+ for (const s of scopes) {
796
+ if (!VALID_SCOPES.includes(s)) {
797
+ throw new Error(
798
+ `oc.scope.request: unknown scope "${s}" \xB7 valid: ${VALID_SCOPES.join(", ")}`
799
+ );
800
+ }
801
+ }
802
+ if (typeof window === "undefined") {
803
+ throw new Error("oc.scope.request: must be called in a browser environment");
804
+ }
805
+ const origin2 = options.origin ?? getOrigin();
806
+ const url = new URL("/me/scope-grant", origin2);
807
+ url.searchParams.set("project_key", options.project_key);
808
+ url.searchParams.set("scopes", scopes.join(","));
809
+ url.searchParams.set("return_to", options.return_to);
810
+ window.location.assign(url.toString());
811
+ throw new Error("oc.scope.request: redirected to consent prompt");
812
+ }
813
+ var scope = { granted, request };
814
+
663
815
  // src/index.ts
664
- var oc = { session, payment, event, config, webhook, federations };
816
+ var oc = { session, payment, event, config, webhook, federations, scope };
665
817
 
666
818
  exports.MIN_INTEGRATOR_PRICE_SATS = MIN_INTEGRATOR_PRICE_SATS;
667
819
  exports.MeClientError = MeClientError;
@@ -677,6 +829,7 @@ exports.getOrigin = getOrigin;
677
829
  exports.oc = oc;
678
830
  exports.onTelemetry = onTelemetry;
679
831
  exports.payment = payment;
832
+ exports.scope = scope;
680
833
  exports.session = session;
681
834
  exports.setBearerToken = setBearerToken;
682
835
  exports.setOrigin = setOrigin;