@chaindaddy/js 0.3.0 → 0.3.1

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/api.d.ts CHANGED
@@ -15,8 +15,8 @@ export interface paths {
15
15
  * @description A verified coin page by chain and ticker: its name, token address, registration ID, logo, price,
16
16
  * market cap, 24-hour volume, liquidity, 24-hour price change and holder count. A figure Chain Daddy
17
17
  * does not have is `null`, never `0`. The logo is `null` for a page marked NSFW. Answers 404 for a
18
- * ticker with no verified page on that chain. Keyless, the same for every caller, and cached for
19
- * about a minute.
18
+ * ticker with no verified page on that chain, and for a page Chain Daddy removed. Keyless, the same
19
+ * for every caller, and cached for about a minute.
20
20
  */
21
21
  get: operations["getPublicCoin"];
22
22
  put?: never;
@@ -38,9 +38,10 @@ export interface paths {
38
38
  * List the apps on a verified coin's page
39
39
  * @description The apps a verified coin's page shows, in page order: each app's ID, name, description, version,
40
40
  * category, icon and whether it is a built-in. It names the apps; it does not include what the owner
41
- * set up inside them. Apps turned off are left out, and so is every app rated NSFW. Answers 404 for
42
- * a ticker with no verified page on that chain. Keyless, the same for every caller, and cached for
43
- * about a minute.
41
+ * set up inside them. Apps turned off are left out, and so is every app rated NSFW and every app the
42
+ * page itself no longer shows (not reviewed yet, suspended or removed). Answers 404 for a ticker
43
+ * with no verified page on that chain, and for a page Chain Daddy removed. Keyless, the same for
44
+ * every caller, and cached for about a minute.
44
45
  */
45
46
  get: operations["listPublicCoinApps"];
46
47
  put?: never;
@@ -64,7 +65,8 @@ export interface paths {
64
65
  * smallest unit as a decimal string, and `holds` (whether it is above zero). Use it to re-check a
65
66
  * holding after someone signed in to your site with Chain Daddy, without an API key. Works for any
66
67
  * token on a chain Chain Daddy serves. Each caller gets 60 requests a minute; past that it
67
- * answers 429. Cached for about 30 seconds.
68
+ * answers 429. Cached for about 30 seconds. All callers together share a limit on chain reads:
69
+ * in a busy moment it answers 503 with `Retry-After`.
68
70
  */
69
71
  get: operations["getPublicHolding"];
70
72
  put?: never;
@@ -86,10 +88,11 @@ export interface paths {
86
88
  * List a registration's verified sites
87
89
  * @description The websites a coin's registration has verified with a DNS record. `badgeHosts` show the coin's
88
90
  * verified badge on the Chain Daddy sign-in page. `embedHosts` may also run the coin's apps and take
89
- * its checkout. A host covers its subdomains. `interactive` is `false` when there are no
91
+ * its checkout. A host covers its subdomains, except one Chain Daddy has blocked. `interactive` is `false` when there are no
90
92
  * `embedHosts` or Chain Daddy has turned the coin's embeds off. A registration with no verified
91
- * sites answers 200 with empty lists. Keyless, the same for every caller, and cached for about a
92
- * minute.
93
+ * sites answers 200 with empty lists. Only the registration a verified coin page shows answers
94
+ * (the `crownId` the coin read gives); any other ID answers 404. Keyless, the same for every
95
+ * caller, and cached for about a minute.
93
96
  */
94
97
  get: operations["getPublicCrownSites"];
95
98
  put?: never;
@@ -833,6 +836,12 @@ export interface paths {
833
836
  * A buyer paying a checkout session sends `checkoutSessionId` from their own session on chaindaddy.io. The
834
837
  * session then fixes the store, the SKU, the quantity and `appAccountToken`, so `storeId` and `sku` may be
835
838
  * left out. The amount and the fee are quoted exactly as for any other order of that item.
839
+ *
840
+ * When the session's item belongs to an installed app, the order is that app's order: it pays the page, the
841
+ * fee and the app's developer, needs `acknowledgeFinalSale: true`, and stays inside the app's limits. The app
842
+ * is the item's own; an `appId` sent with a session is ignored. Everything is checked again when the order is
843
+ * made, so a session opened while the item could be sold answers 409 `APP_ITEM_NOT_SOLD_HERE` once its
844
+ * developer turns that off, pauses, or changes the item's terms.
836
845
  */
837
846
  post: operations["createIapOrder"];
838
847
  delete?: never;
@@ -884,8 +893,12 @@ export interface paths {
884
893
  *
885
894
  * `successUrl` and `cancelUrl` must be `https` pages on one of the coin's verified sites, or a subdomain of
886
895
  * one (400 `RETURN_URL_NOT_VERIFIED`, which lists the sites that pass). The wallet that opened the store
887
- * must have signed the Seller Terms (403 `SELLER_TERMS_REQUIRED`). An item that belongs to an installed app
888
- * cannot be sold through a session (409 `SKU_NOT_FOR_SALE`).
896
+ * must have signed the Seller Terms (403 `SELLER_TERMS_REQUIRED`).
897
+ *
898
+ * An item of an app installed on the coin's page (its `sku` starts with `app.`) is sold through a session
899
+ * only when the app's developer has allowed that item to be sold outside the app; otherwise the call answers
900
+ * 409 `APP_ITEM_NOT_SOLD_HERE`, with a `reason`. The sale pays the same wallets as inside the app: the page,
901
+ * the fee and the developer's share. Such a session takes at most the app's per-order quantity.
889
902
  *
890
903
  * Send an `Idempotency-Key`. A retry of the same request returns the session it opened, with status 200
891
904
  * and the header `Idempotent-Replayed: true`.
@@ -946,6 +959,10 @@ export interface paths {
946
959
  * needs no credential (the session id in the buyer's link is enough) and never carries the session's
947
960
  * `metadata` or `clientReferenceId`. The answer is never cached.
948
961
  *
962
+ * When the item belongs to an app installed on the coin's page, `sku` names the app (`appId`) and carries
963
+ * nothing else of the app's: no `appBps`, `appTermsVersion`, `appItemKey` or `appRole`, and an empty
964
+ * `metadata`.
965
+ *
949
966
  * Pass `origin` to learn whether a page on that origin may open this checkout in a popup
950
967
  * (`openerAllowed`): it must be `https` on one of the coin's verified sites.
951
968
  *
@@ -1019,7 +1036,8 @@ export interface paths {
1019
1036
  * List the event types a webhook can subscribe to
1020
1037
  * @description Returns every subscribable event type with a one-line description: registration, heartbeat, holder, trade
1021
1038
  * and alert events, API quota events, deal lifecycle events (`deal.created`, `deal.accepted`,
1022
- * `deal.rejected`, `deal.cancelled`, `deal.completed`, `deal.failed`) and creator-store events (`iap.*`).
1039
+ * `deal.rejected`, `deal.cancelled`, `deal.completed`, `deal.failed`), creator-store events (`iap.*`) and
1040
+ * `app.order.confirmed`, which tells a paid app's developer of each confirmed order made through the app.
1023
1041
  * This list is exactly what create and update accept. Read it before creating a webhook rather than
1024
1042
  * guessing names: a misspelled type is refused with 400.
1025
1043
  *
@@ -1343,6 +1361,18 @@ export interface components {
1343
1361
  error: string;
1344
1362
  /** @description Machine-readable error code (e.g. `IAP_PLAN_REQUIRED`, `INSUFFICIENT_QUANTITY`) */
1345
1363
  code?: string;
1364
+ /**
1365
+ * @description Which of a code's causes this is, where a code has several. Sent with `APP_NOT_SELLING`:
1366
+ * `app_not_published`, `selling_switched_off` (stopped by Chain Daddy), `developer_paused`
1367
+ * (paused by the app's developer), `developer_unavailable` (the developer cannot sell right
1368
+ * now; why is between them and Chain Daddy, and their own portal tells them), `no_payout_on_chain`
1369
+ * or `payout_contract_missing` (the developer is not paid on this chain). Sent with
1370
+ * `APP_ITEM_NOT_SOLD_HERE` (an app's item and a checkout session): any of those, or
1371
+ * `not_allowed_outside_app` (the app's developer has not allowed the item to be sold outside the app),
1372
+ * `app_not_installed`, `terms_changed` or `item_not_for_sale`. Absent on every other error. Expect new
1373
+ * values.
1374
+ */
1375
+ reason?: string;
1346
1376
  };
1347
1377
  /** @description One token prize. Amounts are base units, as strings. */
1348
1378
  IapAirdropAward: {
@@ -2460,8 +2490,8 @@ export interface components {
2460
2490
  iat: number;
2461
2491
  /** @description Five minutes after `iat` */
2462
2492
  exp: number;
2463
- /** @description When the Chain Daddy session this sign-in rides on began */
2464
- auth_time: number;
2493
+ /** @description When the Chain Daddy session this sign-in rides on began. Only for a client whose `sub` is the wallet; a client with a per-site `sub` gets none, because the same value at every site would link its ids */
2494
+ auth_time?: number;
2465
2495
  /** @description Your `nonce`, when you sent one */
2466
2496
  nonce?: string;
2467
2497
  jti: string;
@@ -2740,7 +2770,7 @@ export interface operations {
2740
2770
  /** @description The registration's ID on that chain */
2741
2771
  crownId: number;
2742
2772
  tokenAddress: string;
2743
- /** @description The page's logo; `null` when it has none or the page is marked NSFW */
2773
+ /** @description The page's logo; `null` when it has none, the page is marked NSFW, or Chain Daddy removed the image */
2744
2774
  logoUrl: string | null;
2745
2775
  /** @description Whether the page carries the NSFW label */
2746
2776
  nsfw: boolean;
@@ -2758,6 +2788,21 @@ export interface operations {
2758
2788
  };
2759
2789
  };
2760
2790
  };
2791
+ /** @description The request came with the user agent of an AI or LLM crawler, and no cached answer was there to serve instead. Never sent to a browser or to a server using its own user agent. */
2792
+ 403: {
2793
+ headers: {
2794
+ [name: string]: unknown;
2795
+ };
2796
+ content: {
2797
+ /**
2798
+ * @example {
2799
+ * "error": "ai_bot_blocked",
2800
+ * "message": "AI/LLM scraping is not permitted. Use our API with a developer-tier API key for programmatic access."
2801
+ * }
2802
+ */
2803
+ "application/json": components["schemas"]["Error"];
2804
+ };
2805
+ };
2761
2806
  /** @description No verified page for that ticker on that chain, or an unknown chain */
2762
2807
  404: {
2763
2808
  headers: {
@@ -2774,6 +2819,24 @@ export interface operations {
2774
2819
  "application/json": components["schemas"]["Error"];
2775
2820
  };
2776
2821
  };
2822
+ /** @description More than 400 requests in a minute from one IP address, across the whole API. Never cached. */
2823
+ 429: {
2824
+ headers: {
2825
+ /** @description Seconds to wait before trying again */
2826
+ "Retry-After"?: number;
2827
+ [name: string]: unknown;
2828
+ };
2829
+ content: {
2830
+ /**
2831
+ * @example {
2832
+ * "error": "Too many requests. Please try again later.",
2833
+ * "code": "rate_limit_exceeded",
2834
+ * "message": "Too many requests. Please try again later."
2835
+ * }
2836
+ */
2837
+ "application/json": components["schemas"]["Error"];
2838
+ };
2839
+ };
2777
2840
  /** @description The read could not be answered right now. Never cached; try again. */
2778
2841
  503: {
2779
2842
  headers: {
@@ -2852,6 +2915,21 @@ export interface operations {
2852
2915
  };
2853
2916
  };
2854
2917
  };
2918
+ /** @description The request came with the user agent of an AI or LLM crawler, and no cached answer was there to serve instead. Never sent to a browser or to a server using its own user agent. */
2919
+ 403: {
2920
+ headers: {
2921
+ [name: string]: unknown;
2922
+ };
2923
+ content: {
2924
+ /**
2925
+ * @example {
2926
+ * "error": "ai_bot_blocked",
2927
+ * "message": "AI/LLM scraping is not permitted. Use our API with a developer-tier API key for programmatic access."
2928
+ * }
2929
+ */
2930
+ "application/json": components["schemas"]["Error"];
2931
+ };
2932
+ };
2855
2933
  /** @description No verified page for that ticker on that chain, or an unknown chain */
2856
2934
  404: {
2857
2935
  headers: {
@@ -2868,6 +2946,24 @@ export interface operations {
2868
2946
  "application/json": components["schemas"]["Error"];
2869
2947
  };
2870
2948
  };
2949
+ /** @description More than 400 requests in a minute from one IP address, across the whole API. Never cached. */
2950
+ 429: {
2951
+ headers: {
2952
+ /** @description Seconds to wait before trying again */
2953
+ "Retry-After"?: number;
2954
+ [name: string]: unknown;
2955
+ };
2956
+ content: {
2957
+ /**
2958
+ * @example {
2959
+ * "error": "Too many requests. Please try again later.",
2960
+ * "code": "rate_limit_exceeded",
2961
+ * "message": "Too many requests. Please try again later."
2962
+ * }
2963
+ */
2964
+ "application/json": components["schemas"]["Error"];
2965
+ };
2966
+ };
2871
2967
  /** @description The read could not be answered right now. Never cached; try again. */
2872
2968
  503: {
2873
2969
  headers: {
@@ -2932,6 +3028,21 @@ export interface operations {
2932
3028
  };
2933
3029
  };
2934
3030
  };
3031
+ /** @description The request came with the user agent of an AI or LLM crawler, and no cached answer was there to serve instead. Never sent to a browser or to a server using its own user agent. */
3032
+ 403: {
3033
+ headers: {
3034
+ [name: string]: unknown;
3035
+ };
3036
+ content: {
3037
+ /**
3038
+ * @example {
3039
+ * "error": "ai_bot_blocked",
3040
+ * "message": "AI/LLM scraping is not permitted. Use our API with a developer-tier API key for programmatic access."
3041
+ * }
3042
+ */
3043
+ "application/json": components["schemas"]["Error"];
3044
+ };
3045
+ };
2935
3046
  /** @description An unknown chain, or an address that is not one on that chain */
2936
3047
  404: {
2937
3048
  headers: {
@@ -2966,9 +3077,15 @@ export interface operations {
2966
3077
  "application/json": components["schemas"]["Error"];
2967
3078
  };
2968
3079
  };
2969
- /** @description The read could not be answered right now. Never cached; try again. */
3080
+ /**
3081
+ * @description The read could not be answered right now. Never cached; try again. It never means the wallet
3082
+ * holds nothing. In a busy moment, when Chain Daddy is making as many chain reads as it allows,
3083
+ * it carries `Retry-After`.
3084
+ */
2970
3085
  503: {
2971
3086
  headers: {
3087
+ /** @description Seconds to wait before trying again. Sent only in a busy moment */
3088
+ "Retry-After"?: number;
2972
3089
  [name: string]: unknown;
2973
3090
  };
2974
3091
  content: {
@@ -3023,7 +3140,7 @@ export interface operations {
3023
3140
  chain: string;
3024
3141
  chainId: string;
3025
3142
  crownId: number;
3026
- /** @description The coin's ticker; empty when the registration could not be read */
3143
+ /** @description The coin's ticker */
3027
3144
  symbol: string;
3028
3145
  badgeHosts: string[];
3029
3146
  embedHosts: string[];
@@ -3031,7 +3148,22 @@ export interface operations {
3031
3148
  };
3032
3149
  };
3033
3150
  };
3034
- /** @description An unknown chain, or an ID that is not a positive whole number */
3151
+ /** @description The request came with the user agent of an AI or LLM crawler, and no cached answer was there to serve instead. Never sent to a browser or to a server using its own user agent. */
3152
+ 403: {
3153
+ headers: {
3154
+ [name: string]: unknown;
3155
+ };
3156
+ content: {
3157
+ /**
3158
+ * @example {
3159
+ * "error": "ai_bot_blocked",
3160
+ * "message": "AI/LLM scraping is not permitted. Use our API with a developer-tier API key for programmatic access."
3161
+ * }
3162
+ */
3163
+ "application/json": components["schemas"]["Error"];
3164
+ };
3165
+ };
3166
+ /** @description An unknown chain, an ID that is not a positive whole number, or a registration that is not a verified coin page's */
3035
3167
  404: {
3036
3168
  headers: {
3037
3169
  [name: string]: unknown;
@@ -3047,6 +3179,24 @@ export interface operations {
3047
3179
  "application/json": components["schemas"]["Error"];
3048
3180
  };
3049
3181
  };
3182
+ /** @description More than 400 requests in a minute from one IP address, across the whole API. Never cached. */
3183
+ 429: {
3184
+ headers: {
3185
+ /** @description Seconds to wait before trying again */
3186
+ "Retry-After"?: number;
3187
+ [name: string]: unknown;
3188
+ };
3189
+ content: {
3190
+ /**
3191
+ * @example {
3192
+ * "error": "Too many requests. Please try again later.",
3193
+ * "code": "rate_limit_exceeded",
3194
+ * "message": "Too many requests. Please try again later."
3195
+ * }
3196
+ */
3197
+ "application/json": components["schemas"]["Error"];
3198
+ };
3199
+ };
3050
3200
  /** @description The read could not be answered right now. Never cached; try again. */
3051
3201
  503: {
3052
3202
  headers: {
@@ -4412,7 +4562,8 @@ export interface operations {
4412
4562
  * @description Sold out, or the wallet has reached the SKU's per-wallet limit. For an app's item: `APP_TERMS_CHANGED`
4413
4563
  * (its developer changed its terms and the page's owner has not accepted them yet), `APP_NOT_INSTALLED`,
4414
4564
  * `APP_NOT_SELLING`, `APP_ORDER_LIMIT` (above the per-purchase limit) or `APP_DAILY_LIMIT` (the wallet
4415
- * reached what it may pay that app in 24 hours)
4565
+ * reached what it may pay that app in 24 hours). For an app's item paid through a checkout session:
4566
+ * `APP_ITEM_NOT_SOLD_HERE`, with a `reason`
4416
4567
  */
4417
4568
  409: {
4418
4569
  headers: {
@@ -4599,7 +4750,13 @@ export interface operations {
4599
4750
  "application/json": components["schemas"]["IapError"];
4600
4751
  };
4601
4752
  };
4602
- /** @description `SKU_NOT_FOR_SALE`: the item is archived, has no price, is an unlock, or belongs to an installed app */
4753
+ /**
4754
+ * @description `SKU_NOT_FOR_SALE`: the item is archived, has no price or is an unlock. `APP_ITEM_NOT_SOLD_HERE`: the
4755
+ * item belongs to an app installed on the coin's page and cannot be sold from the coin's own site now.
4756
+ * `reason` says why: `not_allowed_outside_app` (the app's developer has not turned it on for this item),
4757
+ * `app_not_installed`, `terms_changed` (the coin's owner must accept the app's new terms on the coin's
4758
+ * page), `item_not_for_sale` (the app no longer sells it), or one of the `APP_NOT_SELLING` reasons
4759
+ */
4603
4760
  409: {
4604
4761
  headers: {
4605
4762
  [name: string]: unknown;
package/dist/cd.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";(()=>{var S="0.3.0";function v(t){let e="";for(let n of t)e+=String.fromCharCode(n);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function f(){return v(crypto.getRandomValues(new Uint8Array(32)))}function R(t,e,n,s){let a=o=>{if(o&&typeof o=="object"&&o.type===t)try{n(o)}catch{}},d=o=>{o.origin===e&&a(o.data)};window.addEventListener("message",d);let u=null;if(s&&typeof BroadcastChannel=="function"&&e===location.origin)try{u=new BroadcastChannel(s),u.onmessage=o=>a(o.data)}catch{u=null}return()=>{window.removeEventListener("message",d),u?.close()}}var m={get(t){try{return sessionStorage.getItem(t)}catch{return null}},set(t,e){try{sessionStorage.setItem(t,e)}catch{}},remove(t){try{sessionStorage.removeItem(t)}catch{}}};var q="https://api.chaindaddy.io",V={"https://api.chaindaddy.io":"https://chaindaddy.io/_oauth/authorize","https://staging-api.chaindaddy.io":"https://staging.chaindaddy.io/_oauth/authorize"},w="cd-signin",T="cd:signin",y="cd.signin";async function F(t){let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return v(new Uint8Array(e))}function G(t="openid"){let e=t.split(/\s+/).filter(Boolean);return(e.includes("openid")?e:["openid",...e]).join(" ")}async function K(t,e,n){let s=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:e.redirectUri,scope:G(t.scope),state:e.state,nonce:e.nonce,code_challenge:await F(e.verifier),code_challenge_method:"S256"});return t.claims&&s.set("claims",typeof t.claims=="string"?t.claims:JSON.stringify(t.claims)),`${n}?${s}`}function _(t,e){return{code:e,codeVerifier:t.verifier,state:t.state,nonce:t.nonce,issuer:t.issuer,clientId:t.clientId,redirectUri:t.redirectUri}}function b(t){let e=(t.issuer??q).replace(/\/$/,""),n=t.authorizeUrl??V[e];if(!n)return Promise.reject(new Error("authorizeUrl is required for this issuer"));if(!t.clientId||!t.redirectUri)return Promise.reject(new Error("clientId and redirectUri are required"));let s={state:f(),nonce:f(),verifier:f(),issuer:e,clientId:t.clientId,redirectUri:t.redirectUri};m.set(y,JSON.stringify(s));let a=window.open("",w,"popup,width=480,height=720");return(async()=>{let d=await K(t,s,n);if(!a)return location.assign(d),null;a.location.href=d;let u=new URL(t.redirectUri,location.href).origin;return new Promise((o,i)=>{let c=R(T,u,r=>{r.state===s.state&&(c(),m.remove(y),typeof r.error=="string"&&r.error?i(new Error(r.error)):r.iss!==e?i(new Error("the answer came from another issuer")):typeof r.code!="string"||!r.code?i(new Error("the answer carried no code")):o(_(s,r.code)))},w);t.signal?.addEventListener("abort",()=>{c(),i(new Error("aborted"))})})})()}async function U(){let t=new URLSearchParams(location.search),e={type:T,code:t.get("code"),state:t.get("state"),iss:t.get("iss"),error:t.get("error")};if(window.name===w){try{window.opener?.postMessage(e,location.origin)}catch{}try{let a=new BroadcastChannel(w);a.postMessage(e),a.close()}catch{}return window.close(),null}let n=m.get(y);m.remove(y);let s=n?JSON.parse(n):null;if(!s||e.state!==s.state)throw new Error("the sign-in state does not match: start again");if(e.error)throw new Error(e.error);if(e.iss!==s.issuer)throw new Error("the answer came from another issuer");if(!e.code)throw new Error("the answer carried no code");return _(s,e.code)}async function A(t){let e=await fetch(`${t.issuer}/api/v2/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:t.code,redirect_uri:t.redirectUri,client_id:t.clientId,code_verifier:t.codeVerifier})}),n=await e.json();if(!e.ok)throw new Error(`${n.error??e.status}: ${n.error_description??""}`.trim());return n}var W='<svg viewBox="0 0 24 24" fill="#FFD700" width="20" height="20" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M5 16L3 5l5.5 5L12 4l3.5 6L21 5l-2 11H5z" stroke="#B8860B" stroke-width="0.5"/><path d="M5 18h14v2H5v-2z" stroke="#B8860B" stroke-width="0.5"/></svg>',Y=`
1
+ "use strict";(()=>{var S="0.3.1";function v(t){let e="";for(let r of t)e+=String.fromCharCode(r);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function f(){return v(crypto.getRandomValues(new Uint8Array(32)))}function R(t,e,r,s,o){let d=n=>{if(n&&typeof n=="object"&&n.type===t)try{r(n)}catch{}},u=n=>{n.origin===e&&(!o||n.source===o)&&d(n.data)};window.addEventListener("message",u);let c=null;if(s&&typeof BroadcastChannel=="function"&&e===location.origin)try{c=new BroadcastChannel(s),c.onmessage=n=>d(n.data)}catch{c=null}return()=>{window.removeEventListener("message",u),c?.close()}}var m={get(t){try{return sessionStorage.getItem(t)}catch{return null}},set(t,e){try{sessionStorage.setItem(t,e)}catch{}},remove(t){try{sessionStorage.removeItem(t)}catch{}}};var q="https://api.chaindaddy.io",V={"https://api.chaindaddy.io":"https://chaindaddy.io/_oauth/authorize","https://staging-api.chaindaddy.io":"https://staging.chaindaddy.io/_oauth/authorize"},w="cd-signin",T="cd:signin",y="cd.signin";async function F(t){let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return v(new Uint8Array(e))}function G(t="openid"){let e=t.split(/\s+/).filter(Boolean);return(e.includes("openid")?e:["openid",...e]).join(" ")}async function K(t,e,r){let s=new URLSearchParams({response_type:"code",client_id:e.clientId,redirect_uri:e.redirectUri,scope:G(t.scope),state:e.state,nonce:e.nonce,code_challenge:await F(e.verifier),code_challenge_method:"S256"});return t.claims&&s.set("claims",typeof t.claims=="string"?t.claims:JSON.stringify(t.claims)),`${r}?${s}`}function _(t,e){return{code:e,codeVerifier:t.verifier,state:t.state,nonce:t.nonce,issuer:t.issuer,clientId:t.clientId,redirectUri:t.redirectUri}}function b(t){let e=(t.issuer??q).replace(/\/$/,""),r=t.authorizeUrl??V[e];if(!r)return Promise.reject(new Error("authorizeUrl is required for this issuer"));if(!t.clientId||!t.redirectUri)return Promise.reject(new Error("clientId and redirectUri are required"));let s={state:f(),nonce:f(),verifier:f(),issuer:e,clientId:t.clientId,redirectUri:t.redirectUri};m.set(y,JSON.stringify(s));let o=window.open("",w,"popup,width=480,height=720");return(async()=>{let d=await K(t,s,r);if(!o)return location.assign(d),null;o.location.href=d;let u=new URL(t.redirectUri,location.href).origin;return new Promise((c,n)=>{let a=R(T,u,i=>{i.state===s.state&&(a(),m.remove(y),typeof i.error=="string"&&i.error?n(new Error(i.error)):i.iss!==e?n(new Error("the answer came from another issuer")):typeof i.code!="string"||!i.code?n(new Error("the answer carried no code")):c(_(s,i.code)))},w,o);t.signal?.addEventListener("abort",()=>{a(),n(new Error("aborted"))})})})()}async function U(){let t=new URLSearchParams(location.search),e={type:T,code:t.get("code"),state:t.get("state"),iss:t.get("iss"),error:t.get("error")};if(window.name===w){try{window.opener?.postMessage(e,location.origin)}catch{}try{let o=new BroadcastChannel(w);o.postMessage(e),o.close()}catch{}return window.close(),null}let r=m.get(y);m.remove(y);let s=r?JSON.parse(r):null;if(!s||e.state!==s.state)throw new Error("the sign-in state does not match: start again");if(e.error)throw new Error(e.error);if(e.iss!==s.issuer)throw new Error("the answer came from another issuer");if(!e.code)throw new Error("the answer carried no code");return _(s,e.code)}async function A(t){let e=await fetch(`${t.issuer}/api/v2/oauth/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:t.code,redirect_uri:t.redirectUri,client_id:t.clientId,code_verifier:t.codeVerifier})}),r=await e.json();if(!e.ok)throw new Error(`${r.error??e.status}: ${r.error_description??""}`.trim());return r}var W='<svg viewBox="0 0 24 24" fill="#FFD700" width="20" height="20" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><path d="M5 16L3 5l5.5 5L12 4l3.5 6L21 5l-2 11H5z" stroke="#B8860B" stroke-width="0.5"/><path d="M5 18h14v2H5v-2z" stroke="#B8860B" stroke-width="0.5"/></svg>',Y=`
2
2
  :host { display: inline-block; }
3
3
  button { display: inline-flex; align-items: center; justify-content: center; gap: 10px; box-sizing: border-box;
4
4
  min-height: 40px; padding: 0 16px; border-radius: 10px; font: 600 15px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
@@ -7,7 +7,7 @@ button[data-theme="dark"] { background: #101828; color: #ffffff; border-color: #
7
7
  button:focus-visible { outline: 2px solid #f59e0b; outline-offset: 2px; }
8
8
  button:disabled { opacity: .6; cursor: default; }
9
9
  svg { flex: none; }
10
- `;function L(){if(typeof customElements>"u"||customElements.get("cd-signin-button"))return;class t extends HTMLElement{constructor(){super(),this.root=this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(){this.isConnected&&this.render()}render(){let n=this.getAttribute("text")==="continue"?"Continue with Chain Daddy":"Sign in with Chain Daddy",s=this.getAttribute("theme")==="dark"?"dark":"light";this.root.innerHTML=`<style>${Y}</style><button type="button" part="button" data-theme="${s}">${W}<span></span></button>`;let a=this.root.querySelector("button");a.querySelector("span").textContent=n,a.addEventListener("click",()=>this.start())}start(){let n=s=>this.getAttribute(s)||void 0;b({clientId:n("client-id")??"",redirectUri:n("redirect-uri")??"",scope:n("scope"),claims:n("claims"),issuer:n("issuer"),authorizeUrl:n("authorize-url")}).then(s=>s&&this.dispatchEvent(new CustomEvent("cd-signin",{detail:s,bubbles:!0,composed:!0})),s=>this.dispatchEvent(new CustomEvent("cd-signin-error",{detail:{message:String(s?.message??s)},bubbles:!0,composed:!0})))}}t.observedAttributes=["theme","text"],customElements.define("cd-signin-button",t)}var M="https://embed.chaindaddy.io",k="https://embed-staging.chaindaddy.io";var J=["--cd-accent","--cd-surface","--cd-text","--cd-text-muted","--cd-border"];function P(t){try{if(t&&new URL(t).hostname==="js.staging.chaindaddy.io")return k}catch{}return M}var X=`
10
+ `;function L(){if(typeof customElements>"u"||customElements.get("cd-signin-button"))return;class t extends HTMLElement{constructor(){super(),this.root=this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(){this.isConnected&&this.render()}render(){let r=this.getAttribute("text")==="continue"?"Continue with Chain Daddy":"Sign in with Chain Daddy",s=this.getAttribute("theme")==="dark"?"dark":"light";this.root.innerHTML=`<style>${Y}</style><button type="button" part="button" data-theme="${s}">${W}<span></span></button>`;let o=this.root.querySelector("button");o.querySelector("span").textContent=r,o.addEventListener("click",()=>this.start())}start(){let r=s=>this.getAttribute(s)||void 0;b({clientId:r("client-id")??"",redirectUri:r("redirect-uri")??"",scope:r("scope"),claims:r("claims"),issuer:r("issuer"),authorizeUrl:r("authorize-url")}).then(s=>s&&this.dispatchEvent(new CustomEvent("cd-signin",{detail:s,bubbles:!0,composed:!0})),s=>this.dispatchEvent(new CustomEvent("cd-signin-error",{detail:{message:String(s?.message??s)},bubbles:!0,composed:!0})))}}t.observedAttributes=["theme","text"],customElements.define("cd-signin-button",t)}var M="https://embed.chaindaddy.io",k="https://embed-staging.chaindaddy.io";var J=["--cd-accent","--cd-surface","--cd-text","--cd-text-muted","--cd-border"];function P(t){try{if(t&&new URL(t).hostname==="js.staging.chaindaddy.io")return k}catch{}return M}var X=`
11
11
  :host { display: block; }
12
12
  iframe { display: block; width: 100%; border: 0; height: 1px; opacity: 0; color-scheme: normal; }
13
13
  :host([data-cd-ready]) iframe { opacity: 1; }
@@ -19,4 +19,4 @@ button { box-sizing: border-box; min-height: 40px; padding: 0 16px; border-radiu
19
19
  font: 600 15px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
20
20
  border: 1px solid var(--cd-border, #d0d5dd); background: var(--cd-accent, #f59e0b); color: var(--cd-text, #101828); }
21
21
  button:focus-visible { outline: 2px solid var(--cd-accent, #f59e0b); outline-offset: 2px; }
22
- `;function O(t={}){try{if(typeof customElements>"u"||typeof HTMLElement>"u")return;let e=t.origin===k?k:M;class n extends HTMLElement{constructor(){super(...arguments);this.kind="app";this.frame=null;this.onMessage=i=>this.receive(i)}connectedCallback(){try{this.shadowRoot||this.attachShadow({mode:"open"}),this.mount()}catch{this.unavailable()}}disconnectedCallback(){try{window.removeEventListener("message",this.onMessage),clearTimeout(this.timer)}catch{}}attributeChangedCallback(){try{this.isConnected&&this.shadowRoot&&this.mount()}catch{this.unavailable()}}src(){let i=(this.getAttribute("crown")??"").trim(),c=(this.getAttribute("chain")??"").trim(),r=(this.getAttribute("app")??"").trim();if(!/^[0-9]{1,18}$/.test(i)||!c||this.kind==="app"&&!r)return null;let l=new URLSearchParams({crown:i,chain:c});return this.kind==="app"?l.set("app",r):l.set("kind","coin"),l.set("mode",this.mode()),l.set("v","1"),`${e}/v1/frame?${l.toString()}`}mode(){let i=this.getAttribute("mode");if(i==="light"||i==="dark")return i;try{return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}catch{return"light"}}mount(){let i=this.shadowRoot;window.removeEventListener("message",this.onMessage),clearTimeout(this.timer),this.removeAttribute("data-cd-ready"),this.removeAttribute("data-cd-unavailable");let c=this.src();if(!c){i.innerHTML="<slot></slot>",this.frame=null;return}i.innerHTML=`<style>${X}</style><slot></slot>`;let r=document.createElement("iframe");r.setAttribute("loading","lazy"),r.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),r.setAttribute("allow","clipboard-write; fullscreen"),r.setAttribute("title",this.kind==="coin"?"Coin on Chain Daddy":"App on Chain Daddy"),r.src=c,i.appendChild(r),this.frame=r,window.addEventListener("message",this.onMessage),this.timer=setTimeout(()=>{this.hasAttribute("data-cd-ready")||this.unavailable()},8e3)}receive(i){try{if(i.origin!==e||!this.frame||!i.source||i.source!==this.frame.contentWindow)return;let c=i.data;if(!c||typeof c!="object")return;if(c.type==="cd:ready")clearTimeout(this.timer),this.removeAttribute("data-cd-unavailable"),this.setAttribute("data-cd-ready",""),this.sendTheme(),this.dispatchEvent(new CustomEvent("cd:ready"));else if(c.type==="cd:resize"){let r=Number(c.height);Number.isFinite(r)&&(this.frame.style.height=`${Math.max(1,Math.min(4e3,Math.ceil(r)))}px`)}else c.type==="cd:unavailable"&&this.unavailable()}catch{}}sendTheme(){let i={},c=getComputedStyle(this);for(let r of J){let l=c.getPropertyValue(r).trim();l&&(i[r]=l)}this.frame?.contentWindow?.postMessage({type:"cd:theme",tokens:i},e)}unavailable(){try{if(clearTimeout(this.timer),this.removeAttribute("data-cd-ready"),this.hasAttribute("data-cd-unavailable"))return;this.setAttribute("data-cd-unavailable",""),this.dispatchEvent(new CustomEvent("cd:unavailable"))}catch{}}}n.observedAttributes=["crown","chain","app","mode"];class s extends n{}class a extends n{constructor(){super(...arguments);this.kind="coin"}}class d extends HTMLElement{connectedCallback(){try{let o=this.querySelector("a[href]"),i=o?new URL(o.getAttribute("href")??"",document.baseURI):null;if(!i||i.protocol!=="https:")return;let c=this.shadowRoot??this.attachShadow({mode:"open"});c.innerHTML=`<style>${Q}</style><button type="button" part="button"></button>`;let r=c.querySelector("button");r.textContent=(o.textContent??"").trim()||"Buy on Chain Daddy",r.addEventListener("click",()=>{try{window.open(i.toString(),"cd-buy","popup,width=460,height=760")||window.location.assign(i.toString())}catch{}})}catch{}}}for(let[u,o]of[["cd-app",s],["cd-coin",a],["cd-buy",d]])customElements.get(u)||customElements.define(u,o)}catch{}}var Z=["https://chaindaddy.io","https://staging.chaindaddy.io"],D=()=>"cd-checkout-"+f(),H="popup,width=480,height=820",$=300,tt=7;function E(t){if(typeof t!="string")return null;let e;try{e=new URL(t)}catch{return null}let n=/^\/_pay\/([\w-]+)$/.exec(e.pathname);return n&&Z.includes(e.origin)&&!e.username&&!e.password?{href:e.origin+e.pathname,origin:e.origin,id:n[1]}:null}function C(t,e){if(typeof t!="string")return null;let n;try{n=new URL(t,location.href)}catch{return null}if(!/^https?:$/.test(n.protocol)||n.username||n.password)return null;let s=d=>{let u=d.split("=")[0];try{return decodeURIComponent(u.replace(/\+/g," "))}catch{return u}},a=n.search.slice(1).split("&").filter(d=>d&&s(d)!=="session_id");return a.push("session_id="+encodeURIComponent(e)),n.origin+n.pathname+"?"+a.join("&")+n.hash}var p;function N(t,e,n){return new Promise(s=>{let a=!1,d=0,u,o=l=>{clearInterval(r),clearTimeout(u),window.removeEventListener("message",i),n&&l.status==="completed"&&location.assign(n),s(l)},i=l=>{if(l.origin!==e.origin||l.source!==t)return;let g=l.data;if(!g||typeof g!="object")return;g.type==="cd:checkout.ready"&&(a=!0);let h=g.session;if(!(!h||typeof h!="object"||h.id!==e.id)){if(g.type==="cd:checkout.cancelled")o({status:"cancelled",session:{id:e.id}});else if(g.type==="cd:checkout.completed"&&(h.status==="complete"||h.status==="paid")){let I={id:e.id,status:h.status};typeof h.orderId=="string"&&/^[\w-]{1,128}$/.test(h.orderId)&&(I.orderId=h.orderId),o({status:"completed",session:I})}}},c=()=>{try{t.postMessage({type:"cd:checkout.hello"},e.origin)}catch{}},r=setInterval(()=>{t.closed?(clearInterval(r),u=setTimeout(()=>o({status:"closed"}),$)):(!a||++d%tt===0)&&c()},$);window.addEventListener("message",i),c()})}function x(t){let e=()=>new Error("checkout: url is not a Chain Daddy checkout session link"),n=(a,d,u)=>{p={popup:a,result:d,href:u};let o=()=>{p&&p.popup===a&&(p=void 0)};return d.then(o,o),d},s=a=>(location.assign(a.href),{status:"redirected"});try{let{url:a,successUrl:d}=t;if(d&&!C(d,""))throw new Error("checkout: successUrl is not a web address");let u=r=>d?C(d,r.id):null,o=typeof a=="function"?null:E(a);if(typeof a!="function"&&!o)throw e();if(p&&!p.popup.closed&&(!o||p.href===o.href))return p.popup.focus(),p.result;if(o){let r=window.open(o.href,D(),H);return r?n(r,N(r,o,u(o)),o.href):Promise.resolve(s(o))}let i=window.open("",D(),H),c=new Promise(r=>r(a())).then(r=>{let l=E(r);if(!l)throw i?.close(),e();return i?(i.location.href=l.href,N(i,l,u(l))):s(l)},r=>{throw i?.close(),r});return i?n(i,c):c}catch(a){return Promise.reject(a)}}var B=!1,z;function j(){B||typeof document>"u"||(B=!0,document.addEventListener("click",t=>{let e=t.target instanceof Element?t.target.closest("[data-cd-checkout]"):null;if(!e||t.defaultPrevented||t.button||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey)return;let n=e.getAttribute("data-cd-checkout")||e.href,s=e.getAttribute("data-cd-success");if(!E(n)||s&&!C(s,""))return;t.preventDefault();let a=x({url:n,successUrl:s});a!==z&&(z=a,a.then(d=>void e.dispatchEvent(new CustomEvent("cd:checkout",{detail:d,bubbles:!0})),()=>{}))}))}var et={version:S,signIn:b,handleCallback:U,exchangeCode:A,checkout:x};window.ChainDaddy=Object.assign(window.ChainDaddy??{},et);L();O({origin:P(document.currentScript?.src)});j();})();
22
+ `;function O(t={}){try{if(typeof customElements>"u"||typeof HTMLElement>"u")return;let e=t.origin===k?k:M;class r extends HTMLElement{constructor(){super(...arguments);this.kind="app";this.frame=null;this.onMessage=n=>this.receive(n)}connectedCallback(){try{this.shadowRoot||this.attachShadow({mode:"open"}),this.mount()}catch{this.unavailable()}}disconnectedCallback(){try{window.removeEventListener("message",this.onMessage),clearTimeout(this.timer)}catch{}}attributeChangedCallback(){try{this.isConnected&&this.shadowRoot&&this.mount()}catch{this.unavailable()}}src(){let n=(this.getAttribute("crown")??"").trim(),a=(this.getAttribute("chain")??"").trim(),i=(this.getAttribute("app")??"").trim();if(!/^[0-9]{1,18}$/.test(n)||!a||this.kind==="app"&&!i)return null;let l=new URLSearchParams({crown:n,chain:a});return this.kind==="app"?l.set("app",i):l.set("kind","coin"),l.set("mode",this.mode()),l.set("v","1"),`${e}/v1/frame?${l.toString()}`}mode(){let n=this.getAttribute("mode");if(n==="light"||n==="dark")return n;try{return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}catch{return"light"}}mount(){let n=this.shadowRoot;window.removeEventListener("message",this.onMessage),clearTimeout(this.timer),this.removeAttribute("data-cd-ready"),this.removeAttribute("data-cd-unavailable");let a=this.src();if(!a){n.innerHTML="<slot></slot>",this.frame=null;return}n.innerHTML=`<style>${X}</style><slot></slot>`;let i=document.createElement("iframe");i.setAttribute("loading","lazy"),i.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),i.setAttribute("allow","clipboard-write; fullscreen"),i.setAttribute("title",this.kind==="coin"?"Coin on Chain Daddy":"App on Chain Daddy"),i.src=a,n.appendChild(i),this.frame=i,window.addEventListener("message",this.onMessage),this.timer=setTimeout(()=>{this.hasAttribute("data-cd-ready")||this.unavailable()},8e3)}receive(n){try{if(n.origin!==e||!this.frame||!n.source||n.source!==this.frame.contentWindow)return;let a=n.data;if(!a||typeof a!="object")return;if(a.type==="cd:ready")clearTimeout(this.timer),this.removeAttribute("data-cd-unavailable"),this.setAttribute("data-cd-ready",""),this.sendTheme(),this.dispatchEvent(new CustomEvent("cd:ready"));else if(a.type==="cd:resize"){let i=Number(a.height);Number.isFinite(i)&&(this.frame.style.height=`${Math.max(1,Math.min(4e3,Math.ceil(i)))}px`)}else a.type==="cd:unavailable"&&this.unavailable()}catch{}}sendTheme(){let n={},a=getComputedStyle(this);for(let i of J){let l=a.getPropertyValue(i).trim();l&&(n[i]=l)}this.frame?.contentWindow?.postMessage({type:"cd:theme",tokens:n},e)}unavailable(){try{if(clearTimeout(this.timer),this.removeAttribute("data-cd-ready"),this.hasAttribute("data-cd-unavailable"))return;this.setAttribute("data-cd-unavailable",""),this.dispatchEvent(new CustomEvent("cd:unavailable"))}catch{}}}r.observedAttributes=["crown","chain","app","mode"];class s extends r{}class o extends r{constructor(){super(...arguments);this.kind="coin"}}class d extends HTMLElement{connectedCallback(){try{let c=this.querySelector("a[href]"),n=c?new URL(c.getAttribute("href")??"",document.baseURI):null;if(!n||n.protocol!=="https:")return;let a=this.shadowRoot??this.attachShadow({mode:"open"});a.innerHTML=`<style>${Q}</style><button type="button" part="button"></button>`;let i=a.querySelector("button");i.textContent=(c.textContent??"").trim()||"Buy on Chain Daddy",i.addEventListener("click",()=>{try{window.open(n.toString(),"cd-buy","popup,width=460,height=760")||window.location.assign(n.toString())}catch{}})}catch{}}}for(let[u,c]of[["cd-app",s],["cd-coin",o],["cd-buy",d]])customElements.get(u)||customElements.define(u,c)}catch{}}var Z=["https://chaindaddy.io","https://staging.chaindaddy.io"],D=()=>"cd-checkout-"+f(),H="popup,width=480,height=820",$=300,tt=7;function E(t){if(typeof t!="string")return null;let e;try{e=new URL(t)}catch{return null}let r=/^\/_pay\/([\w-]+)$/.exec(e.pathname);return r&&Z.includes(e.origin)&&!e.username&&!e.password?{href:e.origin+e.pathname,origin:e.origin,id:r[1]}:null}function C(t,e){if(typeof t!="string")return null;let r;try{r=new URL(t,location.href)}catch{return null}if(!/^https?:$/.test(r.protocol)||r.username||r.password)return null;let s=d=>{let u=d.split("=")[0];try{return decodeURIComponent(u.replace(/\+/g," "))}catch{return u}},o=r.search.slice(1).split("&").filter(d=>d&&s(d)!=="session_id");return o.push("session_id="+encodeURIComponent(e)),r.origin+r.pathname+"?"+o.join("&")+r.hash}var p;function N(t,e,r){return new Promise(s=>{let o=!1,d=0,u,c=l=>{clearInterval(i),clearTimeout(u),window.removeEventListener("message",n),r&&l.status==="completed"&&location.assign(r),s(l)},n=l=>{if(l.origin!==e.origin||l.source!==t)return;let g=l.data;if(!g||typeof g!="object")return;g.type==="cd:checkout.ready"&&(o=!0);let h=g.session;if(!(!h||typeof h!="object"||h.id!==e.id)){if(g.type==="cd:checkout.cancelled")c({status:"cancelled",session:{id:e.id}});else if(g.type==="cd:checkout.completed"&&(h.status==="complete"||h.status==="paid")){let I={id:e.id,status:h.status};typeof h.orderId=="string"&&/^[\w-]{1,128}$/.test(h.orderId)&&(I.orderId=h.orderId),c({status:"completed",session:I})}}},a=()=>{try{t.postMessage({type:"cd:checkout.hello"},e.origin)}catch{}},i=setInterval(()=>{t.closed?(clearInterval(i),u=setTimeout(()=>c({status:"closed"}),$)):(!o||++d%tt===0)&&a()},$);window.addEventListener("message",n),a()})}function x(t){let e=()=>new Error("checkout: url is not a Chain Daddy checkout session link"),r=(o,d,u)=>{p={popup:o,result:d,href:u};let c=()=>{p&&p.popup===o&&(p=void 0)};return d.then(c,c),d},s=o=>(location.assign(o.href),{status:"redirected"});try{let{url:o,successUrl:d}=t;if(d&&!C(d,""))throw new Error("checkout: successUrl is not a web address");let u=i=>d?C(d,i.id):null,c=typeof o=="function"?null:E(o);if(typeof o!="function"&&!c)throw e();if(p&&!p.popup.closed&&(!c||p.href===c.href))return p.popup.focus(),p.result;if(c){let i=window.open(c.href,D(),H);return i?r(i,N(i,c,u(c)),c.href):Promise.resolve(s(c))}let n=window.open("",D(),H),a=new Promise(i=>i(o())).then(i=>{let l=E(i);if(!l)throw n?.close(),e();return n?(n.location.href=l.href,N(n,l,u(l))):s(l)},i=>{throw n?.close(),i});return n?r(n,a):a}catch(o){return Promise.reject(o)}}var B=!1,z;function j(){B||typeof document>"u"||(B=!0,document.addEventListener("click",t=>{let e=t.target instanceof Element?t.target.closest("[data-cd-checkout]"):null;if(!e||t.defaultPrevented||t.button||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey)return;let r=e.getAttribute("data-cd-checkout")||e.href,s=e.getAttribute("data-cd-success");if(!E(r)||s&&!C(s,""))return;t.preventDefault();let o=x({url:r,successUrl:s});o!==z&&(z=o,o.then(d=>void e.dispatchEvent(new CustomEvent("cd:checkout",{detail:d,bubbles:!0})),()=>{}))}))}var et={version:S,signIn:b,handleCallback:U,exchangeCode:A,checkout:x};window.ChainDaddy=Object.assign(window.ChainDaddy??{},et);L();O({origin:P(document.currentScript?.src)});j();})();
package/dist/cd.js.sri CHANGED
@@ -1 +1 @@
1
- sha384-oAzz7JY6TsxFo7MvOAoI5wWjgXMDQsM27deR2Rr9F1DCHjZMz+Tb0oN9LT46GSnm
1
+ sha384-EF2XlOLUJ0J2U3uy/hlkmXdqyRP0WVm2LYjWdTseg/+QC4El1HD+qMhMlandYcSF
package/dist/core.d.ts CHANGED
@@ -6,9 +6,10 @@ export declare function randomToken(): string;
6
6
  /**
7
7
  * Listens for messages of `type` from exactly `origin`, on window and on a
8
8
  * same-origin BroadcastChannel (which still works when a COOP header has
9
- * severed window.opener). Returns a function that stops listening.
9
+ * severed window.opener). With `from`, a window message counts only when
10
+ * that window sent it. Returns a function that stops listening.
10
11
  */
11
- export declare function listen(type: string, origin: string, onMessage: (data: Record<string, unknown>) => void, channel?: string): () => void;
12
+ export declare function listen(type: string, origin: string, onMessage: (data: Record<string, unknown>) => void, channel?: string, from?: Window | null): () => void;
12
13
  /** sessionStorage that never throws (private windows, blocked storage). */
13
14
  export declare const store: {
14
15
  get(key: string): string | null;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/core.ts
2
- var VERSION = true ? "0.3.0" : "0.0.0";
2
+ var VERSION = true ? "0.3.1" : "0.0.0";
3
3
  function b64url(bytes) {
4
4
  let s = "";
5
5
  for (const b of bytes) s += String.fromCharCode(b);
@@ -8,7 +8,7 @@ function b64url(bytes) {
8
8
  function randomToken() {
9
9
  return b64url(crypto.getRandomValues(new Uint8Array(32)));
10
10
  }
11
- function listen(type, origin, onMessage, channel) {
11
+ function listen(type, origin, onMessage, channel, from) {
12
12
  const accept = (data) => {
13
13
  if (data && typeof data === "object" && data.type === type) {
14
14
  try {
@@ -18,7 +18,7 @@ function listen(type, origin, onMessage, channel) {
18
18
  }
19
19
  };
20
20
  const onWindow = (e) => {
21
- if (e.origin === origin) accept(e.data);
21
+ if (e.origin === origin && (!from || e.source === from)) accept(e.data);
22
22
  };
23
23
  window.addEventListener("message", onWindow);
24
24
  let bc = null;
@@ -116,7 +116,7 @@ function signIn(o) {
116
116
  else if (m.iss !== issuer) reject(new Error("the answer came from another issuer"));
117
117
  else if (typeof m.code !== "string" || !m.code) reject(new Error("the answer carried no code"));
118
118
  else resolve(result(p, m.code));
119
- }, POPUP_NAME);
119
+ }, POPUP_NAME, popup);
120
120
  o.signal?.addEventListener("abort", () => {
121
121
  stop();
122
122
  reject(new Error("aborted"));
package/dist/signin.js CHANGED
@@ -7,7 +7,7 @@ function b64url(bytes) {
7
7
  function randomToken() {
8
8
  return b64url(crypto.getRandomValues(new Uint8Array(32)));
9
9
  }
10
- function listen(type, origin, onMessage, channel) {
10
+ function listen(type, origin, onMessage, channel, from) {
11
11
  const accept = (data) => {
12
12
  if (data && typeof data === "object" && data.type === type) {
13
13
  try {
@@ -17,7 +17,7 @@ function listen(type, origin, onMessage, channel) {
17
17
  }
18
18
  };
19
19
  const onWindow = (e) => {
20
- if (e.origin === origin) accept(e.data);
20
+ if (e.origin === origin && (!from || e.source === from)) accept(e.data);
21
21
  };
22
22
  window.addEventListener("message", onWindow);
23
23
  let bc = null;
@@ -115,7 +115,7 @@ function signIn(o) {
115
115
  else if (m.iss !== issuer) reject(new Error("the answer came from another issuer"));
116
116
  else if (typeof m.code !== "string" || !m.code) reject(new Error("the answer carried no code"));
117
117
  else resolve(result(p, m.code));
118
- }, POPUP_NAME);
118
+ }, POPUP_NAME, popup);
119
119
  o.signal?.addEventListener("abort", () => {
120
120
  stop();
121
121
  reject(new Error("aborted"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaindaddy/js",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Chain Daddy for any website: Sign in with Chain Daddy (a popup and a button), a coin's apps on its own site (<cd-app>), checkout for a coin's store in a popup, and a server-side check that a store order was paid on chain",
5
5
  "homepage": "https://docs.chaindaddy.io/developer/javascript-sdk",
6
6
  "repository": {
@@ -60,6 +60,7 @@
60
60
  "devDependencies": {
61
61
  "esbuild": "^0.25.0",
62
62
  "jsdom": "^26.0.0",
63
+ "openapi-typescript": "7.13.0",
63
64
  "typescript": "^5.7.0",
64
65
  "vitest": "^3.2.0"
65
66
  },