@markee_team/sdk 0.1.0-alpha.1 → 0.1.0-alpha.10
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 +164 -11
- package/dist/checkout.d.ts +7 -0
- package/dist/client.d.ts +7 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +39 -4
- package/dist/modal.d.ts +4 -1
- package/dist/react.d.ts +13 -1
- package/dist/react.js +39 -4
- package/dist/sign.d.ts +21 -0
- package/dist/styles.d.ts +1 -1
- package/dist/types.d.ts +27 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Markee SDK
|
|
2
2
|
|
|
3
|
-
An ESM JavaScript SDK with a self-contained, Shadow DOM modal and an optional React entry point. The
|
|
3
|
+
An ESM JavaScript SDK with a self-contained, Shadow DOM modal and an optional React entry point. The SDK knows the Markee API endpoint; the host only supplies its placement and, optionally, its current wallet provider. No Alchemy, Redis, Privy, or bridge-provider key belongs in the consuming app.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Embed a Markee leaderboard in your app with wallet-funded For Sale and For Rent flows, automatic strategy detection, and a configurable theme. Eligible Base For Sale boards can also offer Markee-hosted card checkout when enabled by Markee. Incoming cross-chain funding is not included.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The package also includes a standalone **Markee sign**. It shows the board's current winner and follows Markee's moderation decisions, with an optional button to open the payment modal.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
npm install @markee_team/sdk@
|
|
12
|
+
npm install @markee_team/sdk@latest
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
Use React 18 or 19 for the optional React entry point. The plain JavaScript entry point does not require React. Both TypeScript bundler and NodeNext resolution are supported.
|
|
@@ -19,13 +21,37 @@ npm ci --prefix packages/sdk
|
|
|
19
21
|
npm run build --prefix packages/sdk
|
|
20
22
|
```
|
|
21
23
|
|
|
24
|
+
## Create and connect your leaderboard
|
|
25
|
+
|
|
26
|
+
The SDK connects to an existing leaderboard; installing it does not create one.
|
|
27
|
+
|
|
28
|
+
1. Open [Create a Markee](https://www.markee.xyz/create-a-markee) and complete the leaderboard setup on Markee. Choose For Sale or For Rent there. If you already have a leaderboard, use it instead.
|
|
29
|
+
2. Copy the resulting Markee page link: `https://www.markee.xyz/markee/<address>`.
|
|
30
|
+
3. Extract the `0x…` address from that link and use it in the SDK placement: `{ kind: 'board', chainId: 8453, address: yourLeaderboardAddress }`.
|
|
31
|
+
4. Open the modal to display your leaderboard. If using a coding assistant, give it the Markee page link along with the LLM implementation prompt below.
|
|
32
|
+
|
|
33
|
+
The SDK reads the leaderboard's strategy from Markee and automatically renders the appropriate For Sale or For Rent flow. You do not configure a strategy in your app.
|
|
34
|
+
|
|
35
|
+
## Automatic site verification
|
|
36
|
+
|
|
37
|
+
Pass your public page URL or domain as `siteUrl` to `MarkeeModal` or `createMarkee`, for example `siteUrl="https://your-app.example"`. The React component registers the site when mounted, even while closed; the JavaScript modal registers when opened. No API key is required. Use `onSiteVerification` to inspect success or setup errors; verification does not block browsing or payments.
|
|
38
|
+
|
|
39
|
+
Markee fetches the public page and verifies that its HTML contains the matching board marker before adding it to **Served on**. The React component renders this marker for server-rendered apps. For client-rendered apps such as Vite, include it in the deployed `index.html` (replace the address with your board):
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<span hidden data-markee-address="0xYOUR_BOARD_ADDRESS"></span>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The marker must be present in the HTML returned by the server, not only injected by JavaScript. The supplied URL must use HTTPS, match the app's origin, and return the final HTML page without redirects. Localhost and private-network sites cannot be publicly verified. Registration currently supports Base boards. It verifies the board's presence, not legal domain ownership.
|
|
46
|
+
|
|
47
|
+
For an explicit retry after deployment, call `new MarkeeClient().verifySite(placement, siteUrl)`. The endpoint is `POST /api/sdk/v1/sites/verify` with `{ placement, siteUrl }`. Unverified sites are never added to the verified list.
|
|
48
|
+
|
|
22
49
|
## Plain JavaScript
|
|
23
50
|
|
|
24
51
|
```ts
|
|
25
52
|
import { createMarkee } from '@markee_team/sdk';
|
|
26
53
|
|
|
27
54
|
const markee = createMarkee({
|
|
28
|
-
apiUrl: 'https://YOUR-MARKEE-API/api/sdk/v1',
|
|
29
55
|
// Optional. Reuse the wallet selected by your application's wallet connector.
|
|
30
56
|
wallet: {
|
|
31
57
|
getProvider: async () => appWalletProvider ?? null,
|
|
@@ -45,7 +71,7 @@ markee.open({
|
|
|
45
71
|
// markee.close();
|
|
46
72
|
```
|
|
47
73
|
|
|
48
|
-
Without a wallet adapter, browsing works without a wallet. On a connect click the modal discovers installed wallets using EIP-6963, with an EIP-1193 fallback. Multiple discovered wallets are offered for explicit selection. An adapter always takes precedence over injected discovery.
|
|
74
|
+
Without a wallet adapter, browsing works without a wallet. On a connect click the modal discovers installed wallets using EIP-6963, with an EIP-1193 fallback. Multiple discovered wallets are offered for explicit selection. An adapter always takes precedence over injected discovery. Eligible boards also offer hosted login and card checkout when enabled by Markee; the host app does not need its own wallet integration.
|
|
49
75
|
|
|
50
76
|
## React
|
|
51
77
|
|
|
@@ -55,7 +81,6 @@ import { MarkeeModal } from '@markee_team/sdk/react';
|
|
|
55
81
|
<MarkeeModal
|
|
56
82
|
open={open}
|
|
57
83
|
onClose={() => setOpen(false)}
|
|
58
|
-
apiUrl="https://YOUR-MARKEE-API/api/sdk/v1"
|
|
59
84
|
wallet={walletAdapter}
|
|
60
85
|
placement={{ kind: 'gardens-community', chainId: 100, community: communityAddress }}
|
|
61
86
|
/>;
|
|
@@ -63,9 +88,22 @@ import { MarkeeModal } from '@markee_team/sdk/react';
|
|
|
63
88
|
|
|
64
89
|
See [`examples/connectkit`](https://github.com/1Hive/markee/tree/feature/markee-sdk/examples/connectkit) for a complete adapter. Its connection promise resolves only once ConnectKit has selected a provider and rejects when the picker is dismissed. The SDK does not install a second wallet context.
|
|
65
90
|
|
|
91
|
+
## Embed the current Markee sign
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { MarkeeSign } from '@markee_team/sdk/react';
|
|
95
|
+
|
|
96
|
+
const placement = { kind: 'board', chainId: 8453, address: '0x2768BC6e90266248BD8bCF5401C36D8049CdF671' } as const;
|
|
97
|
+
<MarkeeSign placement={placement} theme={{ mode: 'dark' }} />;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`MarkeeSign` shows the current on-chain winner, its message and author, and an **Open Markee** button that launches the SDK modal. It uses the same optional wallet adapter and theme as `MarkeeModal`. No app-side moderation database, RPC key, or moderation provider is needed. To render from plain JavaScript, call `createMarkeeSign(containerElement, { placement })`; its return value has `refresh()`, `setTheme()`, and `destroy()`.
|
|
101
|
+
|
|
102
|
+
The SDK snapshot API reads **board moderation flags** from Markee's database. A flagged winner is blurred with a notice; the author's name is blurred too. The sign does not offer a reveal action or count a view for flagged content. If moderation data cannot be loaded, it withholds the message until the status is known. Visible, unflagged signs record one view per message. The sign refreshes every 30 seconds while mounted and can be refreshed on demand. Markee-only site flags intentionally apply only on markee.xyz; they do not censor a partner's embedded sign. Moderators still manage flags on Markee; moderation writes invalidate SDK snapshots so embedded signs can pick up changes on their next refresh.
|
|
103
|
+
|
|
66
104
|
## Modal layout
|
|
67
105
|
|
|
68
|
-
Both strategies
|
|
106
|
+
Both strategies use a consistent, compact 512px panel with a fixed header/footer, a collapsible leaderboard, the selected message or editor, and a prominent amount card. The leaderboard pins your loaded messages and offers inline funding selection. Your active rental message is selected when available; otherwise an owned message or the creation form is shown.
|
|
69
107
|
|
|
70
108
|
For Sale uses the same arrangement with a one-time ETH amount. For Rent uses an ETHx monthly rate and links to Deposit manager. Wallet balances, rewards, refunds, edits, and community treasury actions remain accessible without top-level tabs. The footer holds the review/confirmation actions and Stop streaming when applicable.
|
|
71
109
|
|
|
@@ -92,7 +130,7 @@ const theme: MarkeeTheme = {
|
|
|
92
130
|
|
|
93
131
|
// React: <MarkeeModal {...modalProps} theme={theme} />
|
|
94
132
|
// JavaScript:
|
|
95
|
-
const markee = createMarkee({
|
|
133
|
+
const markee = createMarkee({ theme });
|
|
96
134
|
markee.setTheme({ mode: 'dark' });
|
|
97
135
|
markee.setTheme(); // Reset to the default light theme.
|
|
98
136
|
```
|
|
@@ -137,4 +175,119 @@ Community activation supports the current council Safe, a current Safe owner, or
|
|
|
137
175
|
- The modal renders escaped text, uses isolated CSS, and supports keyboard focus, Escape, mobile sizing and reduced motion. A host CSP must permit the SDK's inline styles and connections to its configured Markee API. No external font or image is needed by the modal.
|
|
138
176
|
- API failures are explicit. Without moderation data, message text is withheld. No mock balances or fabricated rewards are returned by production handlers.
|
|
139
177
|
|
|
140
|
-
Backend configuration
|
|
178
|
+
Backend configuration and API reference: [`docs/sdk/implementation.md`](https://github.com/1Hive/markee/blob/feature/markee-sdk/docs/sdk/implementation.md).
|
|
179
|
+
|
|
180
|
+
## API endpoint
|
|
181
|
+
|
|
182
|
+
No API URL or Markee API key is required. The SDK connects to the Markee-hosted API and centralizes on-chain reads, metadata, and transaction preparation. For local development or testing, pass an optional `apiUrl` override to `createMarkee`, `MarkeeClient`, or the React modal. The endpoint used by your installed release is exported as `DEFAULT_MARKEE_API_URL`.
|
|
183
|
+
|
|
184
|
+
## LLM implementation prompt
|
|
185
|
+
|
|
186
|
+
Copy this prompt into your coding assistant. It gathers missing requirements before implementing the integration.
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
Integrate @markee_team/sdk@latest into this app. Inspect the codebase first and
|
|
190
|
+
follow its existing framework, styling, and wallet patterns. Read the installed
|
|
191
|
+
package README and types for current capabilities.
|
|
192
|
+
|
|
193
|
+
Before implementing, ask me to create my leaderboard on Markee at
|
|
194
|
+
https://www.markee.xyz/create-a-markee, then provide its resulting Markee page link.
|
|
195
|
+
If I already have a leaderboard, ask for that link instead; do not create a duplicate.
|
|
196
|
+
Example link format:
|
|
197
|
+
https://www.markee.xyz/markee/0x6ceBC87DE40519Fa52fc40a1d49f16FF968bb439
|
|
198
|
+
Never silently substitute a demo board. Wait for my link before wiring the placement.
|
|
199
|
+
|
|
200
|
+
Extract the board address from the /markee/<address> path. Validate the Markee URL
|
|
201
|
+
and the address (0x followed by 40 hexadecimal characters). Markee website boards
|
|
202
|
+
currently use Base, chain ID 8453. Verify the board through the SDK snapshot API;
|
|
203
|
+
if verification fails, explain the error and ask for a corrected link.
|
|
204
|
+
|
|
205
|
+
Do not ask me to choose For Sale or For Rent in the host app. That choice is made
|
|
206
|
+
when creating the leaderboard on Markee. The API returns strategy and the SDK
|
|
207
|
+
adapts the modal automatically. Do not add a strategy prop, toggle, or hardcoded mode.
|
|
208
|
+
|
|
209
|
+
Ask only the remaining unanswered requirements in one concise group:
|
|
210
|
+
- Where should Markee appear, what opens the modal, and what should the button say?
|
|
211
|
+
- Should it reuse the app's existing wallet, use SDK wallet discovery, or use
|
|
212
|
+
Markee-hosted card checkout without an app wallet (For Sale on Base only)? Inspect
|
|
213
|
+
existing connectors first; do not add a second wallet context or install a new
|
|
214
|
+
connector without agreement.
|
|
215
|
+
- Should the modal match the app theme or use specific colors, font, radius, and
|
|
216
|
+
light/dark/system mode?
|
|
217
|
+
- What public domain/page will host this integration? Use it as siteUrl for
|
|
218
|
+
automatic verification. For Vite/client rendering, add the board marker to the
|
|
219
|
+
static HTML as documented; do not claim localhost is verified.
|
|
220
|
+
- What should happen after a confirmed transaction: notification, refresh,
|
|
221
|
+
navigation, or callback? Are there additional mobile/accessibility requirements?
|
|
222
|
+
|
|
223
|
+
Then implement the agreed scope:
|
|
224
|
+
1. Install @markee_team/sdk@latest. No API URL or Markee API key is required.
|
|
225
|
+
Do not create an API proxy or add RPC/database credentials.
|
|
226
|
+
2. Use placement = { kind: 'board', chainId: 8453, address: extractedAddress }.
|
|
227
|
+
Use new MarkeeClient().snapshot(placement) to verify the board and read strategy,
|
|
228
|
+
name, minimum, and other metadata. The modal performs its own snapshot loading;
|
|
229
|
+
do not recreate that loading or strategy logic in the host app.
|
|
230
|
+
3. For React, use MarkeeModal from @markee_team/sdk/react in a client component
|
|
231
|
+
with open, onClose, and placement. Otherwise use createMarkee() from
|
|
232
|
+
@markee_team/sdk, then open({ placement }); close it on teardown.
|
|
233
|
+
4. If a host wallet exists, pass its selected EIP-1193 provider through the wallet
|
|
234
|
+
adapter. For ConnectKit/wagmi use the active connector. Resolve connect after
|
|
235
|
+
selection, reject cancellation, and do not silently switch wallet providers.
|
|
236
|
+
Otherwise omit wallet. Without a connected app account, the modal shows only
|
|
237
|
+
Pay, opening Markee-hosted checkout for supported boards. Do not install
|
|
238
|
+
Privy or collect card details in the host app.
|
|
239
|
+
5. Apply theme options while preserving the built-in modal layout. Handle onEvent
|
|
240
|
+
if needed; show success only for a confirmed event. Let the SDK manage review,
|
|
241
|
+
network switching, submission, and verification.
|
|
242
|
+
6. Verify build/types, loading of the supplied board, automatic strategy selection,
|
|
243
|
+
open/close behavior, theme, and wallet reuse. Do not sign or send transactions
|
|
244
|
+
during automated verification. Report changed files, checks, and limitations.
|
|
245
|
+
|
|
246
|
+
Check the installed release's supported features before promising functionality.
|
|
247
|
+
Wallet-funded flows are supported. Hosted card checkout requires Markee's backend
|
|
248
|
+
capability to be enabled; do not promise availability when it is disabled. Incoming
|
|
249
|
+
bridging is not available. Transactions and card funding use real funds.
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Pay by card without an app wallet
|
|
253
|
+
|
|
254
|
+
Without a connected app wallet, the modal shows **Pay** as its only payment action
|
|
255
|
+
and hides wallet balances and wallet-management sections. For Sale boards on Base
|
|
256
|
+
with MARKEE rewards support this flow
|
|
257
|
+
when the Markee backend enables hosted checkout. No Privy provider, payment keys or
|
|
258
|
+
API configuration is needed in the integrating app. Omit the `wallet` adapter.
|
|
259
|
+
|
|
260
|
+
The SDK opens Markee, where the user signs in, receives a Privy embedded wallet,
|
|
261
|
+
funds it through Stripe (Base USDC converted to ETH) or MoonPay (Base ETH), and confirms
|
|
262
|
+
the Markee payment. The contract sends MARKEE directly to that user's paying
|
|
263
|
+
wallet. The host receives `onEvent({ type: 'confirmed', hash })` only after
|
|
264
|
+
server-side receipt verification. Card funding alone is not a successful payment.
|
|
265
|
+
|
|
266
|
+
The checkout can resume after closing or refreshing. If a wallet submission has an
|
|
267
|
+
unknown result, it asks the user to check the existing transaction instead of
|
|
268
|
+
sending again. On browsers that block popups, it navigates to Markee in the same
|
|
269
|
+
tab. Reopen Pay after returning to recover the confirmed result.
|
|
270
|
+
|
|
271
|
+
Card availability, fees, minimum purchase amounts and identity checks depend on
|
|
272
|
+
the funding provider and user eligibility. Any unused USDC or ETH remains in the
|
|
273
|
+
user's wallet. Conversion uses a capped approval and maximum 1% slippage, with
|
|
274
|
+
wallet confirmation and Markee-sponsored conversion gas. For Rent, incoming
|
|
275
|
+
bridging and automatic rewards forwarding to a different wallet are outside this
|
|
276
|
+
checkout flow. If hosted checkout is unavailable, Pay is disabled with an
|
|
277
|
+
availability message; the modal does not fall back to asking for a wallet.
|
|
278
|
+
|
|
279
|
+
### Reuse a Markee login
|
|
280
|
+
|
|
281
|
+
Pay opens a temporary browser tab on Markee, where the existing Privy session is
|
|
282
|
+
restored before showing sign-in. The SDK does not copy login tokens into the host
|
|
283
|
+
app. The tab closes after the host verifies the payment. If tabs are blocked,
|
|
284
|
+
checkout falls back to a same-tab redirect. To always redirect, pass
|
|
285
|
+
`checkoutWindow: 'redirect'` (`checkoutWindow="redirect"` in React).
|
|
286
|
+
|
|
287
|
+
Session reuse requires the same exact Markee origin and Privy app ID. A login on
|
|
288
|
+
`www.markee.xyz` is not a login on a Vercel preview domain. Markee can set
|
|
289
|
+
`MARKEE_CHECKOUT_ORIGIN=https://www.markee.xyz` on its API deployment **after** the
|
|
290
|
+
checkout route is deployed there. Both deployments must use the same checkout KV,
|
|
291
|
+
signing secret, supported configuration and Privy app. Omit this setting to keep
|
|
292
|
+
checkout on the API origin. Integrators do not configure an API or checkout URL.
|
|
293
|
+
Existing pending checkout sessions retain their original destination.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type MarkeeClient } from './client.js';
|
|
2
|
+
import type { Action, CheckoutSession, CheckoutStatus, Placement, TransactionResult } from './types.js';
|
|
3
|
+
export declare function savedCheckout(client: MarkeeClient, placement: Placement): CheckoutSession | null;
|
|
4
|
+
export declare function checkoutStatus(client: MarkeeClient, session: CheckoutSession): Promise<CheckoutStatus>;
|
|
5
|
+
export declare function forgetCheckout(client: MarkeeClient, placement: Placement): void;
|
|
6
|
+
/** Call directly from a click handler to preserve popup permission. */
|
|
7
|
+
export declare function openHostedCheckout(client: MarkeeClient, placement: Placement, action: Action): Promise<TransactionResult>;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { Action, Address, AdminOperation, AdminResult, Authorization, BridgeStatus, ClaimQuote, EIP1193Provider, Hex, Placement, PreparedAction, SDKOptions, Snapshot, TransactionResult } from './types.js';
|
|
1
|
+
import type { Action, Address, AdminOperation, AdminResult, Authorization, BridgeStatus, ClaimQuote, EIP1193Provider, Hex, Placement, PreparedAction, SDKOptions, Snapshot, SiteVerification, TransactionResult } from './types.js';
|
|
2
|
+
/** Markee-hosted API used by integrations unless overridden for local development. */
|
|
3
|
+
export declare const DEFAULT_MARKEE_API_URL = "https://2staging.markee.xyz/api/sdk/v1";
|
|
2
4
|
export declare class MarkeeError extends Error {
|
|
3
5
|
code: string;
|
|
4
6
|
status?: number | undefined;
|
|
@@ -31,11 +33,14 @@ export declare class MarkeeClient {
|
|
|
31
33
|
private inMemoryPending;
|
|
32
34
|
private adminMemory;
|
|
33
35
|
private communityReceipts;
|
|
34
|
-
constructor(options
|
|
36
|
+
constructor(options?: SDKOptions);
|
|
35
37
|
request<T>(path: string, body?: unknown, signal?: AbortSignal): Promise<T>;
|
|
36
38
|
provider(): Promise<EIP1193Provider | null>;
|
|
37
39
|
account(): Promise<Address | null>;
|
|
38
40
|
connect(selected?: EIP1193Provider): Promise<Address>;
|
|
41
|
+
verifySite(placement: Placement, siteUrl: string): Promise<SiteVerification>;
|
|
42
|
+
private siteRequests;
|
|
43
|
+
registerSite(placement: Placement): void;
|
|
39
44
|
snapshot(placement: Placement, account?: Address | null, offset?: number, signal?: AbortSignal): Promise<Snapshot>;
|
|
40
45
|
prepare(placement: Placement, action: Action): Promise<PreparedAction>;
|
|
41
46
|
private ensureWallet;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
|
-
export { MarkeeClient, MarkeeError, discoverWallets } from './client.js';
|
|
2
|
+
export { MarkeeClient, MarkeeError, discoverWallets, DEFAULT_MARKEE_API_URL } from './client.js';
|
|
3
3
|
export type { PendingTransaction, DiscoveredWallet } from './client.js';
|
|
4
4
|
export { createMarkee, MarkeeModal } from './modal.js';
|
|
5
5
|
export type { ModalOptions } from './modal.js';
|
|
6
6
|
export { parseEth, formatEth } from './amount.js';
|
|
7
|
+
export { openHostedCheckout, checkoutStatus, savedCheckout } from './checkout.js';
|
|
8
|
+
export { createMarkeeSign, signContent } from './sign.js';
|
|
9
|
+
export type { MarkeeSignOptions } from './sign.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var p=class extends Error{constructor(t,a="MARKEE_ERROR",i){super(t);this.code=a;this.status=i;this.name="MarkeeError"}};async function E(){if(typeof window>"u")return[];let s=new Map,e=a=>{let i=a.detail;i?.provider?.request&&typeof i.info?.uuid=="string"&&s.set(i.info.uuid,{uuid:i.info.uuid,name:String(i.info.name).slice(0,80),provider:i.provider})};window.addEventListener("eip6963:announceProvider",e),window.dispatchEvent(new Event("eip6963:requestProvider")),await new Promise(a=>setTimeout(a,150)),window.removeEventListener("eip6963:announceProvider",e);let t=window.ethereum;return!s.size&&t?.request&&s.set("injected",{uuid:"injected",name:"Browser wallet",provider:t}),[...s.values()]}var x=s=>typeof s=="string"&&/^0x[\da-f]{40}$/i.test(s),T=s=>typeof s=="string"&&/^0x[\da-f]{64}$/i.test(s),k=class{constructor(e){this.options=e;let t=new URL(e.apiUrl);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new p("Use an HTTPS Markee API URL (HTTP is allowed on localhost).");this.apiUrl=t.href.replace(/\/$/,""),this.fetcher=e.fetch||globalThis.fetch.bind(globalThis)}apiUrl;fetcher;injected=null;sending=!1;inMemoryPending=[];adminMemory=null;communityReceipts={};async request(e,t,a){let i=await this.fetcher(`${this.apiUrl}/${e}`,{method:t===void 0?"GET":"POST",body:t===void 0?void 0:JSON.stringify(t),headers:t===void 0?void 0:{"Content-Type":"application/json"},credentials:"omit",signal:a||AbortSignal.timeout(55e3)}),r=await i.json().catch(()=>null);if(!i.ok)throw new p(r?.error||`Markee returned HTTP ${i.status}.`,r?.code,i.status);return r}async provider(){return this.options.wallet?this.options.wallet.getProvider():this.injected}async account(){let e=await this.provider();if(!e)return null;let t=await e.request({method:"eth_accounts"});return Array.isArray(t)&&x(t[0])?t[0]:null}async connect(e){let t=await this.provider();if(this.options.wallet)t||(t=await this.options.wallet.connect?.()||null);else{if(t=e||t,!t){let i=await E();if(i.length>1)throw new p("Select a browser wallet.","SELECT_WALLET");t=i[0]?.provider||null}this.injected=t}if(!t)throw new p("Connect a wallet in the app or install a browser wallet to continue.","NO_WALLET");let a=await t.request({method:"eth_requestAccounts"});if(!Array.isArray(a)||!x(a[0]))throw new p("The wallet did not return an account.");return a[0]}async snapshot(e,t,a,i){let r=new URLSearchParams({placement:JSON.stringify(e)});return t&&r.set("account",t),a!==void 0&&r.set("offset",String(a)),this.request(`snapshot?${r}`,void 0,i)}async prepare(e,t){let a=await this.account();if(!a)throw new p("Connect your wallet first.","NOT_CONNECTED");return this.request("prepare",{placement:e,account:a,action:t})}async ensureWallet(e,t){let a=await this.provider();if(!a||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("Your wallet account changed. Review this action again.","ACCOUNT_CHANGED");let i=Number(await a.request({method:"eth_chainId"}));if(i!==t&&await a.request({method:"wallet_switchEthereumChain",params:[{chainId:`0x${t.toString(16)}`}]}),i=Number(await a.request({method:"eth_chainId"})),i!==t||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("The wallet account or network changed. Review again.","WALLET_CHANGED");return a}async send(e){if(this.sending)throw new p("A wallet request is already in progress.");if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");if(this.pending(e.placement,e.transaction.from))throw new p("A transaction is still pending for this wallet and placement. Check it before submitting again.","PENDING_TRANSACTION");this.sending=!0;try{let a=await this.ensureWallet(e.transaction.from,e.transaction.chainId);if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");let{chainId:i,...r}=e.transaction,n=await a.request({method:"eth_sendTransaction",params:[r]});if(!T(n))throw new p("The wallet returned an unexpected transaction identifier. Check your wallet before retrying.");return this.persist([...this.records(),{preparation:e,hash:n}]),this.options.onEvent?.({type:"submitted",hash:n}),n}catch(a){throw this.options.onEvent?.({type:"error",message:a instanceof Error?a.message:String(a)}),a}finally{this.sending=!1}}async verify(e){let t=await this.request("verify",{id:e.preparation.id,hash:e.hash});return t.status!=="pending"&&(this.persist(this.records().filter(a=>a.hash!==e.hash)),t.status==="confirmed"&&this.options.onEvent?.({type:"confirmed",hash:t.hash})),t}async reconcile(e,t){if(!T(t))throw new p("Enter a valid replacement transaction hash.");let a=await this.request("verify",{id:e.preparation.id,hash:t});return a.status!=="pending"&&this.persist(this.records().filter(i=>i.hash!==e.hash)),a}storageKey(){return`markee:sdk:v1:pending:${this.apiUrl}`}records(){try{if(typeof localStorage>"u")return this.inMemoryPending;let e=JSON.parse(localStorage.getItem(this.storageKey())||"[]");return Array.isArray(e)?e.filter(t=>T(t?.hash)&&typeof t.preparation?.id=="string"&&x(t.preparation?.transaction?.from)&&t.preparation?.placement):[]}catch{return this.inMemoryPending}}persist(e){this.inMemoryPending=e;try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey(),JSON.stringify(e))}catch{}}pending(e,t){return this.records().find(a=>JSON.stringify(a.preparation.placement).toLowerCase()===JSON.stringify(e).toLowerCase()&&a.preparation.transaction.from.toLowerCase()===t.toLowerCase())}async quote(e){return this.request(`community/quote?${new URLSearchParams({chainId:String(e.chainId),community:e.community})}`)}async authorize(e,t){let a=await this.account();if(!a)throw new p("Connect your community council wallet first.");return this.request(`community/${t}`,{action:"challenge",chainId:e.chainId,community:e.community,account:a})}async executeAuthorization(e,t,a){if(this.pendingAuthorization())throw new p("An earlier community authorization is still processing. Check its status first.");let i=t.typedData,n=await(await this.ensureWallet(a,i.domain.chainId)).request({method:"eth_signTypedData_v4",params:[a,JSON.stringify({...i,types:{...i.types,EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}]}})]});if(typeof n!="string"||!/^0x[\da-f]+$/i.test(n))throw new p("Wallet did not return a typed-data signature.");return this.saveAuthorization({kind:e,nonce:t.nonce,signature:n,account:a,community:i.domain.verifyingContract,chainId:i.domain.chainId}),this.resumeAuthorization()}pendingAuthorization(){try{let e=typeof localStorage>"u"?this.adminMemory:JSON.parse(localStorage.getItem(`${this.storageKey()}:admin`)||"null");return e&&["activate","claim"].includes(e.kind)&&x(e.account)&&x(e.community)&&typeof e.nonce=="string"&&typeof e.signature=="string"?e:null}catch{return this.adminMemory}}saveAuthorization(e){this.adminMemory=e;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:admin`,JSON.stringify(e))}catch{}}async resumeAuthorization(){let e=this.pendingAuthorization();if(!e)throw new p("There is no pending community authorization.");let t=await this.request(`community/${e.kind}`,{action:"verify",nonce:e.nonce,signature:e.signature});if(t.status==="complete"&&t.result){let a=`${e.chainId}:${e.community.toLowerCase()}`;this.communityReceipts[a]=t.result;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:community:${a}`,JSON.stringify(t.result))}catch{}}return(t.status==="complete"||t.status==="failed")&&this.saveAuthorization(null),t}communityReceipt(e){let t=`${e.chainId}:${e.community.toLowerCase()}`;try{let a=typeof localStorage>"u"?this.communityReceipts[t]:JSON.parse(localStorage.getItem(`${this.storageKey()}:community:${t}`)||"null");return a&&T(a.transactionHash)?a:null}catch{return this.communityReceipts[t]||null}}bridgeStatus(e,t,a,i){return this.request(`community/status?${new URLSearchParams({protocol:e,transactionHash:t,fromChainId:String(a),toChainId:String(i)})}`)}recordView(e,t,a){return this.request("views",{address:e,message:t,url:a})}};function g(s,e=!1){let t=s.trim();if(!/^\d+(\.\d{0,18})?$/.test(t))throw new Error("Enter an ETH amount with up to 18 decimal places.");let[a,i=""]=t.split("."),r=BigInt(a)*10n**18n+BigInt(i.padEnd(18,"0"));if(!e&&r===0n||r>=2n**256n)throw new Error("Enter a positive amount.");return r.toString()}function m(s,e=6){let t=BigInt(s),a=t<0n?"-":"",i=t<0n?-t:t,r=(i%10n**18n).toString().padStart(18,"0").slice(0,e).replace(/0+$/,"");return i>0n&&i<10n**BigInt(18-e)?`${a}<0.${"0".repeat(e-1)}1`:`${a}${i/10n**18n}${r?`.${r}`:""}`}function C(s){return`${s.slice(0,6)}\u2026${s.slice(-4)}`}function l(s){return String(s).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}var H=`
|
|
1
|
+
var U="https://2staging.markee.xyz/api/sdk/v1",u=class extends Error{constructor(t,a="MARKEE_ERROR",r){super(t);this.code=a;this.status=r;this.name="MarkeeError"}};async function P(){if(typeof window>"u")return[];let n=new Map,e=a=>{let r=a.detail;r?.provider?.request&&typeof r.info?.uuid=="string"&&n.set(r.info.uuid,{uuid:r.info.uuid,name:String(r.info.name).slice(0,80),provider:r.provider})};window.addEventListener("eip6963:announceProvider",e),window.dispatchEvent(new Event("eip6963:requestProvider")),await new Promise(a=>setTimeout(a,150)),window.removeEventListener("eip6963:announceProvider",e);let t=window.ethereum;return!n.size&&t?.request&&n.set("injected",{uuid:"injected",name:"Browser wallet",provider:t}),[...n.values()]}var C=n=>typeof n=="string"&&/^0x[\da-f]{40}$/i.test(n),A=n=>typeof n=="string"&&/^0x[\da-f]{64}$/i.test(n),T=class{constructor(e={}){this.options=e;let t=new URL(e.apiUrl??U);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new u("Use an HTTPS Markee API URL (HTTP is allowed on localhost).");this.apiUrl=t.href.replace(/\/$/,""),this.fetcher=e.fetch||globalThis.fetch.bind(globalThis)}apiUrl;fetcher;injected=null;sending=!1;inMemoryPending=[];adminMemory=null;communityReceipts={};async request(e,t,a){let r=await this.fetcher(`${this.apiUrl}/${e}`,{method:t===void 0?"GET":"POST",body:t===void 0?void 0:JSON.stringify(t),headers:t===void 0?void 0:{"Content-Type":"application/json"},credentials:"omit",signal:a||AbortSignal.timeout(55e3)}),i=await r.json().catch(()=>null);if(!r.ok)throw new u(i?.error||`Markee returned HTTP ${r.status}.`,i?.code,r.status);return i}async provider(){return this.options.wallet?this.options.wallet.getProvider():this.injected}async account(){let e=await this.provider();if(!e)return null;let t=await e.request({method:"eth_accounts"});return Array.isArray(t)&&C(t[0])?t[0]:null}async connect(e){let t=await this.provider();if(this.options.wallet)t||(t=await this.options.wallet.connect?.()||null);else{if(t=e||t,!t){let r=await P();if(r.length>1)throw new u("Select a browser wallet.","SELECT_WALLET");t=r[0]?.provider||null}this.injected=t}if(!t)throw new u("Connect a wallet in the app or install a browser wallet to continue.","NO_WALLET");let a=await t.request({method:"eth_requestAccounts"});if(!Array.isArray(a)||!C(a[0]))throw new u("The wallet did not return an account.");return a[0]}verifySite(e,t){return this.request("sites/verify",{placement:e,siteUrl:t})}siteRequests=new Map;registerSite(e){if(!this.options.siteUrl)return;let t=JSON.stringify([e,this.options.siteUrl]);if(this.siteRequests.has(t))return;let a=this.verifySite(e,this.options.siteUrl);this.siteRequests.set(t,a),a.then(r=>this.options.onSiteVerification?.(r),r=>this.options.onSiteVerification?.({verified:!1,url:this.options.siteUrl,message:r instanceof Error?r.message:"Site verification failed."})).catch(()=>{})}async snapshot(e,t,a,r){let i=new URLSearchParams({placement:JSON.stringify(e)});return t&&i.set("account",t),a!==void 0&&i.set("offset",String(a)),this.request(`snapshot?${i}`,void 0,r)}async prepare(e,t){let a=await this.account();if(!a)throw new u("Connect your wallet first.","NOT_CONNECTED");return this.request("prepare",{placement:e,account:a,action:t})}async ensureWallet(e,t){let a=await this.provider();if(!a||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new u("Your wallet account changed. Review this action again.","ACCOUNT_CHANGED");let r=Number(await a.request({method:"eth_chainId"}));if(r!==t&&await a.request({method:"wallet_switchEthereumChain",params:[{chainId:`0x${t.toString(16)}`}]}),r=Number(await a.request({method:"eth_chainId"})),r!==t||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new u("The wallet account or network changed. Review again.","WALLET_CHANGED");return a}async send(e){if(this.sending)throw new u("A wallet request is already in progress.");if(e.expiresAt<=Date.now())throw new u("This review expired. Prepare the action again.","REVIEW_EXPIRED");if(this.pending(e.placement,e.transaction.from))throw new u("A transaction is still pending for this wallet and placement. Check it before submitting again.","PENDING_TRANSACTION");this.sending=!0;try{let a=await this.ensureWallet(e.transaction.from,e.transaction.chainId);if(e.expiresAt<=Date.now())throw new u("This review expired. Prepare the action again.","REVIEW_EXPIRED");let{chainId:r,...i}=e.transaction,s=await a.request({method:"eth_sendTransaction",params:[i]});if(!A(s))throw new u("The wallet returned an unexpected transaction identifier. Check your wallet before retrying.");return this.persist([...this.records(),{preparation:e,hash:s}]),this.options.onEvent?.({type:"submitted",hash:s}),s}catch(a){throw this.options.onEvent?.({type:"error",message:a instanceof Error?a.message:String(a)}),a}finally{this.sending=!1}}async verify(e){let t=await this.request("verify",{id:e.preparation.id,hash:e.hash});return t.status!=="pending"&&(this.persist(this.records().filter(a=>a.hash!==e.hash)),t.status==="confirmed"&&this.options.onEvent?.({type:"confirmed",hash:t.hash})),t}async reconcile(e,t){if(!A(t))throw new u("Enter a valid replacement transaction hash.");let a=await this.request("verify",{id:e.preparation.id,hash:t});return a.status!=="pending"&&this.persist(this.records().filter(r=>r.hash!==e.hash)),a}storageKey(){return`markee:sdk:v1:pending:${this.apiUrl}`}records(){try{if(typeof localStorage>"u")return this.inMemoryPending;let e=JSON.parse(localStorage.getItem(this.storageKey())||"[]");return Array.isArray(e)?e.filter(t=>A(t?.hash)&&typeof t.preparation?.id=="string"&&C(t.preparation?.transaction?.from)&&t.preparation?.placement):[]}catch{return this.inMemoryPending}}persist(e){this.inMemoryPending=e;try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey(),JSON.stringify(e))}catch{}}pending(e,t){return this.records().find(a=>JSON.stringify(a.preparation.placement).toLowerCase()===JSON.stringify(e).toLowerCase()&&a.preparation.transaction.from.toLowerCase()===t.toLowerCase())}async quote(e){return this.request(`community/quote?${new URLSearchParams({chainId:String(e.chainId),community:e.community})}`)}async authorize(e,t){let a=await this.account();if(!a)throw new u("Connect your community council wallet first.");return this.request(`community/${t}`,{action:"challenge",chainId:e.chainId,community:e.community,account:a})}async executeAuthorization(e,t,a){if(this.pendingAuthorization())throw new u("An earlier community authorization is still processing. Check its status first.");let r=t.typedData,s=await(await this.ensureWallet(a,r.domain.chainId)).request({method:"eth_signTypedData_v4",params:[a,JSON.stringify({...r,types:{...r.types,EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}]}})]});if(typeof s!="string"||!/^0x[\da-f]+$/i.test(s))throw new u("Wallet did not return a typed-data signature.");return this.saveAuthorization({kind:e,nonce:t.nonce,signature:s,account:a,community:r.domain.verifyingContract,chainId:r.domain.chainId}),this.resumeAuthorization()}pendingAuthorization(){try{let e=typeof localStorage>"u"?this.adminMemory:JSON.parse(localStorage.getItem(`${this.storageKey()}:admin`)||"null");return e&&["activate","claim"].includes(e.kind)&&C(e.account)&&C(e.community)&&typeof e.nonce=="string"&&typeof e.signature=="string"?e:null}catch{return this.adminMemory}}saveAuthorization(e){this.adminMemory=e;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:admin`,JSON.stringify(e))}catch{}}async resumeAuthorization(){let e=this.pendingAuthorization();if(!e)throw new u("There is no pending community authorization.");let t=await this.request(`community/${e.kind}`,{action:"verify",nonce:e.nonce,signature:e.signature});if(t.status==="complete"&&t.result){let a=`${e.chainId}:${e.community.toLowerCase()}`;this.communityReceipts[a]=t.result;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:community:${a}`,JSON.stringify(t.result))}catch{}}return(t.status==="complete"||t.status==="failed")&&this.saveAuthorization(null),t}communityReceipt(e){let t=`${e.chainId}:${e.community.toLowerCase()}`;try{let a=typeof localStorage>"u"?this.communityReceipts[t]:JSON.parse(localStorage.getItem(`${this.storageKey()}:community:${t}`)||"null");return a&&A(a.transactionHash)?a:null}catch{return this.communityReceipts[t]||null}}bridgeStatus(e,t,a,r){return this.request(`community/status?${new URLSearchParams({protocol:e,transactionHash:t,fromChainId:String(a),toChainId:String(r)})}`)}recordView(e,t,a){return this.request("views",{address:e,message:t,url:a})}};var N=(n,e)=>`markee:checkout:v1:${n.apiUrl}:${JSON.stringify(e)}`;function j(n,e){try{let t=JSON.parse(localStorage.getItem(N(n,e))||"null");return t&&typeof t.id=="string"&&/^[a-f0-9]{48}$/.test(t.id)&&/^[a-f0-9]{64}$/.test(t.readToken)&&/^[a-f0-9]{64}$/.test(t.writeToken)&&Number.isFinite(t.expiresAt)?t:null}catch{return null}}async function B(n,e){return n.request("checkout/status",{id:e.id,token:e.readToken})}function S(n,e){try{localStorage.removeItem(N(n,e))}catch{}}async function F(n,e,t){let a=n.options.checkoutWindow==="redirect"?null:window.open("about:blank","_blank");a&&(a.opener=null);let r=j(n,e);try{if(r){let s=await B(n,r).catch(o=>{if(o instanceof u&&o.status===404)return S(n,e),r=null,null;throw o});if(s?.result?.status==="confirmed"||s?.result?.status==="reverted")return S(n,e),a?.close(),s.result;r&&s&&r.expiresAt<Date.now()&&["created","ready"].includes(s.status)&&(S(n,e),r=null)}if(!r){r=await n.request("checkout/create",{placement:e,action:t,origin:window.location.origin});try{localStorage.setItem(N(n,e),JSON.stringify(r))}catch{}}let i=new URL(`/checkout/${r.id}`,r.checkoutOrigin||n.apiUrl);if(i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1"].includes(i.hostname)))throw new Error("Invalid Markee checkout destination.");if(i.hash=new URLSearchParams({token:r.writeToken}).toString(),a)a.location.replace(i.href);else throw window.location.assign(i.href),new Error("Continuing payment on Markee.");for(let s=0;s<1800;s++){let o=await B(n,r);if(o.result&&o.status==="confirmed")return S(n,e),a.close(),o.result;if(o.status==="reverted")throw S(n,e),new Error("Payment reverted. Any unspent funds remain in your Markee wallet.");if(a.closed)throw new Error("Markee checkout closed. Choose Pay again to resume; funding alone does not complete payment.");await new Promise(d=>setTimeout(d,3e3))}throw new Error("Checkout is still pending. Reopen it to check the payment; do not pay again.")}catch(i){throw r||a?.close(),i}}function b(n,e=!1){let t=n.trim();if(!/^\d+(\.\d{0,18})?$/.test(t))throw new Error("Enter an ETH amount with up to 18 decimal places.");let[a,r=""]=t.split("."),i=BigInt(a)*10n**18n+BigInt(r.padEnd(18,"0"));if(!e&&i===0n||i>=2n**256n)throw new Error("Enter a positive amount.");return i.toString()}function m(n,e=6){let t=BigInt(n),a=t<0n?"-":"",r=t<0n?-t:t,i=(r%10n**18n).toString().padStart(18,"0").slice(0,e).replace(/0+$/,"");return r>0n&&r<10n**BigInt(18-e)?`${a}<0.${"0".repeat(e-1)}1`:`${a}${r/10n**18n}${i?`.${i}`:""}`}function E(n){return`${n.slice(0,6)}\u2026${n.slice(-4)}`}function l(n){return String(n).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}var K=`
|
|
2
2
|
:host{all:initial;font-family:var(--markee-font-family);color:var(--markee-text);font-size:14px;line-height:1.5;color-scheme:var(--markee-color-scheme)}
|
|
3
3
|
|
|
4
4
|
*{box-sizing:border-box}
|
|
@@ -56,7 +56,6 @@ form{display:grid;gap:16px}
|
|
|
56
56
|
.divider{height:1px;background:var(--markee-border);margin:20px 0}
|
|
57
57
|
a{color:var(--markee-link);text-decoration:none;overflow-wrap:anywhere}
|
|
58
58
|
ul{padding-left:20px;font-size:14px}
|
|
59
|
-
.review li{margin-bottom:9px;overflow-wrap:anywhere}
|
|
60
59
|
.loading{padding:40px;text-align:center;color:var(--markee-muted)}
|
|
61
60
|
.empty{padding:24px 8px;text-align:center}
|
|
62
61
|
.spinner{display:inline-block;width:14px;height:14px;border-radius:100%;border:2px solid var(--markee-border);border-top-color:var(--markee-muted);animation:spin 1s linear infinite;margin-right:8px}
|
|
@@ -64,7 +63,26 @@ ul{padding-left:20px;font-size:14px}
|
|
|
64
63
|
}
|
|
65
64
|
footer{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border);background:var(--markee-background);color:var(--markee-muted);font-size:11px}
|
|
66
65
|
.mono{font-family:ui-monospace,monospace}
|
|
67
|
-
.
|
|
66
|
+
.payment-review{display:grid;gap:16px}
|
|
67
|
+
.review-message{border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-input-background);padding:16px 18px;min-width:0}
|
|
68
|
+
.review-message .message{font-size:14px;margin:0}
|
|
69
|
+
.review-summary{padding:0 4px}
|
|
70
|
+
.review-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px solid var(--markee-border);font-size:13px}
|
|
71
|
+
.review-row:last-child{border-bottom:0}
|
|
72
|
+
.review-row>span{color:var(--markee-muted)}
|
|
73
|
+
.review-row strong{text-align:right;font-family:ui-monospace,monospace;font-size:13px;overflow-wrap:anywhere}
|
|
74
|
+
.review-callout{padding:16px;border:1px solid var(--markee-accent-border);border-radius:var(--markee-control-radius);background:var(--markee-accent-surface);color:var(--markee-accent-surface-text)}
|
|
75
|
+
.review-callout strong{display:block;font-family:ui-monospace,monospace;font-size:13px;line-height:1.45}
|
|
76
|
+
.review-callout p{margin:6px 0 0;font-size:12px;line-height:1.5}
|
|
77
|
+
.review-details{font-size:11px;color:var(--markee-muted)}
|
|
78
|
+
.review-details summary{cursor:pointer;color:var(--markee-link);font-size:12px}
|
|
79
|
+
.review-details .review-row{font-size:11px;padding:7px 0}
|
|
80
|
+
.review-details .review-row strong{font-size:11px;color:var(--markee-text)}
|
|
81
|
+
.review-address{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0}
|
|
82
|
+
.review-copy{padding:3px 7px;font-size:10px;line-height:1.3;color:var(--markee-link);white-space:nowrap}
|
|
83
|
+
.review-details p{margin:8px 0}
|
|
84
|
+
.review-footer .footer-actions{justify-content:flex-end}
|
|
85
|
+
.review-footer .footer-actions>.primary:last-child{margin-left:0}
|
|
68
86
|
.wallets{display:grid;gap:10px}
|
|
69
87
|
|
|
70
88
|
|
|
@@ -88,6 +106,7 @@ footer{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border)
|
|
|
88
106
|
.funding-card>label{font-size:11px;color:var(--markee-muted);font-weight:500;margin-bottom:8px}.amount-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.amount-value{display:flex;gap:6px;align-items:baseline;min-width:0;flex:1 1 140px}.amount-value input{background:transparent;border:0;border-radius:2px;box-shadow:none;font-family:ui-monospace,monospace;font-size:23px;font-weight:600;min-width:0;width:100%;padding:3px 0;color:var(--markee-text)}.amount-value>span{font-size:11px;color:var(--markee-muted);white-space:nowrap}.amount-presets{display:flex;gap:6px;margin-left:auto}.amount-presets button{color:var(--markee-link)}.amount-presets button[aria-pressed=true]{border-color:var(--markee-link);background:var(--markee-selected);color:var(--markee-selected-text)}
|
|
89
107
|
.funding-caption{display:flex;justify-content:space-between;flex-wrap:wrap;gap:4px 10px;margin-top:9px;color:var(--markee-muted);font-size:10px}.funding-tools{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;border-top:1px solid var(--markee-border);margin-top:13px;padding-top:12px}.funding-tools .meta{font-size:10px}.funding-hint{font-size:11px;margin:0}.funding-hint+.note{margin:0;font-size:11px}
|
|
90
108
|
.footer-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.footer-actions>.primary:last-child{margin-left:auto}.footer-actions:empty{display:none}.footer-meta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px;margin-top:10px;font-size:10px}.footer-meta .text-button{font-size:10px}
|
|
109
|
+
.payment-choice-footer .footer-actions{justify-content:flex-end}.payment-choice-footer .footer-actions>.primary:last-child{margin-left:0}
|
|
91
110
|
|
|
92
111
|
@media(max-width:560px){.overlay{padding:8px;align-items:flex-end}
|
|
93
112
|
.panel{border-radius:var(--markee-radius) var(--markee-radius) var(--markee-control-radius) var(--markee-control-radius);max-height:94dvh}
|
|
@@ -99,9 +118,25 @@ header{padding:20px 18px}
|
|
|
99
118
|
footer{padding:12px 18px}
|
|
100
119
|
.btn{padding:10px 12px}
|
|
101
120
|
.compact{padding:5px 9px}.text-button{padding:0}.footer-actions>.btn{flex:1;white-space:normal}.footer-actions>.primary:last-child{margin-left:0}
|
|
121
|
+
.review-footer .footer-actions>.btn{flex:0 1 auto}
|
|
122
|
+
.payment-choice-footer .footer-actions>.btn{flex:0 1 auto}
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
@media(prefers-reduced-motion:reduce){*{animation:none!important;scroll-behavior:auto!important}
|
|
105
126
|
}
|
|
106
127
|
|
|
107
|
-
`;var B={background:"#fbfcff",surface:"#ffffff",text:"#181b21",muted:"#687080",border:"#dce1ea",inputBackground:"#ffffff",inputText:"#202737",primary:"#282e3e",primaryText:"#ffffff",accent:"#c9f1a7",accentText:"#2b3c20",accentSurface:"#f1f7ea",accentSurfaceText:"#4e6535",accentBorder:"#cde3b5",selected:"#e9edf7",selectedText:"#242c47",info:"#edf1f9",infoText:"#52617b",error:"#fff0f0",errorText:"#9c3540",success:"#edf7e6",successText:"#40602f",link:"#4762a5",focusRing:"#5871c8",overlay:"#17203888"},O={background:"#151923",surface:"#202633",text:"#f0f3f8",muted:"#a6b1c3",border:"#434f63",inputBackground:"#10151e",inputText:"#f0f3f8",primary:"#dde6fa",primaryText:"#182238",accent:"#c9f1a7",accentText:"#24361a",accentSurface:"#243221",accentSurfaceText:"#c4e5ad",accentBorder:"#526b40",selected:"#313d53",selectedText:"#edf3ff",info:"#243149",infoText:"#bdcff1",error:"#44262e",errorText:"#ffbdc5",success:"#233b2b",successText:"#b5e4bf",link:"#adc5ff",focusRing:"#a1b4ff",overlay:"#030711b8"},N='Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',F=s=>`--markee-${s.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`;function R(s,e){let t,a=(i={})=>{t?.(),t=void 0;let r=i.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)"):void 0,n=()=>{let d=i.mode==="dark"||r?.matches?"dark":"light",c=d==="dark"?O:B;s.dataset.markeeTheme=d,s.style.setProperty("--markee-color-scheme",d);for(let u of Object.keys(c)){let w=i.colors?.[u];s.style.setProperty(F(u),w&&CSS.supports("color",w)?w:c[u])}s.style.setProperty("--markee-font-family",i.fontFamily&&CSS.supports("font-family",i.fontFamily)?i.fontFamily:N);let f=typeof i.radius=="number"&&Number.isFinite(i.radius)?Math.max(0,Math.min(48,i.radius)):22;s.style.setProperty("--markee-radius",`${f}px`),s.style.setProperty("--markee-card-radius",`${f*.64}px`),s.style.setProperty("--markee-control-radius",`${f*.45}px`),s.style.setProperty("--markee-small-radius",`${f*.32}px`)};n(),r&&(r.addEventListener("change",n),t=()=>r.removeEventListener("change",n))};return a(e),{set:a,destroy(){t?.(),t=void 0}}}var v=2628000n,$=10n**15n,S=(...s)=>s.reduce((e,t)=>e>t?e:t,0n);function A(s,e){let t=s.strategy==="rent",a=t?(BigInt(s.minimum)+$-1n)/$*$:e?1n:BigInt(s.minimum),i=s.entries.filter(u=>u.address.toLowerCase()!==e?.address.toLowerCase()),r=S(...i.map(u=>BigInt(u.score))),n=!!e&&e.address.toLowerCase()===s.top?.toLowerCase();if(!t){let u=BigInt(e?.totalFunds??"0");return{minimum:a,boost:S(a,r+$-u,n?u:0n),double:n&&u>0n}}let c=!!e&&s.wallet?.backedMarkee?.toLowerCase()===e.address.toLowerCase()?BigInt(s.wallet.flowRate):0n,f=S(BigInt(e?.aggregateRate??"0")-c);return{minimum:a,boost:S(a,(r-f)*v+$,n?c*v*2n:0n),double:n&&c>0n}}var M=s=>{let e=BigInt(s);return`${e/10n**18n}.${(e%10n**18n).toString().padStart(18,"0")}`.replace(/\.?0+$/,"")||"0"},o=(s,e,t="",a="")=>`<button type="button" class="btn ${t}" data-cmd="${s}" ${a}>${e}</button>`,z=(s,e)=>/^https:\/\//.test(s)?`<a href="${l(s)}" target="_blank" rel="noopener noreferrer">${l(e)} \u2197</a>`:"",P=class{constructor(e,t){this.client=e;this.options=t;if(typeof document>"u")throw new Error("Open the Markee modal in a browser.");this.previousFocus=document.activeElement,this.previousOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.host=document.createElement("div"),this.host.setAttribute("data-markee-modal",""),this.root=this.host.attachShadow({mode:"open"}),this.theme=R(this.host,t.theme??e.options.theme),document.body.appendChild(this.host),this.root.addEventListener("click",this.onClick),this.root.addEventListener("submit",this.onSubmit),this.root.addEventListener("keydown",this.onKey),this.root.addEventListener("input",()=>{this.captureDraft(),this.updateFields()}),this.render(),this.root.querySelector('[data-cmd="close"]')?.focus(),this.reload(),this.watchAccount()}host;root;theme;snapshot;account=null;tab="main";leaderboardOpen=!1;initialSelection=!1;renderedView="";form;review;authorization;adminResult;adminProcessing=!1;result;pending;wallets;busy=!1;error="";closed=!1;epoch=0;timer;accountTimer;watched;previousFocus;previousOverflow;abort=new AbortController;drafts=new Map;viewObserver;viewed=new Set;walletChanged=()=>{this.initialSelection=!1,this.review=void 0,this.authorization=void 0,this.form=void 0,this.result=void 0,this.error="Wallet changed. Refreshing this placement\u2026",this.reload()};close(){this.closed||(this.closed=!0,this.abort.abort(),clearTimeout(this.timer),clearTimeout(this.accountTimer),this.viewObserver?.disconnect(),this.theme.destroy(),this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.host.remove(),document.body.style.overflow=this.previousOverflow,this.previousFocus?.focus(),this.options.onClose?.())}setTheme(e){this.closed||this.theme.set(e)}async watchAccount(){try{let e=await this.client.provider();e!==this.watched&&(this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.watched=e||void 0,e?.on?.("accountsChanged",this.walletChanged),e?.on?.("chainChanged",this.walletChanged)),(await this.client.account())?.toLowerCase()!==this.account?.toLowerCase()&&!this.busy&&this.walletChanged()}catch{}this.closed||(this.accountTimer=setTimeout(()=>void this.watchAccount(),2e3))}async reload(e){let t=++this.epoch;try{let a=await this.client.account(),i=await this.client.snapshot(this.options.placement,a,e,this.abort.signal);if(this.closed||t!==this.epoch)return;if(this.account=a,this.snapshot=i,this.error="",this.form&&(this.form.entry=i.entries.find(n=>n.address.toLowerCase()===this.form.entry.address.toLowerCase())??this.form.entry),!this.initialSelection&&a){this.initialSelection=!0;let n=i.entries.find(d=>d.address.toLowerCase()===i.wallet?.backedMarkee?.toLowerCase())??i.entries.find(d=>d.owner.toLowerCase()===a.toLowerCase());n&&!this.form&&!this.drafts.get("create")?.message&&(this.form={kind:i.strategy==="rent"?"stream":"fund",entry:n})}this.options.placement.kind==="gardens-community"&&(this.adminResult=this.client.communityReceipt(this.options.placement)||void 0),this.pending=a?this.client.pending(this.options.placement,a):void 0;let r=this.client.pendingAuthorization();this.adminProcessing=!!r&&this.options.placement.kind==="gardens-community"&&r.account.toLowerCase()===a?.toLowerCase()&&r.community.toLowerCase()===this.options.placement.community.toLowerCase()&&r.chainId===this.options.placement.chainId,this.render(),this.pending&&this.poll()}catch(a){!this.closed&&t===this.epoch&&this.fail(a)}}fail(e){this.error=e instanceof Error?e.message:String(e),this.render()}async task(e){if(!this.busy){this.busy=!0,this.error="",this.render();try{await e()}catch(t){this.fail(t)}finally{this.busy=!1,this.render()}}}async connect(){if(!this.client.options.wallet){let e=await E();if(e.length>1){this.wallets=e,this.render();return}}this.host.style.visibility="hidden";try{await this.client.connect()}finally{this.host.style.visibility=""}await this.reload()}async prepare(e){if(this.pending)throw new Error("Check your pending transaction before preparing another action.");if(!this.account){await this.connect();return}this.review=await this.client.prepare(this.options.placement,e),this.authorization=void 0}async poll(){if(clearTimeout(this.timer),!(!this.pending||this.closed)){try{let e=this.pending,t=await this.client.verify(e);if(this.closed||this.pending?.hash!==e.hash)return;if(t.status!=="pending"){if(this.pending=void 0,this.result=t,this.error="",await this.reload(),t.createdMarkee&&this.snapshot?.strategy==="rent"){let a=this.snapshot.entries.find(r=>r.address.toLowerCase()===t.createdMarkee.toLowerCase()),i=e.preparation.action;if(i.kind==="create"){this.form={kind:"stream",entry:a||{address:t.createdMarkee,owner:e.preparation.transaction.from,message:i.message,name:i.name,score:"0",totalFunds:"0",aggregateRate:"0",legacyFloor:"0",moderated:!1,views:0}};let r=this.drafts.get("create")?.amount;r&&this.drafts.set(this.draftKey(),{amount:r})}}this.render();return}}catch(e){this.closed||this.fail(e)}!this.closed&&this.pending&&(this.timer=setTimeout(()=>void this.poll(),5e3))}}async applyAdmin(e){if(this.authorization=void 0,this.adminProcessing=e.status==="working"||e.status==="submitted",e.status==="complete"&&(this.adminResult=e.result,await this.reload()),e.status==="failed")throw new Error(e.error||"Community action failed.")}onClick=e=>{let t=e.target.closest("[data-cmd]");if(!t)return;let a=t.dataset.cmd;if(a==="close"){this.close();return}if(!this.busy){if(this.captureDraft(),a==="leaderboard"){this.leaderboardOpen=!this.leaderboardOpen,this.render();return}if(a==="create"){this.tab="main",this.form=void 0,this.review=void 0,this.render();return}if(a.startsWith("tab:")){this.tab=a.slice(4),this.review=void 0,this.authorization=void 0,this.render();return}if(a==="back"){this.review||this.authorization||this.wallets?(this.review=void 0,this.authorization=void 0,this.wallets=void 0):this.tab!=="main"?this.tab="main":this.form?.kind.startsWith("edit")?this.form={kind:this.snapshot.strategy==="rent"?"stream":"fund",entry:this.form.entry}:this.form=void 0,this.render();return}if(a.startsWith("preset:")&&this.snapshot){let i=this.root.querySelector("#amount");if(i){let r=A(this.snapshot,this.form?.entry);i.value=M((a==="preset:min"?r.minimum:r.boost).toString()),this.captureDraft(),this.updateFields()}return}if(a.startsWith("form:")){let[,i,r]=a.split(":"),n=this.snapshot?.entries.find(d=>d.address===r);n&&(this.form={kind:i,entry:n},this.tab="main"),this.render();return}this.task(async()=>{if(a==="connect")await this.connect();else if(a.startsWith("wallet:"))await this.client.connect(this.wallets[Number(a.slice(7))].provider),this.wallets=void 0,await this.reload();else if(a==="refresh")await this.reload();else if(a==="more")await this.reload(this.snapshot?.nextOffset??void 0);else if(a==="send"&&this.review){let i=this.review,r=await this.client.send(i);this.pending={preparation:i,hash:r},this.review=void 0,this.form=void 0,this.result=void 0,this.poll()}else if(a==="check")await this.poll();else if(["stop","withdraw-buffer","settle"].includes(a))await this.prepare({kind:a});else if(a.startsWith("claim-refund:")||a.startsWith("connect-refund:")||a.startsWith("claim-top:")){let[i,r]=a.split(":");await this.prepare({kind:i,markee:r})}else if(a==="activate"||a==="claim"){let i=this.options.placement;if(i.kind!=="gardens-community"||!this.account)return;let r=this.account;this.authorization={kind:a,account:r,value:await this.client.authorize(i,a)},this.review=void 0}else if(a==="sign"&&this.authorization){let i=this.authorization;try{await this.applyAdmin(await this.client.executeAuthorization(i.kind,i.value,i.account))}finally{this.client.pendingAuthorization()&&(this.authorization=void 0,this.adminProcessing=!0)}}else if(a==="admin-check")await this.applyAdmin(await this.client.resumeAuthorization());else if(a==="bridge"&&this.adminResult){let i=await this.client.bridgeStatus(this.adminResult.bridgeProtocol||"none",this.adminResult.transactionHash,this.snapshot.chainId,this.options.placement.chainId);this.error=`Treasury transfer status: ${i.status.replace(/_/g," ")}.`}})}};onSubmit=e=>{if(e.preventDefault(),this.busy)return;this.captureDraft();let t=e.target,a=new FormData(t),i=r=>String(a.get(r)||"");this.task(async()=>{if(t.dataset.form==="create")this.snapshot?.strategy==="rent"&&g(i("amount")),await this.prepare({kind:"create",message:i("message"),name:i("name"),...this.snapshot?.strategy==="sale"?{amount:g(i("amount"),!0)}:{}});else if(t.dataset.form==="balance")await this.prepare({kind:i("kind"),amount:g(i("amount"))});else if(this.form){let{kind:r,entry:n}=this.form;r==="fund"?await this.prepare({kind:r,markee:n.address,amount:g(i("amount"))}):r==="stream"?await this.prepare({kind:r,markee:n.address,monthlyAmount:g(i("amount"))}):r==="edit-message"?await this.prepare({kind:r,markee:n.address,message:i("message")}):await this.prepare({kind:r,markee:n.address,name:i("name")})}})};draftKey(){return this.tab!=="main"?this.tab:this.form?`${this.form.kind}:${this.form.entry.address}`:"create"}captureDraft(){let e=this.root.querySelector("form");e&&this.drafts.set(this.draftKey(),Object.fromEntries([...new FormData(e)].map(([t,a])=>[t,String(a)])))}onKey=e=>{let t=e;if(t.key==="Escape"&&(t.preventDefault(),this.close()),t.key!=="Tab"||this.host.style.visibility==="hidden")return;let a=[...this.root.querySelectorAll("button:not(:disabled),a[href],input,textarea,select")],i=a[0],r=a[a.length-1];t.shiftKey&&this.root.activeElement===i?(t.preventDefault(),r?.focus()):!t.shiftKey&&this.root.activeElement===r&&(t.preventDefault(),i?.focus())};field(e,t,a="",i="",r=!1){let n=e==="message"?this.snapshot?.maxMessageBytes:e==="name"?this.snapshot?.maxNameBytes:void 0,d=`${e==="name"?"":"required"} ${n===void 0?"":`data-byte-limit="${n}"`} aria-describedby="${e}-hint"`;return`<div class="field"><label for="${e}">${t}${n===void 0?"":`<span class="field-count" aria-hidden="true" data-count-for="${e}"></span>`}</label>${r?`<textarea id="${e}" name="${e}" ${d} placeholder="Your message on the sign">${l(a)}</textarea>`:`<input id="${e}" name="${e}" ${e==="amount"?'inputmode="decimal"':""} value="${l(a)}" ${d}>`}${i?`<small id="${e}-hint">${i}</small>`:""}</div>`}reviewHtml(){let e=this.review,t=e.action,a=t.kind==="create"||t.kind==="edit-message"?t.message:this.form?this.entryMessage(this.form.entry):void 0,i=e.review.lines.filter(r=>!r.startsWith("Message: "));return`<h2 class="review-title">${l(e.review.title)}</h2>${a?`<section class="message-card"><p class="message">${l(a)}</p></section>`:""}<section class="review"><ul>${i.map(r=>`<li>${l(r)}</li>`).join("")}</ul><div class="stat"><span>Estimated network fee</span><strong>${m(e.review.estimatedGasCost)} ETH</strong></div><div class="stat"><span>Wallet</span><strong class="mono">${C(e.transaction.from)}</strong></div></section><p class="note">${l(e.review.reward)}</p><p class="meta">This review expires in 5 minutes. Your wallet shows the final network fee.</p>`}authorizationHtml(){let e=this.authorization,t=e.value.typedData.message;return`<div class="eyebrow">Community authorization</div><h2>${e.kind==="activate"?"Activate this community\u2019s Markee":"Claim community revenue"}</h2><p>A signed authorization lets Markee\u2019s keeper execute this action. The server rechecks your current council role before submitting it.</p><div class="card stack">${["registryCommunity","recipient","leaderboardFactory"].filter(a=>t[a]).map(a=>`<div class="meta">${l(a)}<br><strong class="mono">${l(t[a])}</strong></div>`).join("")}${["claimAmount","gasCost","maxFeeAmount"].filter(a=>t[a]!==void 0).map(a=>`<div class="stat"><span>${a==="claimAmount"?"Revenue":a==="gasCost"?"Keeper network fee":"Maximum bridge fee"}</span><strong>${m(String(t[a]))} ETH</strong></div>`).join("")}</div><p class="note">${e.kind==="claim"?"Revenue is sent to the community council treasury. Bridged claims remain pending until destination delivery is confirmed.":"This creates the community board and its revenue vault on the Markee chain."}</p>`}entryMessage(e){return e.moderated===!1?e.message:e.moderated?"This message is hidden by moderation.":"Message unavailable while moderation loads."}entriesHtml(){let e=this.snapshot,t=[...e.entries].sort((r,n)=>BigInt(r.score)>BigInt(n.score)?-1:BigInt(r.score)<BigInt(n.score)?1:0),a=[...t.filter(r=>r.owner.toLowerCase()===this.account?.toLowerCase()),...t.filter(r=>r.owner.toLowerCase()!==this.account?.toLowerCase())],i=e.board&&[8453,11155111].includes(e.chainId)?`https://${e.chainId===8453?"www":"2staging"}.markee.xyz/markee/${e.board}`:"";return`<section class="leaderboard" aria-label="Markee leaderboard"><div class="row between">${o("leaderboard",`<span class="chevron" aria-hidden="true">${this.leaderboardOpen?"\u2303":"\u2304"}</span> Leaderboard`,"text-button",`aria-expanded="${this.leaderboardOpen}" aria-controls="markee-leaderboard"`)}${z(i,"Open in Markee")}</div>${this.leaderboardOpen?`<div class="leaderboard-list" id="markee-leaderboard">${a.map(r=>{let n=r.owner.toLowerCase()===this.account?.toLowerCase(),d=r.address.toLowerCase()===e.top?.toLowerCase(),c=r.address.toLowerCase()===this.form?.entry.address.toLowerCase();return`<article class="leaderboard-entry ${d?"winner":""} ${c?"selected-entry":""}"><div class="grow"><p class="message">${l(this.entryMessage(r))}</p><div class="row entry-caption">${d?'<span class="pill">Winner</span>':""}${n?'<span class="meta">Yours</span>':""}${r.moderated===!1&&r.name?`<span class="name">${l(r.name)}</span>`:""}</div></div><div class="entry-funding"><div class="meta mono">${e.strategy==="rent"?`${m((BigInt(r.score)*v).toString())} ETH/mo`:`${m(r.totalFunds)} ETH`}</div><span class="meta">${r.views===null?"Views unavailable":`${r.views.toLocaleString()} views`}</span>${o(`form:${e.strategy==="sale"?"fund":"stream"}:${r.address}`,c?"Selected":"Fund",`compact ${c?"primary":""}`,`aria-pressed="${c}" aria-label="${c?"Selected":"Fund"} message ${C(r.address)}"`)}</div></article>`}).join("")||'<p class="empty">No Markees yet. Create the first one.</p>'}${e.strategy==="rent"&&e.rankedTop&&e.rankedTop.toLowerCase()!==e.top?.toLowerCase()?`<p class="note">The ranking has changed. ${o(`claim-top:${e.rankedTop}`,"Refresh winner","compact")}</p>`:""}${e.nextOffset!==null?o("more","Browse more messages","full"):""}</div>`:""}</section>`}selectedMessageHtml(e){let t=this.snapshot,a=t.wallet,i=e.owner.toLowerCase()===this.account?.toLowerCase(),r=t.entries.find(c=>c.owner.toLowerCase()===this.account?.toLowerCase()),n=e.address.toLowerCase()===t.top?.toLowerCase(),d=e.address.toLowerCase()===a?.backedMarkee?.toLowerCase()&&BigInt(a?.flowRate??"0")>0n;return`<section class="message-card ${n?"winner":""}"><div class="row between"><span class="eyebrow">${i?"Your Markee":"Markee you\u2019re funding"}</span>${n?'<span class="pill">Winner</span>':""}</div><p class="message">${l(this.entryMessage(e))}</p>${e.moderated===!1&&e.name?`<p class="name">${l(e.name)}</p>`:""}<div class="row message-tools">${i?o(`form:edit-message:${e.address}`,"Edit message","text-button")+o(`form:edit-name:${e.address}`,"Edit name","text-button"):""}${!i&&r?o(`form:${t.strategy==="rent"?"stream":"fund"}:${r.address}`,"Back to your Markee","text-button"):""}${o("create","Create your own Markee","text-button")}${t.strategy==="rent"&&this.account?o(`claim-refund:${e.address}`,"Collect refund","text-button"):""}</div><div class="message-stats">${t.strategy==="rent"?`<span class="meta">${d?n?"\u25CF Active stream":a?.poolConnected?"\u25CF Stream refunded while not the winner":"\u25CF Connect your refund pool in Deposit manager":"No active stream from your wallet to this message"}</span><div class="stats-grid"><div><span class="stat-label">Ranking rate</span><strong>${m((BigInt(e.score)*v).toString())} ETH/mo</strong></div><div><span class="stat-label">Your rate</span><strong>${m((d?BigInt(a.flowRate)*v:0n).toString())} ETH/mo</strong></div>${a?`<div><span class="stat-label">ETHx balance</span><strong>${m(a.ethx)} ETHx</strong></div><div><span class="stat-label">Funds remaining</span><strong title="Across all of your ETHx flows">${a.runwaySeconds===null?"No net outflow":`${(Number(a.runwaySeconds)/86400).toFixed(1)} days`}</strong></div>`:""}</div>${BigInt(e.legacyFloor)>0n?`<p class="meta">Ranking includes a decaying legacy floor of ${m((BigInt(e.legacyFloor)*v).toString())} ETH/mo.</p>`:""}`:`<div class="stats-grid"><div><span class="stat-label">Total funded</span><strong>${m(e.totalFunds)} ETH</strong></div><div><span class="stat-label">Views</span><strong>${e.views===null?"Unavailable":e.views.toLocaleString()}</strong></div></div>`}</div></section>`}fundingHtml(e){let t=this.snapshot,a=t.wallet,i=t.strategy==="rent",r=A(t,e),n=!!e&&e.address.toLowerCase()===a?.backedMarkee?.toLowerCase(),d=i&&n?BigInt(a.flowRate)*v:0n,c=BigInt(t.minimum)>r.minimum?BigInt(t.minimum):r.minimum,f=d>c?d:c,u=!i&&e?1n:BigInt(t.minimum);return`<section class="funding-card"><label for="amount">${i?"Monthly streaming rate":"Payment amount"}</label><div class="amount-row"><div class="amount-value"><input id="amount" name="amount" inputmode="decimal" value="${l(M(f.toString()))}" required aria-describedby="amount-hint"><span class="mono">${i?"ETHx/mo":"ETH"}</span></div><div class="amount-presets">${o("preset:min","MIN","compact mono",'title="Use the minimum amount"')}${o("preset:boost",r.double?"2\xD7":"WIN","compact mono",'title="Suggest an amount using the loaded ranking"')}</div></div><div class="funding-caption"><span id="amount-hint">Minimum ${M(u.toString())} ${i?"ETH/mo":"ETH"}</span><span>${a?`Balance ${m(a.eth)} ETH`:"Connect to see your balance"}</span></div><div class="funding-tools">${o("tab:wallet",i?"Deposit manager \u2192":"Wallet & rewards \u2192","text-button")}<span class="meta">${i?a?.runwaySeconds!=null?`${(Number(a.runwaySeconds)/86400).toFixed(1)} days remaining`:a?`${m(a.ethx)} ETHx available`:"ETH funds your ETHx balance":"One-time payment"}</span></div></section><p class="meta funding-hint">${i?"Unspent rent is refunded while your message is not the winner. You can stop streaming at any time.":e?"Adding funds keeps the current message owner.":"Your connected wallet will own this message."} Shortcuts use the loaded ranking; positions can change.</p>`}formHtml(){let e=this.snapshot,t=this.form;return t?.kind.startsWith("edit")?`<form id="markee-action" data-form="entry"><section class="message-card"><div class="eyebrow">Your Markee</div>${t.kind==="edit-message"?this.field("message","Markee message",t.entry.message,`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0):this.field("name","Your name (optional)",t.entry.name,`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section></form>`:`<form id="markee-action" data-form="${t?"entry":"create"}">${t?this.selectedMessageHtml(t.entry):`<section class="message-card editor-card">${this.field("message","Markee message","",`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0)}${this.field("name","Your name (optional)","",`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section>`}${this.fundingHtml(t?.entry)}${!t&&e.strategy==="rent"?'<p class="note">First create your message, then review and confirm its stream. Your chosen rate is kept for the next step.</p>':""}</form>`}updateFields(){for(let t of this.root.querySelectorAll("[data-byte-limit]")){let a=Number(t.dataset.byteLimit),i=new TextEncoder().encode(t.value).length;t.setCustomValidity(i>a?`Use at most ${a} UTF-8 bytes.`:"");let r=this.root.querySelector(`[data-count-for="${t.name}"]`);r&&(r.textContent=`${i}/${a}`)}let e=this.root.querySelector("#markee-action #amount");if(e&&this.snapshot){let t=A(this.snapshot,this.form?.entry),a;try{a=BigInt(g(e.value,this.snapshot.strategy==="sale"))}catch{}let i=this.snapshot.strategy==="sale"&&this.form?1n:BigInt(this.snapshot.minimum);e.setCustomValidity(a===void 0?"Enter a valid ETH amount.":a<i?`Use at least ${M(i.toString())} ETH${this.snapshot.strategy==="rent"?" per month":""}.`:""),this.root.querySelector('[data-cmd="preset:min"]')?.setAttribute("aria-pressed",String(a===t.minimum)),this.root.querySelector('[data-cmd="preset:boost"]')?.setAttribute("aria-pressed",String(a===t.boost))}}walletHtml(){let e=this.snapshot,t=e.wallet;if(!t)return'<p class="empty">Connect your wallet to see balances and manage your Markee.</p>'+o("connect","Connect app wallet","primary full");let a=`<h2>Your wallet</h2><p class="meta mono">${l(t.address)}</p><div class="grid"><div class="card"><span class="meta">Native ETH</span><div class="metric">${m(t.eth)}</div></div><div class="card"><span class="meta">MARKEE</span><div class="metric">${t.markee===null?"Unavailable":m(t.markee,2)}</div></div></div>`;return e.strategy==="sale"?a+'<p class="note">Payments reward the paying wallet when this board has RevNet enabled. Manage your messages from the leaderboard.</p>':(a+=`<div class="divider"></div><div class="card"><div class="stat"><span>Available ETHx</span><strong>${m(t.ethx)} ETHx</strong></div><div class="stat"><span>This board\u2019s monthly rate</span><strong>${m((BigInt(t.flowRate)*2628000n).toString())} ETH</strong></div><div class="stat"><span>Refund flow / month</span><strong>${m((BigInt(t.refundRate)*2628000n).toString())} ETHx</strong></div><div class="stat"><span>Runway across all ETHx flows</span><strong>${t.runwaySeconds===null?"No net outflow":`${(Number(t.runwaySeconds)/86400).toFixed(1)} days`}</strong></div><p class="meta">Snapshot at ${new Date(t.observedAt*1e3).toLocaleTimeString()}. Balances and rates can change.</p><div class="row">${BigInt(t.flowRate)>0n?o("stop","Stop stream","danger"):""}${t.backedMarkee&&!t.poolConnected?o(`connect-refund:${t.backedMarkee}`,"Connect refund pool","accent"):""}${o("refresh","Refresh balances")}</div></div><div class="divider"></div><h3>Manage ETHx</h3><form data-form="balance"><div class="grid"><div><label for="kind">Action</label><select id="kind" name="kind"><option value="wrap">Deposit ETH \u2192 ETHx</option><option value="unwrap">Withdraw ETHx \u2192 ETH</option></select></div>${this.field("amount","Amount","0.001")}</div><button type="submit" class="btn">Review balance change</button></form><div class="divider"></div><div class="card"><h3>Buffer and rewards</h3><div class="stat"><span>Refundable board buffer</span><strong>${m(t.withdrawableDeposit)} ETHx</strong></div><div class="stat"><span>Accrued rent to settle</span><strong>${m(t.pendingSettlement)} ETH</strong></div><p class="meta">Rewards come from actual rent spent, not the ETH deposited into your wallet.</p><div class="row">${BigInt(t.withdrawableDeposit)>0n?o("withdraw-buffer","Recover buffer"):""}${BigInt(t.pendingSettlement)>0n?o("settle",e.revnetEnabled?"Claim MARKEE":"Settle rent","primary"):""}${t.backedMarkee&&BigInt(t.poolClaimable)>0n?o(`claim-refund:${t.backedMarkee}`,"Collect pool refund"):""}</div></div>`,a)}communityHtml(){let e=this.snapshot.community;return e?`<h2>Community treasury</h2><p class="muted">Community council members can activate Markee and collect community revenue.</p><div class="card"><div class="stat"><span>Integration</span><strong>${e.integration.status==="active"?"Active":"Not activated"}</strong></div><div class="stat"><span>Available revenue</span><strong>${m(e.revenue.claimableAmount)} ETH</strong></div>${e.permissions?.councilSafe?`<p class="meta">Council treasury<br><span class="mono">${l(e.permissions.councilSafe)}</span></p>`:""}<div class="row">${this.adminProcessing?'<p class="note">A signed community action is processing. Check it before authorizing another.</p>'+o("admin-check","Check community action","primary"):this.account?e.integration.status!=="active"&&e.permissions?.canActivate?o("activate","Activate community Markee","primary"):e.permissions?.canClaim&&BigInt(e.revenue.claimableAmount)>0n?o("claim","Review revenue claim","primary"):'<span class="meta">No authorized action is currently available for this wallet.</span>':o("connect","Connect council wallet","primary")}</div></div>${this.adminResult?`<div class="success">Source transaction confirmed. ${z(this.adminResult.transactionUrl||"","View transaction")}${this.adminResult.bridged?"<p>Bridge delivery is tracked separately from the source transaction.</p>":""}${o("bridge","Check transfer status")}</div>`:""}`:""}title(){let e=this.snapshot;return this.wallets?"Connect your wallet":this.review?"Review payment":this.authorization?"Review authorization":this.pending?"Payment in progress":this.tab==="wallet"?e?.strategy==="rent"?"Deposit manager":"Wallet & rewards":this.tab==="community"||e&&!e.board?"Community treasury":this.form?.kind.startsWith("edit")?"Edit your Markee":this.form?this.form.entry.owner.toLowerCase()!==this.account?.toLowerCase()?"Fund a Markee":e?.strategy==="sale"?"Fund your Markee":BigInt(e?.wallet?.flowRate??"0")>0n?"Manage your Markee stream":"Stream to your Markee":"Change the Markee Sign"}footerHtml(){let e=this.snapshot,t="";if(this.wallets)t=o("back","Back");else if(this.review)t=o("back","Back")+o("send","Confirm in wallet","primary");else if(this.authorization)t=o("back","Back")+o("sign","Sign authorization","primary");else if(this.pending)t=o("check","Check transaction","primary");else if(e&&this.tab==="main"&&e.board){let a=this.form?.kind.startsWith("edit");t=(a?o("back","Cancel"):e.strategy==="rent"&&BigInt(e.wallet?.flowRate??"0")>0n?o("stop","Stop streaming","danger"):"")+(this.account?`<button class="btn primary" type="submit" form="markee-action">${a?"Review change":!this.form&&e.strategy==="rent"?"Review creation":"Review payment info"}</button>`:o("connect","Connect wallet","primary"))}else e&&(t=o("tab:main","Back to Markee"));return`<footer><div class="footer-actions">${t}</div><div class="footer-meta"><span>Powered by Markee${this.account?` \xB7 ${C(this.account)}`:""}</span>${e?.community&&e.board&&this.tab!=="community"&&!this.review&&!this.authorization&&!this.pending?o("tab:community","Community treasury","text-button"):""}</div></footer>`}render(){if(this.closed)return;let e=this.root.activeElement,t=e?.dataset.cmd,a=e?.id,i=this.wallets?"wallets":this.review?`review:${this.review.id}`:this.authorization?`authorization:${this.authorization.value.nonce}`:this.pending?`pending:${this.pending.hash}`:`${this.tab}:${this.form?.kind??"create"}:${this.form?.entry.address??""}`,r=i===this.renderedView?this.root.querySelector(".content")?.scrollTop??0:0;this.renderedView=i;let n=!document.activeElement||document.activeElement===document.body||document.activeElement===this.host,d=this.snapshot,c="";this.wallets?c=`<h2>Choose your wallet</h2><div class="wallets">${this.wallets.map((h,b)=>o(`wallet:${b}`,l(h.name))).join("")}</div>`:this.review?c=this.reviewHtml():this.authorization?c=this.authorizationHtml():d?this.pending?c=`<h2>Waiting for confirmation</h2><p>Your transaction was sent. You can close this modal and come back to check it.</p><p class="meta mono">${l(this.pending.hash)}</p><p class="note">Do not send a second payment while this transaction is pending.</p>`:!d.board||this.tab==="community"?c=this.communityHtml():this.tab==="wallet"?c=this.walletHtml():c=`${this.form?.kind.startsWith("edit")?"":this.entriesHtml()}${this.formHtml()}`:c=this.error?o("refresh","Retry","primary"):'<div class="loading"><span class="spinner"></span>Loading Markee\u2026</div>';let f=this.result?`<div class="${this.result.status==="reverted"||this.result.settlement==="deferred"?"error":"success"}">${this.result.status==="reverted"?"Transaction reverted. No action was completed.":this.result.settlement==="deferred"?"The transaction confirmed, but reward settlement was deferred. Your claim remains available.":`Transaction confirmed.${this.result.tokensReceived&&BigInt(this.result.tokensReceived)>0n?` ${m(this.result.tokensReceived,2)} MARKEE delivered to your wallet.`:""}`} ${z(this.result.explorerUrl,"View receipt")}</div>`:"";this.root.innerHTML=`<style>${H}</style><div class="overlay"><section class="panel" role="dialog" aria-modal="true" aria-labelledby="markee-title"><header><div class="grow"><h1 id="markee-title">${l(this.title())}</h1><p class="header-caption">${l(d?.name||"Markee")}${d?` \xB7 ${d.strategy==="rent"?"For rent":"For sale"}${d.chainId===8453?" \xB7 Base":d.chainId===11155111?" \xB7 Sepolia testnet":""}`:""}</p></div><button class="close" data-cmd="close" aria-label="Close Markee">\xD7</button></header><main class="content" aria-busy="${this.busy}"><div role="status" aria-live="polite">${this.busy?'<p class="meta"><span class="spinner"></span>Working\u2026</p>':""}${this.error?`<div class="error">${l(this.error)}</div>`:""}${f}</div>${d?.warnings.map(h=>`<div class="note">${l(h)}</div>`).join("")||""}${c}</main>${this.footerHtml()}</section></div>`,this.busy&&this.root.querySelectorAll('button:not([data-cmd="close"])').forEach(h=>{h.disabled=!0});let u=this.drafts.get(this.draftKey());if(u)for(let h of this.root.querySelectorAll("input,textarea,select"))u[h.name]!==void 0&&(h.value=u[h.name]);this.updateFields();let w=this.root.querySelector(".content");w&&(w.scrollTop=r),this.viewObserver?.disconnect();let I=this.root.querySelector(".winner"),y=d?.entries.find(h=>h.address.toLowerCase()===d.top?.toLowerCase()),L=y?`${y.address}:${y.message}`:"";I&&y?.moderated===!1&&!this.viewed.has(L)&&typeof IntersectionObserver<"u"&&(this.viewObserver=new IntersectionObserver(h=>{h.some(b=>b.isIntersecting)&&(this.viewObserver?.disconnect(),this.viewed.add(L),this.client.recordView(y.address,y.message,window.location.origin).catch(()=>{this.viewed.delete(L)}))},{threshold:.5}),this.viewObserver.observe(I)),n&&((a?this.root.getElementById(a):t?[...this.root.querySelectorAll("[data-cmd]")].find(b=>b.dataset.cmd===t):null)??this.root.querySelector('[data-cmd="close"]'))?.focus({preventScroll:!0})}};function q(s){let e=new k(s),t,a=s.theme;return{client:e,open(i){return t?.close(),t=new P(e,{...i,theme:i.theme??a}),t},setTheme(i){a=i??{},t?.setTheme(a)},close(){t?.close(),t=void 0}}}export{k as MarkeeClient,p as MarkeeError,P as MarkeeModal,q as createMarkee,E as discoverWallets,m as formatEth,g as parseEth};
|
|
128
|
+
`;var J={background:"#fbfcff",surface:"#ffffff",text:"#181b21",muted:"#687080",border:"#dce1ea",inputBackground:"#ffffff",inputText:"#202737",primary:"#282e3e",primaryText:"#ffffff",accent:"#c9f1a7",accentText:"#2b3c20",accentSurface:"#f1f7ea",accentSurfaceText:"#4e6535",accentBorder:"#cde3b5",selected:"#e9edf7",selectedText:"#242c47",info:"#edf1f9",infoText:"#52617b",error:"#fff0f0",errorText:"#9c3540",success:"#edf7e6",successText:"#40602f",link:"#4762a5",focusRing:"#5871c8",overlay:"#17203888"},G={background:"#151923",surface:"#202633",text:"#f0f3f8",muted:"#a6b1c3",border:"#434f63",inputBackground:"#10151e",inputText:"#f0f3f8",primary:"#dde6fa",primaryText:"#182238",accent:"#c9f1a7",accentText:"#24361a",accentSurface:"#243221",accentSurfaceText:"#c4e5ad",accentBorder:"#526b40",selected:"#313d53",selectedText:"#edf3ff",info:"#243149",infoText:"#bdcff1",error:"#44262e",errorText:"#ffbdc5",success:"#233b2b",successText:"#b5e4bf",link:"#adc5ff",focusRing:"#a1b4ff",overlay:"#030711b8"},Q='Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',X=n=>`--markee-${n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`;function L(n,e){let t,a=(r={})=>{t?.(),t=void 0;let i=r.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)"):void 0,s=()=>{let o=r.mode==="dark"||i?.matches?"dark":"light",d=o==="dark"?G:J;n.dataset.markeeTheme=o,n.style.setProperty("--markee-color-scheme",o);for(let p of Object.keys(d)){let w=r.colors?.[p];n.style.setProperty(X(p),w&&CSS.supports("color",w)?w:d[p])}n.style.setProperty("--markee-font-family",r.fontFamily&&CSS.supports("font-family",r.fontFamily)?r.fontFamily:Q);let f=typeof r.radius=="number"&&Number.isFinite(r.radius)?Math.max(0,Math.min(48,r.radius)):22;n.style.setProperty("--markee-radius",`${f}px`),n.style.setProperty("--markee-card-radius",`${f*.64}px`),n.style.setProperty("--markee-control-radius",`${f*.45}px`),n.style.setProperty("--markee-small-radius",`${f*.32}px`)};s(),i&&(i.addEventListener("change",s),t=()=>i.removeEventListener("change",s))};return a(e),{set:a,destroy(){t?.(),t=void 0}}}var x=2628000n,M=10n**15n,z=(...n)=>n.reduce((e,t)=>e>t?e:t,0n);function I(n,e){let t=n.strategy==="rent",a=t?(BigInt(n.minimum)+M-1n)/M*M:e?1n:BigInt(n.minimum),r=n.entries.filter(p=>p.address.toLowerCase()!==e?.address.toLowerCase()),i=z(...r.map(p=>BigInt(p.score))),s=!!e&&e.address.toLowerCase()===n.top?.toLowerCase();if(!t){let p=BigInt(e?.totalFunds??"0");return{minimum:a,boost:z(a,i+M-p,s?p:0n),double:s&&p>0n}}let d=!!e&&n.wallet?.backedMarkee?.toLowerCase()===e.address.toLowerCase()?BigInt(n.wallet.flowRate):0n,f=z(BigInt(e?.aggregateRate??"0")-d);return{minimum:a,boost:z(a,(i-f)*x+M,s?d*x*2n:0n),double:s&&d>0n}}var H=n=>{let e=BigInt(n);return`${e/10n**18n}.${(e%10n**18n).toString().padStart(18,"0")}`.replace(/\.?0+$/,"")||"0"},c=(n,e,t="",a="")=>`<button type="button" class="btn ${t}" data-cmd="${n}" ${a}>${e}</button>`,q=(n,e)=>/^https:\/\//.test(n)?`<a href="${l(n)}" target="_blank" rel="noopener noreferrer">${l(e)} \u2197</a>`:"",R=class{constructor(e,t){this.client=e;this.options=t;if(typeof document>"u")throw new Error("Open the Markee modal in a browser.");e.registerSite(t.placement),this.previousFocus=document.activeElement,this.previousOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.host=document.createElement("div"),this.host.setAttribute("data-markee-modal",""),this.root=this.host.attachShadow({mode:"open"}),this.theme=L(this.host,t.theme??e.options.theme),document.body.appendChild(this.host),this.root.addEventListener("click",this.onClick),this.root.addEventListener("submit",this.onSubmit),this.root.addEventListener("keydown",this.onKey),this.root.addEventListener("input",()=>{this.captureDraft(),this.updateFields()}),e.request("checkout/config").then(a=>{this.cardAvailable=a.enabled}).catch(()=>{}).finally(()=>{this.checkoutChecked=!0,this.render()}),this.render(),this.root.querySelector('[data-cmd="close"]')?.focus(),this.reload(),this.watchAccount()}host;root;theme;snapshot;cardAvailable=!1;checkoutChecked=!1;account=null;tab="main";leaderboardOpen=!1;initialSelection=!1;renderedView="";form;review;authorization;adminResult;adminProcessing=!1;result;pending;wallets;busy=!1;error="";closed=!1;epoch=0;timer;accountTimer;watched;previousFocus;previousOverflow;abort=new AbortController;drafts=new Map;viewObserver;viewed=new Set;walletChanged=()=>{this.initialSelection=!1,this.review=void 0,this.authorization=void 0,this.form=void 0,this.tab="main",this.result=void 0,this.error="Wallet changed. Refreshing this placement\u2026",this.reload()};close(){this.closed||(this.closed=!0,this.abort.abort(),clearTimeout(this.timer),clearTimeout(this.accountTimer),this.viewObserver?.disconnect(),this.theme.destroy(),this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.host.remove(),document.body.style.overflow=this.previousOverflow,this.previousFocus?.focus(),this.options.onClose?.())}setTheme(e){this.closed||this.theme.set(e)}async watchAccount(){try{let e=await this.client.provider();e!==this.watched&&(this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.watched=e||void 0,e?.on?.("accountsChanged",this.walletChanged),e?.on?.("chainChanged",this.walletChanged)),(await this.client.account())?.toLowerCase()!==this.account?.toLowerCase()&&!this.busy&&this.walletChanged()}catch{}this.closed||(this.accountTimer=setTimeout(()=>void this.watchAccount(),2e3))}async reload(e){let t=++this.epoch;try{let a=await this.client.account().catch(()=>null),r=await this.client.snapshot(this.options.placement,a,e,this.abort.signal);if(this.closed||t!==this.epoch)return;if(this.account=a,this.snapshot=r,this.error="",this.form&&(this.form.entry=r.entries.find(s=>s.address.toLowerCase()===this.form.entry.address.toLowerCase())??this.form.entry),!this.initialSelection&&a){this.initialSelection=!0;let s=r.entries.find(o=>o.address.toLowerCase()===r.wallet?.backedMarkee?.toLowerCase())??r.entries.find(o=>o.owner.toLowerCase()===a.toLowerCase());s&&!this.form&&!this.drafts.get("create")?.message&&(this.form={kind:r.strategy==="rent"?"stream":"fund",entry:s})}this.options.placement.kind==="gardens-community"&&(this.adminResult=this.client.communityReceipt(this.options.placement)||void 0),this.pending=a?this.client.pending(this.options.placement,a):void 0;let i=this.client.pendingAuthorization();this.adminProcessing=!!i&&this.options.placement.kind==="gardens-community"&&i.account.toLowerCase()===a?.toLowerCase()&&i.community.toLowerCase()===this.options.placement.community.toLowerCase()&&i.chainId===this.options.placement.chainId,this.render(),this.pending&&this.poll()}catch(a){!this.closed&&t===this.epoch&&this.fail(a)}}fail(e){this.error=e instanceof Error?e.message:String(e),this.render()}async task(e){if(!this.busy){this.busy=!0,this.error="",this.render();try{await e()}catch(t){this.fail(t)}finally{this.busy=!1,this.render()}}}async connect(){if(!this.client.options.wallet){let e=await P();if(e.length>1){this.wallets=e,this.render();return}}this.host.style.visibility="hidden";try{await this.client.connect()}finally{this.host.style.visibility=""}await this.reload()}async prepare(e){if(this.pending)throw new Error("Check your pending transaction before preparing another action.");if(!this.account){await this.connect();return}this.review=await this.client.prepare(this.options.placement,e),this.authorization=void 0}async poll(){if(clearTimeout(this.timer),!(!this.pending||this.closed)){try{let e=this.pending,t=await this.client.verify(e);if(this.closed||this.pending?.hash!==e.hash)return;if(t.status!=="pending"){if(this.pending=void 0,this.result=t,this.error="",await this.reload(),t.createdMarkee&&this.snapshot?.strategy==="rent"){let a=this.snapshot.entries.find(i=>i.address.toLowerCase()===t.createdMarkee.toLowerCase()),r=e.preparation.action;if(r.kind==="create"){this.form={kind:"stream",entry:a||{address:t.createdMarkee,owner:e.preparation.transaction.from,message:r.message,name:r.name,score:"0",totalFunds:"0",aggregateRate:"0",legacyFloor:"0",moderated:!1,views:0}};let i=this.drafts.get("create")?.amount;i&&this.drafts.set(this.draftKey(),{amount:i})}}this.render();return}}catch(e){this.closed||this.fail(e)}!this.closed&&this.pending&&(this.timer=setTimeout(()=>void this.poll(),5e3))}}async applyAdmin(e){if(this.authorization=void 0,this.adminProcessing=e.status==="working"||e.status==="submitted",e.status==="complete"&&(this.adminResult=e.result,await this.reload()),e.status==="failed")throw new Error(e.error||"Community action failed.")}onClick=e=>{let t=e.target.closest("[data-cmd]");if(!t)return;let a=t.dataset.cmd;if(a==="close"){this.close();return}if((a==="copy-recipient"||a==="copy-wallet")&&this.review){let r=a==="copy-recipient"?this.review.transaction.to:this.review.transaction.from,i=navigator.clipboard?.writeText(r);if(!i){t.textContent="Copy unavailable";return}i.then(()=>{t.textContent="Copied",setTimeout(()=>{t.isConnected&&(t.textContent="Copy")},2e3)}).catch(()=>{t.textContent="Copy failed"});return}if(!this.busy){if(this.captureDraft(),a==="leaderboard"){this.leaderboardOpen=!this.leaderboardOpen,this.render();return}if(a==="create"){this.tab="main",this.form=void 0,this.review=void 0,this.render();return}if(a.startsWith("tab:")){this.tab=a.slice(4),this.review=void 0,this.authorization=void 0,this.render();return}if(a==="back"){this.review||this.authorization||this.wallets?(this.review=void 0,this.authorization=void 0,this.wallets=void 0):this.tab!=="main"?this.tab="main":this.form?.kind.startsWith("edit")?this.form={kind:this.snapshot.strategy==="rent"?"stream":"fund",entry:this.form.entry}:this.form=void 0,this.render();return}if(a.startsWith("preset:")&&this.snapshot){let r=this.root.querySelector("#amount");if(r){let i=I(this.snapshot,this.form?.entry);r.value=H((a==="preset:min"?i.minimum:i.boost).toString()),this.captureDraft(),this.updateFields()}return}if(a.startsWith("form:")){let[,r,i]=a.split(":"),s=this.snapshot?.entries.find(o=>o.address===i);s&&(this.form={kind:r,entry:s},this.tab="main"),this.render();return}if(a==="card"&&this.hostedEligible()&&this.cardAvailable){this.captureDraft();let r=this.root.querySelector("#markee-action");if(!r||!r.reportValidity())return;let i=new FormData(r),s;try{let d=b(String(i.get("amount")||""));s=this.form?.kind==="fund"?{kind:"fund",markee:this.form.entry.address,amount:d}:{kind:"create",message:String(i.get("message")||""),name:String(i.get("name")||""),amount:d}}catch(d){this.error=d.message,this.render();return}let o=F(this.client,this.options.placement,s);this.task(async()=>{let d=await o;if(d.status!=="confirmed")throw new Error("Payment was not confirmed.");this.result=d,this.client.options.onEvent?.({type:"confirmed",hash:d.hash}),await this.reload()});return}this.task(async()=>{if(a==="connect")await this.connect();else if(a.startsWith("wallet:"))await this.client.connect(this.wallets[Number(a.slice(7))].provider),this.wallets=void 0,await this.reload();else if(a==="refresh")await this.reload();else if(a==="more")await this.reload(this.snapshot?.nextOffset??void 0);else if(a==="send"&&this.review){let r=this.review,i=await this.client.send(r);this.pending={preparation:r,hash:i},this.review=void 0,this.form=void 0,this.result=void 0,this.poll()}else if(a==="check")await this.poll();else if(["stop","withdraw-buffer","settle"].includes(a))await this.prepare({kind:a});else if(a.startsWith("claim-refund:")||a.startsWith("connect-refund:")||a.startsWith("claim-top:")){let[r,i]=a.split(":");await this.prepare({kind:r,markee:i})}else if(a==="activate"||a==="claim"){let r=this.options.placement;if(r.kind!=="gardens-community"||!this.account)return;let i=this.account;this.authorization={kind:a,account:i,value:await this.client.authorize(r,a)},this.review=void 0}else if(a==="sign"&&this.authorization){let r=this.authorization;try{await this.applyAdmin(await this.client.executeAuthorization(r.kind,r.value,r.account))}finally{this.client.pendingAuthorization()&&(this.authorization=void 0,this.adminProcessing=!0)}}else if(a==="admin-check")await this.applyAdmin(await this.client.resumeAuthorization());else if(a==="bridge"&&this.adminResult){let r=await this.client.bridgeStatus(this.adminResult.bridgeProtocol||"none",this.adminResult.transactionHash,this.snapshot.chainId,this.options.placement.chainId);this.error=`Treasury transfer status: ${r.status.replace(/_/g," ")}.`}})}};onSubmit=e=>{if(e.preventDefault(),this.busy)return;if(!this.account){this.root.querySelector('[data-cmd="card"]:not(:disabled)')?.click();return}this.captureDraft();let t=e.target,a=new FormData(t),r=i=>String(a.get(i)||"");this.task(async()=>{if(t.dataset.form==="create")this.snapshot?.strategy==="rent"&&b(r("amount")),await this.prepare({kind:"create",message:r("message"),name:r("name"),...this.snapshot?.strategy==="sale"?{amount:b(r("amount"),!0)}:{}});else if(t.dataset.form==="balance")await this.prepare({kind:r("kind"),amount:b(r("amount"))});else if(this.form){let{kind:i,entry:s}=this.form;i==="fund"?await this.prepare({kind:i,markee:s.address,amount:b(r("amount"))}):i==="stream"?await this.prepare({kind:i,markee:s.address,monthlyAmount:b(r("amount"))}):i==="edit-message"?await this.prepare({kind:i,markee:s.address,message:r("message")}):await this.prepare({kind:i,markee:s.address,name:r("name")})}})};draftKey(){return this.tab!=="main"?this.tab:this.form?`${this.form.kind}:${this.form.entry.address}`:"create"}captureDraft(){let e=this.root.querySelector("form");e&&this.drafts.set(this.draftKey(),Object.fromEntries([...new FormData(e)].map(([t,a])=>[t,String(a)])))}onKey=e=>{let t=e;if(t.key==="Escape"&&(t.preventDefault(),this.close()),t.key!=="Tab"||this.host.style.visibility==="hidden")return;let a=[...this.root.querySelectorAll("button:not(:disabled),a[href],input,textarea,select")],r=a[0],i=a[a.length-1];t.shiftKey&&this.root.activeElement===r?(t.preventDefault(),i?.focus()):!t.shiftKey&&this.root.activeElement===i&&(t.preventDefault(),r?.focus())};field(e,t,a="",r="",i=!1){let s=e==="message"?this.snapshot?.maxMessageBytes:e==="name"?this.snapshot?.maxNameBytes:void 0,o=`${e==="name"?"":"required"} ${s===void 0?"":`data-byte-limit="${s}"`} aria-describedby="${e}-hint"`;return`<div class="field"><label for="${e}">${t}${s===void 0?"":`<span class="field-count" aria-hidden="true" data-count-for="${e}"></span>`}</label>${i?`<textarea id="${e}" name="${e}" ${o} placeholder="Your message on the sign">${l(a)}</textarea>`:`<input id="${e}" name="${e}" ${e==="amount"?'inputmode="decimal"':""} value="${l(a)}" ${o}>`}${r?`<small id="${e}-hint">${r}</small>`:""}</div>`}reviewHtml(){let e=this.review,t=e.action,a="markee"in t?this.snapshot?.entries.find(h=>h.address.toLowerCase()===t.markee.toLowerCase()):void 0,r=t.kind==="create"||t.kind==="edit-message"?t.message:this.form?this.entryMessage(this.form.entry):a?this.entryMessage(a):void 0,i=BigInt(e.transaction.value),s=t.kind==="stream"?`${m(t.monthlyAmount)} ETHx/mo`:t.kind==="fund"||t.kind==="create"&&i>0n?`${m(i.toString())} ETH`:null,o=s!==null,d=o?[["Paying",s],[t.kind==="stream"&&i>0n?"Depositing now":"Estimated network fee",t.kind==="stream"&&i>0n?`${m(i.toString())} ETH`:`${m(e.review.estimatedGasCost)} ETH`],["You'll earn",e.review.estimatedTokens!==void 0?`${m(e.review.estimatedTokens,4)} MARKEE (estimated)`:this.snapshot?.revnetEnabled?t.kind==="stream"?"MARKEE while winning":"MARKEE to your wallet":"No MARKEE on this board"]]:[["Action",e.review.title],["Native ETH sent",`${m(i.toString())} ETH`],["Estimated network fee",`${m(e.review.estimatedGasCost)} ETH`]],f=e.review.lines.filter(h=>!/^(Message: |Name: |Native ETH sent: |Network: |Recipient: )/.test(h)),p=d.map(([h,y])=>`<div class="review-row"><span>${l(h)}</span><strong>${l(y)}</strong></div>`).join(""),w=t.kind==="stream"?"Your payment only streams while your message is winning":t.kind==="fund"?"Funding keeps the current message owner":t.kind==="create"&&o?"Your payment gives you this Markee message":"Review this wallet action",k=t.kind==="stream"?"Anyone can overtake your message. The refund pool offsets rent while you are not winning; you can stop the stream at any time.":e.review.reward;return`<div class="payment-review">${r?`<section class="review-message" aria-label="Markee message"><p class="message">${l(r)}</p></section>`:""}<section class="review-summary" aria-label="Payment summary">${p}</section><section class="review-callout"><strong>${l(w)}</strong><p>${l(k)}</p></section><details class="review-details"><summary>Transaction details</summary><div class="review-row"><span>Network</span><strong>${l(this.snapshot?.chainId===8453?"Base":this.snapshot?.chainId===11155111?"Sepolia testnet":String(e.transaction.chainId))}</strong></div><div class="review-row"><span>Recipient</span><div class="review-address"><strong class="mono" title="${l(e.transaction.to)}">${l(E(e.transaction.to))}</strong>${c("copy-recipient","Copy","review-copy",'aria-label="Copy recipient address"')}</div></div><div class="review-row"><span>Wallet</span><div class="review-address"><strong class="mono" title="${l(e.transaction.from)}">${l(E(e.transaction.from))}</strong>${c("copy-wallet","Copy","review-copy",'aria-label="Copy wallet address"')}</div></div>${t.kind==="stream"&&i>0n?`<div class="review-row"><span>Estimated network fee</span><strong>${m(e.review.estimatedGasCost)} ETH</strong></div>`:""}${f.map(h=>`<p>${l(h)}</p>`).join("")}${t.kind==="stream"?`<p>${l(e.review.reward)}</p>`:""}<p>This review expires in 5 minutes. Your wallet shows the final network fee.</p></details></div>`}authorizationHtml(){let e=this.authorization,t=e.value.typedData.message;return`<div class="eyebrow">Community authorization</div><h2>${e.kind==="activate"?"Activate this community\u2019s Markee":"Claim community revenue"}</h2><p>A signed authorization lets Markee\u2019s keeper execute this action. The server rechecks your current council role before submitting it.</p><div class="card stack">${["registryCommunity","recipient","leaderboardFactory"].filter(a=>t[a]).map(a=>`<div class="meta">${l(a)}<br><strong class="mono">${l(t[a])}</strong></div>`).join("")}${["claimAmount","gasCost","maxFeeAmount"].filter(a=>t[a]!==void 0).map(a=>`<div class="stat"><span>${a==="claimAmount"?"Revenue":a==="gasCost"?"Keeper network fee":"Maximum bridge fee"}</span><strong>${m(String(t[a]))} ETH</strong></div>`).join("")}</div><p class="note">${e.kind==="claim"?"Revenue is sent to the community council treasury. Bridged claims remain pending until destination delivery is confirmed.":"This creates the community board and its revenue vault on the Markee chain."}</p>`}entryMessage(e){return e.moderated===!1?e.message:e.moderated?"This message is hidden by moderation.":"Message unavailable while moderation loads."}entriesHtml(){let e=this.snapshot,t=[...e.entries].sort((i,s)=>BigInt(i.score)>BigInt(s.score)?-1:BigInt(i.score)<BigInt(s.score)?1:0),a=[...t.filter(i=>i.owner.toLowerCase()===this.account?.toLowerCase()),...t.filter(i=>i.owner.toLowerCase()!==this.account?.toLowerCase())],r=e.board&&[8453,11155111].includes(e.chainId)?`https://${e.chainId===8453?"www":"2staging"}.markee.xyz/markee/${e.board}`:"";return`<section class="leaderboard" aria-label="Markee leaderboard"><div class="row between">${c("leaderboard",`<span class="chevron" aria-hidden="true">${this.leaderboardOpen?"\u2303":"\u2304"}</span> Leaderboard`,"text-button",`aria-expanded="${this.leaderboardOpen}" aria-controls="markee-leaderboard"`)}${q(r,"Open in Markee")}</div>${this.leaderboardOpen?`<div class="leaderboard-list" id="markee-leaderboard">${a.map(i=>{let s=i.owner.toLowerCase()===this.account?.toLowerCase(),o=i.address.toLowerCase()===e.top?.toLowerCase(),d=i.address.toLowerCase()===this.form?.entry.address.toLowerCase();return`<article class="leaderboard-entry ${o?"winner":""} ${d?"selected-entry":""}"><div class="grow"><p class="message">${l(this.entryMessage(i))}</p><div class="row entry-caption">${o?'<span class="pill">Winner</span>':""}${s?'<span class="meta">Yours</span>':""}${i.moderated===!1&&i.name?`<span class="name">${l(i.name)}</span>`:""}</div></div><div class="entry-funding"><div class="meta mono">${e.strategy==="rent"?`${m((BigInt(i.score)*x).toString())} ETH/mo`:`${m(i.totalFunds)} ETH`}</div><span class="meta">${i.views===null?"Views unavailable":`${i.views.toLocaleString()} views`}</span>${c(`form:${e.strategy==="sale"?"fund":"stream"}:${i.address}`,d?"Selected":"Fund",`compact ${d?"primary":""}`,`aria-pressed="${d}" aria-label="${d?"Selected":"Fund"} message ${E(i.address)}"`)}</div></article>`}).join("")||'<p class="empty">No Markees yet. Create the first one.</p>'}${e.strategy==="rent"&&e.rankedTop&&e.rankedTop.toLowerCase()!==e.top?.toLowerCase()?`<p class="note">The ranking has changed. ${c(`claim-top:${e.rankedTop}`,"Refresh winner","compact")}</p>`:""}${e.nextOffset!==null?c("more","Browse more messages","full"):""}</div>`:""}</section>`}selectedMessageHtml(e){let t=this.snapshot,a=t.wallet,r=e.owner.toLowerCase()===this.account?.toLowerCase(),i=t.entries.find(d=>d.owner.toLowerCase()===this.account?.toLowerCase()),s=e.address.toLowerCase()===t.top?.toLowerCase(),o=e.address.toLowerCase()===a?.backedMarkee?.toLowerCase()&&BigInt(a?.flowRate??"0")>0n;return`<section class="message-card ${s?"winner":""}"><div class="row between"><span class="eyebrow">${r?"Your Markee":"Markee you\u2019re funding"}</span>${s?'<span class="pill">Winner</span>':""}</div><p class="message">${l(this.entryMessage(e))}</p>${e.moderated===!1&&e.name?`<p class="name">${l(e.name)}</p>`:""}<div class="row message-tools">${r?c(`form:edit-message:${e.address}`,"Edit message","text-button")+c(`form:edit-name:${e.address}`,"Edit name","text-button"):""}${!r&&i?c(`form:${t.strategy==="rent"?"stream":"fund"}:${i.address}`,"Back to your Markee","text-button"):""}${c("create","Create your own Markee","text-button")}${t.strategy==="rent"&&this.account?c(`claim-refund:${e.address}`,"Collect refund","text-button"):""}</div><div class="message-stats">${t.strategy==="rent"?`<span class="meta">${this.account?o?s?"\u25CF Active stream":a?.poolConnected?"\u25CF Stream refunded while not the winner":"\u25CF Connect your refund pool in Deposit manager":"No active stream from your wallet to this message":"Live message ranking"}</span><div class="stats-grid"><div><span class="stat-label">Ranking rate</span><strong>${m((BigInt(e.score)*x).toString())} ETH/mo</strong></div>${this.account?`<div><span class="stat-label">Your rate</span><strong>${m((o?BigInt(a.flowRate)*x:0n).toString())} ETH/mo</strong></div>`:""}${a?`<div><span class="stat-label">ETHx balance</span><strong>${m(a.ethx)} ETHx</strong></div><div><span class="stat-label">Funds remaining</span><strong title="Across all of your ETHx flows">${a.runwaySeconds===null?"No net outflow":`${(Number(a.runwaySeconds)/86400).toFixed(1)} days`}</strong></div>`:""}</div>${BigInt(e.legacyFloor)>0n?`<p class="meta">Ranking includes a decaying legacy floor of ${m((BigInt(e.legacyFloor)*x).toString())} ETH/mo.</p>`:""}`:`<div class="stats-grid"><div><span class="stat-label">Total funded</span><strong>${m(e.totalFunds)} ETH</strong></div><div><span class="stat-label">Views</span><strong>${e.views===null?"Unavailable":e.views.toLocaleString()}</strong></div></div>`}</div></section>`}fundingHtml(e){let t=this.snapshot,a=t.wallet,r=t.strategy==="rent",i=I(t,e),s=!!e&&e.address.toLowerCase()===a?.backedMarkee?.toLowerCase(),o=r&&s?BigInt(a.flowRate)*x:0n,d=BigInt(t.minimum)>i.minimum?BigInt(t.minimum):i.minimum,f=o>d?o:d,p=!r&&e?1n:BigInt(t.minimum);return`<section class="funding-card"><label for="amount">${r?"Monthly streaming rate":"Payment amount"}</label><div class="amount-row"><div class="amount-value"><input id="amount" name="amount" inputmode="decimal" value="${l(H(f.toString()))}" required aria-describedby="amount-hint"><span class="mono">${r?"ETHx/mo":"ETH"}</span></div><div class="amount-presets">${c("preset:min","MIN","compact mono",'title="Use the minimum amount"')}${c("preset:boost",i.double?"2\xD7":"WIN","compact mono",'title="Suggest an amount using the loaded ranking"')}</div></div><div class="funding-caption"><span id="amount-hint">Minimum ${H(p.toString())} ${r?"ETH/mo":"ETH"}</span>${this.account&&a?`<span>Balance ${m(a.eth)} ETH</span>`:""}</div><div class="funding-tools">${this.account?c("tab:wallet",r?"Deposit manager \u2192":"Wallet & rewards \u2192","text-button"):""}<span class="meta">${r?a?.runwaySeconds!=null?`${(Number(a.runwaySeconds)/86400).toFixed(1)} days remaining`:a?`${m(a.ethx)} ETHx available`:"ETH funds your ETHx balance":"One-time payment"}</span></div></section><p class="meta funding-hint">${r?"Unspent rent is refunded while your message is not the winner. You can stop streaming at any time.":e?"Adding funds keeps the current message owner.":"The paying wallet will own this message."} Shortcuts use the loaded ranking; positions can change.</p>`}formHtml(){let e=this.snapshot,t=this.form;return t?.kind.startsWith("edit")?`<form id="markee-action" data-form="entry"><section class="message-card"><div class="eyebrow">Your Markee</div>${t.kind==="edit-message"?this.field("message","Markee message",t.entry.message,`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0):this.field("name","Your name (optional)",t.entry.name,`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section></form>`:`<form id="markee-action" data-form="${t?"entry":"create"}">${t?this.selectedMessageHtml(t.entry):`<section class="message-card editor-card">${this.field("message","Markee message","",`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0)}${this.field("name","Your name (optional)","",`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section>`}${this.fundingHtml(t?.entry)}${!t&&e.strategy==="rent"?'<p class="note">First create your message, then review and confirm its stream. Your chosen rate is kept for the next step.</p>':""}</form>`}updateFields(){for(let t of this.root.querySelectorAll("[data-byte-limit]")){let a=Number(t.dataset.byteLimit),r=new TextEncoder().encode(t.value).length;t.setCustomValidity(r>a?`Use at most ${a} UTF-8 bytes.`:"");let i=this.root.querySelector(`[data-count-for="${t.name}"]`);i&&(i.textContent=`${r}/${a}`)}let e=this.root.querySelector("#markee-action #amount");if(e&&this.snapshot){let t=I(this.snapshot,this.form?.entry),a;try{a=BigInt(b(e.value,this.snapshot.strategy==="sale"))}catch{}let r=this.snapshot.strategy==="sale"&&this.form?1n:BigInt(this.snapshot.minimum);e.setCustomValidity(a===void 0?"Enter a valid ETH amount.":a<r?`Use at least ${H(r.toString())} ETH${this.snapshot.strategy==="rent"?" per month":""}.`:""),this.root.querySelector('[data-cmd="preset:min"]')?.setAttribute("aria-pressed",String(a===t.minimum)),this.root.querySelector('[data-cmd="preset:boost"]')?.setAttribute("aria-pressed",String(a===t.boost))}}walletHtml(){let e=this.snapshot,t=e.wallet;if(!t)return'<p class="empty">Connect your wallet to see balances and manage your Markee.</p>'+c("connect","Connect app wallet","primary full");let a=`<h2>Your wallet</h2><p class="meta mono">${l(t.address)}</p><div class="grid"><div class="card"><span class="meta">Native ETH</span><div class="metric">${m(t.eth)}</div></div><div class="card"><span class="meta">MARKEE</span><div class="metric">${t.markee===null?"Unavailable":m(t.markee,2)}</div></div></div>`;return e.strategy==="sale"?a+'<p class="note">Payments reward the paying wallet when this board has RevNet enabled. Manage your messages from the leaderboard.</p>':(a+=`<div class="divider"></div><div class="card"><div class="stat"><span>Available ETHx</span><strong>${m(t.ethx)} ETHx</strong></div><div class="stat"><span>This board\u2019s monthly rate</span><strong>${m((BigInt(t.flowRate)*2628000n).toString())} ETH</strong></div><div class="stat"><span>Refund flow / month</span><strong>${m((BigInt(t.refundRate)*2628000n).toString())} ETHx</strong></div><div class="stat"><span>Runway across all ETHx flows</span><strong>${t.runwaySeconds===null?"No net outflow":`${(Number(t.runwaySeconds)/86400).toFixed(1)} days`}</strong></div><p class="meta">Snapshot at ${new Date(t.observedAt*1e3).toLocaleTimeString()}. Balances and rates can change.</p><div class="row">${BigInt(t.flowRate)>0n?c("stop","Stop stream","danger"):""}${t.backedMarkee&&!t.poolConnected?c(`connect-refund:${t.backedMarkee}`,"Connect refund pool","accent"):""}${c("refresh","Refresh balances")}</div></div><div class="divider"></div><h3>Manage ETHx</h3><form data-form="balance"><div class="grid"><div><label for="kind">Action</label><select id="kind" name="kind"><option value="wrap">Deposit ETH \u2192 ETHx</option><option value="unwrap">Withdraw ETHx \u2192 ETH</option></select></div>${this.field("amount","Amount","0.001")}</div><button type="submit" class="btn">Review balance change</button></form><div class="divider"></div><div class="card"><h3>Buffer and rewards</h3><div class="stat"><span>Refundable board buffer</span><strong>${m(t.withdrawableDeposit)} ETHx</strong></div><div class="stat"><span>Accrued rent to settle</span><strong>${m(t.pendingSettlement)} ETH</strong></div><p class="meta">Rewards come from actual rent spent, not the ETH deposited into your wallet.</p><div class="row">${BigInt(t.withdrawableDeposit)>0n?c("withdraw-buffer","Recover buffer"):""}${BigInt(t.pendingSettlement)>0n?c("settle",e.revnetEnabled?"Claim MARKEE":"Settle rent","primary"):""}${t.backedMarkee&&BigInt(t.poolClaimable)>0n?c(`claim-refund:${t.backedMarkee}`,"Collect pool refund"):""}</div></div>`,a)}communityHtml(){let e=this.snapshot.community;return e?`<h2>Community treasury</h2><p class="muted">Community council members can activate Markee and collect community revenue.</p><div class="card"><div class="stat"><span>Integration</span><strong>${e.integration.status==="active"?"Active":"Not activated"}</strong></div><div class="stat"><span>Available revenue</span><strong>${m(e.revenue.claimableAmount)} ETH</strong></div>${e.permissions?.councilSafe?`<p class="meta">Council treasury<br><span class="mono">${l(e.permissions.councilSafe)}</span></p>`:""}<div class="row">${this.adminProcessing?'<p class="note">A signed community action is processing. Check it before authorizing another.</p>'+c("admin-check","Check community action","primary"):this.account?e.integration.status!=="active"&&e.permissions?.canActivate?c("activate","Activate community Markee","primary"):e.permissions?.canClaim&&BigInt(e.revenue.claimableAmount)>0n?c("claim","Review revenue claim","primary"):'<span class="meta">No authorized action is currently available for this wallet.</span>':c("connect","Connect council wallet","primary")}</div></div>${this.adminResult?`<div class="success">Source transaction confirmed. ${q(this.adminResult.transactionUrl||"","View transaction")}${this.adminResult.bridged?"<p>Bridge delivery is tracked separately from the source transaction.</p>":""}${c("bridge","Check transfer status")}</div>`:""}`:""}title(){let e=this.snapshot;return this.wallets?"Connect your wallet":this.review?this.review.action.kind==="create"&&BigInt(this.review.transaction.value)===0n?"Review creation":this.review.action.kind.startsWith("edit-")?"Review change":"Review payment":this.authorization?"Review authorization":this.pending?"Payment in progress":this.tab==="wallet"?e?.strategy==="rent"?"Deposit manager":"Wallet & rewards":this.tab==="community"||e&&!e.board?"Community treasury":this.form?.kind.startsWith("edit")?"Edit your Markee":this.form?this.form.entry.owner.toLowerCase()!==this.account?.toLowerCase()?"Fund a Markee":e?.strategy==="sale"?"Fund your Markee":BigInt(e?.wallet?.flowRate??"0")>0n?"Manage your Markee stream":"Stream to your Markee":"Change the Markee Sign"}hostedEligible(){let e=this.snapshot;return!!e&&e.strategy==="sale"&&e.chainId===8453&&e.placement.kind==="board"&&e.revnetEnabled&&!!e.token}footerHtml(){let e=this.snapshot,t="",a=!1;if(this.wallets)t=c("back","Back");else if(this.review)t=c("back","Back")+c("send",this.review.action.kind==="fund"||this.review.action.kind==="stream"||this.review.action.kind==="create"&&BigInt(this.review.transaction.value)>0n?"Confirm payment":"Confirm in wallet","primary");else if(this.authorization)t=c("back","Back")+c("sign","Sign authorization","primary");else if(this.pending)t=c("check","Check transaction","primary");else if(e&&this.tab==="main"&&e.board){let r=this.form?.kind.startsWith("edit"),i=r?c("back","Cancel"):e.strategy==="rent"&&BigInt(e.wallet?.flowRate??"0")>0n?c("stop","Stop streaming","danger"):"";this.account?(a=this.cardAvailable&&this.hostedEligible()&&!r,t=(a?c("card","Pay by card","primary"):"")+i+`<button class="btn primary" type="submit" form="markee-action">${r?"Review change":!this.form&&e.strategy==="rent"?"Review creation":"Review payment info"}</button>`):t=c("card","Pay","primary",!this.checkoutChecked||!this.cardAvailable||!this.hostedEligible()?"disabled":"")}else e&&(t=c("tab:main","Back to Markee"));return`<footer${this.review?' class="review-footer"':a?' class="payment-choice-footer"':""}><div class="footer-actions">${t}</div>${this.review?"":`<div class="footer-meta"><span>Powered by Markee${this.account?` \xB7 ${E(this.account)}`:""}</span>${this.account&&e?.community&&e.board&&this.tab!=="community"&&!this.authorization&&!this.pending?c("tab:community","Community treasury","text-button"):""}</div>`}</footer>`}render(){if(this.closed)return;let e=this.root.activeElement,t=e?.dataset.cmd,a=e?.id,r=this.wallets?"wallets":this.review?`review:${this.review.id}`:this.authorization?`authorization:${this.authorization.value.nonce}`:this.pending?`pending:${this.pending.hash}`:`${this.tab}:${this.form?.kind??"create"}:${this.form?.entry.address??""}`,i=r===this.renderedView?this.root.querySelector(".content")?.scrollTop??0:0;this.renderedView=r;let s=!document.activeElement||document.activeElement===document.body||document.activeElement===this.host,o=this.snapshot,d="";this.wallets?d=`<h2>Choose your wallet</h2><div class="wallets">${this.wallets.map((g,v)=>c(`wallet:${v}`,l(g.name))).join("")}</div>`:this.review?d=this.reviewHtml():this.authorization?d=this.authorizationHtml():o?this.pending?d=`<h2>Waiting for confirmation</h2><p>Your transaction was sent. You can close this modal and come back to check it.</p><p class="meta mono">${l(this.pending.hash)}</p><p class="note">Do not send a second payment while this transaction is pending.</p>`:!o.board||this.tab==="community"?d=this.communityHtml():this.tab==="wallet"?d=this.walletHtml():d=`${this.form?.kind.startsWith("edit")?"":this.entriesHtml()}${this.formHtml()}${this.account?"":`<p class="note">${this.checkoutChecked?this.hostedEligible()?this.cardAvailable?"Sign in and pay on Markee. Your payment wallet and rewards are managed there.":"Pay in Markee is temporarily unavailable. Please try again later.":"Pay in Markee is not supported for this board yet.":"Checking Markee checkout availability\u2026"}</p>`}`:d=this.error?c("refresh","Retry","primary"):'<div class="loading"><span class="spinner"></span>Loading Markee\u2026</div>';let f=this.result?`<div class="${this.result.status==="reverted"||this.result.settlement==="deferred"?"error":"success"}">${this.result.status==="reverted"?"Transaction reverted. No action was completed.":this.result.settlement==="deferred"?"The transaction confirmed, but reward settlement was deferred. Your claim remains available.":`Transaction confirmed.${this.result.tokensReceived&&BigInt(this.result.tokensReceived)>0n?` ${m(this.result.tokensReceived,2)} MARKEE delivered to your wallet.`:""}`} ${q(this.result.explorerUrl,"View receipt")}</div>`:"";this.root.innerHTML=`<style>${K}</style><div class="overlay"><section class="panel" role="dialog" aria-modal="true" aria-labelledby="markee-title"><header><div class="grow"><h1 id="markee-title">${l(this.title())}</h1><p class="header-caption">${l(o?.name||"Markee")}${o?` \xB7 ${o.strategy==="rent"?"For rent":"For sale"}${o.chainId===8453?" \xB7 Base":o.chainId===11155111?" \xB7 Sepolia testnet":""}`:""}</p></div><button class="close" data-cmd="close" aria-label="Close Markee">\xD7</button></header><main class="content" aria-busy="${this.busy}"><div role="status" aria-live="polite">${this.busy?'<p class="meta"><span class="spinner"></span>Working\u2026</p>':""}${this.error?`<div class="error">${l(this.error)}</div>`:""}${f}</div>${o?.warnings.map(g=>`<div class="note">${l(g)}</div>`).join("")||""}${d}</main>${this.footerHtml()}</section></div>`,this.busy&&this.root.querySelectorAll('button:not([data-cmd="close"])').forEach(g=>{g.disabled=!0});let p=this.drafts.get(this.draftKey());if(p)for(let g of this.root.querySelectorAll("input,textarea,select"))p[g.name]!==void 0&&(g.value=p[g.name]);this.updateFields();let w=this.root.querySelector(".content");w&&(w.scrollTop=i),this.viewObserver?.disconnect();let k=this.root.querySelector(".winner"),h=o?.entries.find(g=>g.address.toLowerCase()===o.top?.toLowerCase()),y=h?`${h.address}:${h.message}`:"";k&&h?.moderated===!1&&!this.viewed.has(y)&&typeof IntersectionObserver<"u"&&(this.viewObserver=new IntersectionObserver(g=>{g.some(v=>v.isIntersecting)&&(this.viewObserver?.disconnect(),this.viewed.add(y),this.client.recordView(h.address,h.message,window.location.origin).catch(()=>{this.viewed.delete(y)}))},{threshold:.5}),this.viewObserver.observe(k)),s&&((a?this.root.getElementById(a):t?[...this.root.querySelectorAll("[data-cmd]")].find(v=>v.dataset.cmd===t):null)??this.root.querySelector('[data-cmd="close"]'))?.focus({preventScroll:!0})}};function D(n={}){let e=new T(n),t,a=n.theme;return{client:e,open(r){return t?.close(),t=new R(e,{...r,theme:r.theme??a}),t},setTheme(r){a=r??{},t?.setTheme(a)},close(){t?.close(),t=void 0}}}function W(n){let e=n.entries.find(t=>t.address.toLowerCase()===n.top?.toLowerCase())??null;return{entry:e,visibility:!e||e.moderated===null?"unavailable":e.moderated?"flagged":"visible"}}var Z=`
|
|
129
|
+
:host{display:block;color:var(--markee-text);font-family:var(--markee-font-family);color-scheme:var(--markee-color-scheme)}
|
|
130
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
131
|
+
.sign{position:relative;overflow:hidden;border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:22px;min-height:190px}
|
|
132
|
+
.eyebrow{color:var(--markee-muted);font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
|
|
133
|
+
.board{margin:5px 0 20px;color:var(--markee-muted);font-size:13px}
|
|
134
|
+
.message{font-size:clamp(20px,4vw,30px);line-height:1.3;white-space:pre-wrap;overflow-wrap:anywhere;margin:0 0 16px}
|
|
135
|
+
.author{color:var(--markee-muted);font-size:13px;margin:0 0 16px}
|
|
136
|
+
.obscured{filter:blur(8px);user-select:none;pointer-events:none}
|
|
137
|
+
.veil{position:absolute;inset:55px 12px 62px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--markee-surface) 75%,transparent);color:var(--markee-muted);font-size:14px;text-align:center;padding:15px}
|
|
138
|
+
.notice{color:var(--markee-muted);font-size:14px;min-height:54px}
|
|
139
|
+
.action{appearance:none;border:0;border-radius:var(--markee-control-radius);background:var(--markee-primary);color:var(--markee-primary-text);font:inherit;font-weight:700;padding:11px 16px;cursor:pointer}
|
|
140
|
+
.action:focus-visible{outline:2px solid var(--markee-focus-ring);outline-offset:3px}
|
|
141
|
+
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}
|
|
142
|
+
`;function ee(n,e,t=!1){let a=n?.name||"Markee",r=n?n.strategy==="rent"?"For rent":"For sale":"",{entry:i,visibility:s}=n?W(n):{entry:null,visibility:"unavailable"},o=t?'<p class="notice" role="status">Markee sign is temporarily unavailable.</p>':n?i?s==="unavailable"?'<p class="notice" role="status">Message unavailable while moderation loads.</p>':`<div class="${s==="flagged"?"obscured":""}" ${s==="flagged"?'aria-hidden="true"':""}><p class="message">${l(i.message)}</p><p class="author">${l(i.name||E(i.owner))}</p></div>${s==="flagged"?'<div class="veil" role="status">This message has been flagged.</div>':""}`:'<p class="notice">The sign is waiting for its first message.</p>':'<p class="notice" role="status">Loading the Markee sign\u2026</p>';return`<style>${Z}</style><section class="sign" aria-label="${l(a)} Markee sign"><div class="eyebrow">Current Markee sign</div><p class="board">${l(a)}${r?` \xB7 ${r}`:""}</p>${o}${e&&n?.board?'<button class="action" type="button" data-markee-open>Open Markee</button>':""}</section>`}function te(n,e){if(typeof document>"u")throw new Error("Mount the Markee sign in a browser.");let t=document.createElement("div");t.setAttribute("data-markee-sign","");let a=t.attachShadow({mode:"open"});n.appendChild(t);let r=L(t,e.theme),i=new T(e),s=D(e),o=Number.isFinite(e.refreshIntervalMs)?Math.max(1e4,e.refreshIntervalMs):3e4,d=!0,f,p,w,k=new Set,h=null,y=(v=!1)=>{if(w?.disconnect(),a.innerHTML=ee(h,e.showAction!==!1,v),v||!h||typeof IntersectionObserver>"u")return;let{entry:$,visibility:_}=W(h);if(!$||_!=="visible")return;let O=`${$.address}:${$.message}`;k.has(O)||(w=new IntersectionObserver(V=>{V.some(Y=>Y.isIntersecting)&&(w?.disconnect(),k.add(O),i.recordView($.address,$.message,window.location.origin).catch(()=>{k.delete(O)}))},{threshold:.5}),w.observe(t))},g=async()=>{if(!d)return;clearTimeout(p),f?.abort();let v=new AbortController;f=v;try{let $=await i.snapshot(e.placement,null,void 0,v.signal);d&&f===v&&(h=$,y())}catch{d&&f===v&&!v.signal.aborted&&(h=null,y(!0))}finally{d&&f===v&&(p=setTimeout(()=>void g(),o))}};return a.addEventListener("click",v=>{v.target.closest("[data-markee-open]")&&s.open({placement:e.placement})}),y(),e.siteUrl&&i.registerSite(e.placement),g(),{refresh:g,setTheme:r.set,destroy(){d=!1,f?.abort(),clearTimeout(p),w?.disconnect(),s.close(),r.destroy(),t.remove()}}}export{U as DEFAULT_MARKEE_API_URL,T as MarkeeClient,u as MarkeeError,R as MarkeeModal,B as checkoutStatus,D as createMarkee,te as createMarkeeSign,P as discoverWallets,m as formatEth,F as openHostedCheckout,b as parseEth,j as savedCheckout,W as signContent};
|
package/dist/modal.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare class MarkeeModal {
|
|
|
13
13
|
private root;
|
|
14
14
|
private theme;
|
|
15
15
|
private snapshot?;
|
|
16
|
+
private cardAvailable;
|
|
17
|
+
private checkoutChecked;
|
|
16
18
|
private account;
|
|
17
19
|
private tab;
|
|
18
20
|
private leaderboardOpen;
|
|
@@ -69,10 +71,11 @@ export declare class MarkeeModal {
|
|
|
69
71
|
private walletHtml;
|
|
70
72
|
private communityHtml;
|
|
71
73
|
private title;
|
|
74
|
+
private hostedEligible;
|
|
72
75
|
private footerHtml;
|
|
73
76
|
private render;
|
|
74
77
|
}
|
|
75
|
-
export declare function createMarkee(options
|
|
78
|
+
export declare function createMarkee(options?: SDKOptions): {
|
|
76
79
|
client: MarkeeClient;
|
|
77
80
|
open(options: ModalOptions): MarkeeModal;
|
|
78
81
|
setTheme(next?: MarkeeTheme): void;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import { type MarkeeSignOptions } from './sign.js';
|
|
2
3
|
import type { Placement, SDKOptions } from './types.js';
|
|
3
4
|
export interface MarkeeModalProps extends SDKOptions {
|
|
4
5
|
open: boolean;
|
|
@@ -6,7 +7,10 @@ export interface MarkeeModalProps extends SDKOptions {
|
|
|
6
7
|
onClose(): void;
|
|
7
8
|
}
|
|
8
9
|
/** No wagmi, ConnectKit, Privy, or React provider is required by this wrapper. */
|
|
9
|
-
export declare function MarkeeModal(props: MarkeeModalProps):
|
|
10
|
+
export declare function MarkeeModal(props: MarkeeModalProps): import("react").DetailedReactHTMLElement<{
|
|
11
|
+
hidden: true;
|
|
12
|
+
'data-markee-address': `0x${string}`;
|
|
13
|
+
}, HTMLElement> | null;
|
|
10
14
|
export declare function MarkeeButton({ children, onClick, ...props }: {
|
|
11
15
|
children?: ReactNode;
|
|
12
16
|
onClick(): void;
|
|
@@ -18,3 +22,11 @@ export declare function MarkeeButton({ children, onClick, ...props }: {
|
|
|
18
22
|
className?: string;
|
|
19
23
|
disabled?: boolean;
|
|
20
24
|
}, HTMLElement>;
|
|
25
|
+
export interface MarkeeSignProps extends MarkeeSignOptions {
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/** The current sign, including Markee-hosted moderation, without an app-side data provider. */
|
|
29
|
+
export declare function MarkeeSign(props: MarkeeSignProps): import("react").DetailedReactHTMLElement<{
|
|
30
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
31
|
+
className: string | undefined;
|
|
32
|
+
}, HTMLDivElement>;
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{createElement as j,useEffect as O,useRef as N}from"react";var p=class extends Error{constructor(t,a="MARKEE_ERROR",i){super(t);this.code=a;this.status=i;this.name="MarkeeError"}};async function P(){if(typeof window>"u")return[];let n=new Map,e=a=>{let i=a.detail;i?.provider?.request&&typeof i.info?.uuid=="string"&&n.set(i.info.uuid,{uuid:i.info.uuid,name:String(i.info.name).slice(0,80),provider:i.provider})};window.addEventListener("eip6963:announceProvider",e),window.dispatchEvent(new Event("eip6963:requestProvider")),await new Promise(a=>setTimeout(a,150)),window.removeEventListener("eip6963:announceProvider",e);let t=window.ethereum;return!n.size&&t?.request&&n.set("injected",{uuid:"injected",name:"Browser wallet",provider:t}),[...n.values()]}var x=n=>typeof n=="string"&&/^0x[\da-f]{40}$/i.test(n),$=n=>typeof n=="string"&&/^0x[\da-f]{64}$/i.test(n),T=class{constructor(e){this.options=e;let t=new URL(e.apiUrl);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new p("Use an HTTPS Markee API URL (HTTP is allowed on localhost).");this.apiUrl=t.href.replace(/\/$/,""),this.fetcher=e.fetch||globalThis.fetch.bind(globalThis)}apiUrl;fetcher;injected=null;sending=!1;inMemoryPending=[];adminMemory=null;communityReceipts={};async request(e,t,a){let i=await this.fetcher(`${this.apiUrl}/${e}`,{method:t===void 0?"GET":"POST",body:t===void 0?void 0:JSON.stringify(t),headers:t===void 0?void 0:{"Content-Type":"application/json"},credentials:"omit",signal:a||AbortSignal.timeout(55e3)}),r=await i.json().catch(()=>null);if(!i.ok)throw new p(r?.error||`Markee returned HTTP ${i.status}.`,r?.code,i.status);return r}async provider(){return this.options.wallet?this.options.wallet.getProvider():this.injected}async account(){let e=await this.provider();if(!e)return null;let t=await e.request({method:"eth_accounts"});return Array.isArray(t)&&x(t[0])?t[0]:null}async connect(e){let t=await this.provider();if(this.options.wallet)t||(t=await this.options.wallet.connect?.()||null);else{if(t=e||t,!t){let i=await P();if(i.length>1)throw new p("Select a browser wallet.","SELECT_WALLET");t=i[0]?.provider||null}this.injected=t}if(!t)throw new p("Connect a wallet in the app or install a browser wallet to continue.","NO_WALLET");let a=await t.request({method:"eth_requestAccounts"});if(!Array.isArray(a)||!x(a[0]))throw new p("The wallet did not return an account.");return a[0]}async snapshot(e,t,a,i){let r=new URLSearchParams({placement:JSON.stringify(e)});return t&&r.set("account",t),a!==void 0&&r.set("offset",String(a)),this.request(`snapshot?${r}`,void 0,i)}async prepare(e,t){let a=await this.account();if(!a)throw new p("Connect your wallet first.","NOT_CONNECTED");return this.request("prepare",{placement:e,account:a,action:t})}async ensureWallet(e,t){let a=await this.provider();if(!a||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("Your wallet account changed. Review this action again.","ACCOUNT_CHANGED");let i=Number(await a.request({method:"eth_chainId"}));if(i!==t&&await a.request({method:"wallet_switchEthereumChain",params:[{chainId:`0x${t.toString(16)}`}]}),i=Number(await a.request({method:"eth_chainId"})),i!==t||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("The wallet account or network changed. Review again.","WALLET_CHANGED");return a}async send(e){if(this.sending)throw new p("A wallet request is already in progress.");if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");if(this.pending(e.placement,e.transaction.from))throw new p("A transaction is still pending for this wallet and placement. Check it before submitting again.","PENDING_TRANSACTION");this.sending=!0;try{let a=await this.ensureWallet(e.transaction.from,e.transaction.chainId);if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");let{chainId:i,...r}=e.transaction,s=await a.request({method:"eth_sendTransaction",params:[r]});if(!$(s))throw new p("The wallet returned an unexpected transaction identifier. Check your wallet before retrying.");return this.persist([...this.records(),{preparation:e,hash:s}]),this.options.onEvent?.({type:"submitted",hash:s}),s}catch(a){throw this.options.onEvent?.({type:"error",message:a instanceof Error?a.message:String(a)}),a}finally{this.sending=!1}}async verify(e){let t=await this.request("verify",{id:e.preparation.id,hash:e.hash});return t.status!=="pending"&&(this.persist(this.records().filter(a=>a.hash!==e.hash)),t.status==="confirmed"&&this.options.onEvent?.({type:"confirmed",hash:t.hash})),t}async reconcile(e,t){if(!$(t))throw new p("Enter a valid replacement transaction hash.");let a=await this.request("verify",{id:e.preparation.id,hash:t});return a.status!=="pending"&&this.persist(this.records().filter(i=>i.hash!==e.hash)),a}storageKey(){return`markee:sdk:v1:pending:${this.apiUrl}`}records(){try{if(typeof localStorage>"u")return this.inMemoryPending;let e=JSON.parse(localStorage.getItem(this.storageKey())||"[]");return Array.isArray(e)?e.filter(t=>$(t?.hash)&&typeof t.preparation?.id=="string"&&x(t.preparation?.transaction?.from)&&t.preparation?.placement):[]}catch{return this.inMemoryPending}}persist(e){this.inMemoryPending=e;try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey(),JSON.stringify(e))}catch{}}pending(e,t){return this.records().find(a=>JSON.stringify(a.preparation.placement).toLowerCase()===JSON.stringify(e).toLowerCase()&&a.preparation.transaction.from.toLowerCase()===t.toLowerCase())}async quote(e){return this.request(`community/quote?${new URLSearchParams({chainId:String(e.chainId),community:e.community})}`)}async authorize(e,t){let a=await this.account();if(!a)throw new p("Connect your community council wallet first.");return this.request(`community/${t}`,{action:"challenge",chainId:e.chainId,community:e.community,account:a})}async executeAuthorization(e,t,a){if(this.pendingAuthorization())throw new p("An earlier community authorization is still processing. Check its status first.");let i=t.typedData,s=await(await this.ensureWallet(a,i.domain.chainId)).request({method:"eth_signTypedData_v4",params:[a,JSON.stringify({...i,types:{...i.types,EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}]}})]});if(typeof s!="string"||!/^0x[\da-f]+$/i.test(s))throw new p("Wallet did not return a typed-data signature.");return this.saveAuthorization({kind:e,nonce:t.nonce,signature:s,account:a,community:i.domain.verifyingContract,chainId:i.domain.chainId}),this.resumeAuthorization()}pendingAuthorization(){try{let e=typeof localStorage>"u"?this.adminMemory:JSON.parse(localStorage.getItem(`${this.storageKey()}:admin`)||"null");return e&&["activate","claim"].includes(e.kind)&&x(e.account)&&x(e.community)&&typeof e.nonce=="string"&&typeof e.signature=="string"?e:null}catch{return this.adminMemory}}saveAuthorization(e){this.adminMemory=e;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:admin`,JSON.stringify(e))}catch{}}async resumeAuthorization(){let e=this.pendingAuthorization();if(!e)throw new p("There is no pending community authorization.");let t=await this.request(`community/${e.kind}`,{action:"verify",nonce:e.nonce,signature:e.signature});if(t.status==="complete"&&t.result){let a=`${e.chainId}:${e.community.toLowerCase()}`;this.communityReceipts[a]=t.result;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:community:${a}`,JSON.stringify(t.result))}catch{}}return(t.status==="complete"||t.status==="failed")&&this.saveAuthorization(null),t}communityReceipt(e){let t=`${e.chainId}:${e.community.toLowerCase()}`;try{let a=typeof localStorage>"u"?this.communityReceipts[t]:JSON.parse(localStorage.getItem(`${this.storageKey()}:community:${t}`)||"null");return a&&$(a.transactionHash)?a:null}catch{return this.communityReceipts[t]||null}}bridgeStatus(e,t,a,i){return this.request(`community/status?${new URLSearchParams({protocol:e,transactionHash:t,fromChainId:String(a),toChainId:String(i)})}`)}recordView(e,t,a){return this.request("views",{address:e,message:t,url:a})}};function v(n,e=!1){let t=n.trim();if(!/^\d+(\.\d{0,18})?$/.test(t))throw new Error("Enter an ETH amount with up to 18 decimal places.");let[a,i=""]=t.split("."),r=BigInt(a)*10n**18n+BigInt(i.padEnd(18,"0"));if(!e&&r===0n||r>=2n**256n)throw new Error("Enter a positive amount.");return r.toString()}function m(n,e=6){let t=BigInt(n),a=t<0n?"-":"",i=t<0n?-t:t,r=(i%10n**18n).toString().padStart(18,"0").slice(0,e).replace(/0+$/,"");return i>0n&&i<10n**BigInt(18-e)?`${a}<0.${"0".repeat(e-1)}1`:`${a}${i/10n**18n}${r?`.${r}`:""}`}function E(n){return`${n.slice(0,6)}\u2026${n.slice(-4)}`}function l(n){return String(n).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}var H=`
|
|
1
|
+
"use client";import{createElement as B,useEffect as A,useRef as P}from"react";var Q="https://2staging.markee.xyz/api/sdk/v1",p=class extends Error{constructor(t,a="MARKEE_ERROR",r){super(t);this.code=a;this.status=r;this.name="MarkeeError"}};async function q(){if(typeof window>"u")return[];let n=new Map,e=a=>{let r=a.detail;r?.provider?.request&&typeof r.info?.uuid=="string"&&n.set(r.info.uuid,{uuid:r.info.uuid,name:String(r.info.name).slice(0,80),provider:r.provider})};window.addEventListener("eip6963:announceProvider",e),window.dispatchEvent(new Event("eip6963:requestProvider")),await new Promise(a=>setTimeout(a,150)),window.removeEventListener("eip6963:announceProvider",e);let t=window.ethereum;return!n.size&&t?.request&&n.set("injected",{uuid:"injected",name:"Browser wallet",provider:t}),[...n.values()]}var C=n=>typeof n=="string"&&/^0x[\da-f]{40}$/i.test(n),L=n=>typeof n=="string"&&/^0x[\da-f]{64}$/i.test(n),k=class{constructor(e={}){this.options=e;let t=new URL(e.apiUrl??Q);if(t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw new p("Use an HTTPS Markee API URL (HTTP is allowed on localhost).");this.apiUrl=t.href.replace(/\/$/,""),this.fetcher=e.fetch||globalThis.fetch.bind(globalThis)}apiUrl;fetcher;injected=null;sending=!1;inMemoryPending=[];adminMemory=null;communityReceipts={};async request(e,t,a){let r=await this.fetcher(`${this.apiUrl}/${e}`,{method:t===void 0?"GET":"POST",body:t===void 0?void 0:JSON.stringify(t),headers:t===void 0?void 0:{"Content-Type":"application/json"},credentials:"omit",signal:a||AbortSignal.timeout(55e3)}),i=await r.json().catch(()=>null);if(!r.ok)throw new p(i?.error||`Markee returned HTTP ${r.status}.`,i?.code,r.status);return i}async provider(){return this.options.wallet?this.options.wallet.getProvider():this.injected}async account(){let e=await this.provider();if(!e)return null;let t=await e.request({method:"eth_accounts"});return Array.isArray(t)&&C(t[0])?t[0]:null}async connect(e){let t=await this.provider();if(this.options.wallet)t||(t=await this.options.wallet.connect?.()||null);else{if(t=e||t,!t){let r=await q();if(r.length>1)throw new p("Select a browser wallet.","SELECT_WALLET");t=r[0]?.provider||null}this.injected=t}if(!t)throw new p("Connect a wallet in the app or install a browser wallet to continue.","NO_WALLET");let a=await t.request({method:"eth_requestAccounts"});if(!Array.isArray(a)||!C(a[0]))throw new p("The wallet did not return an account.");return a[0]}verifySite(e,t){return this.request("sites/verify",{placement:e,siteUrl:t})}siteRequests=new Map;registerSite(e){if(!this.options.siteUrl)return;let t=JSON.stringify([e,this.options.siteUrl]);if(this.siteRequests.has(t))return;let a=this.verifySite(e,this.options.siteUrl);this.siteRequests.set(t,a),a.then(r=>this.options.onSiteVerification?.(r),r=>this.options.onSiteVerification?.({verified:!1,url:this.options.siteUrl,message:r instanceof Error?r.message:"Site verification failed."})).catch(()=>{})}async snapshot(e,t,a,r){let i=new URLSearchParams({placement:JSON.stringify(e)});return t&&i.set("account",t),a!==void 0&&i.set("offset",String(a)),this.request(`snapshot?${i}`,void 0,r)}async prepare(e,t){let a=await this.account();if(!a)throw new p("Connect your wallet first.","NOT_CONNECTED");return this.request("prepare",{placement:e,account:a,action:t})}async ensureWallet(e,t){let a=await this.provider();if(!a||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("Your wallet account changed. Review this action again.","ACCOUNT_CHANGED");let r=Number(await a.request({method:"eth_chainId"}));if(r!==t&&await a.request({method:"wallet_switchEthereumChain",params:[{chainId:`0x${t.toString(16)}`}]}),r=Number(await a.request({method:"eth_chainId"})),r!==t||(await this.account())?.toLowerCase()!==e.toLowerCase())throw new p("The wallet account or network changed. Review again.","WALLET_CHANGED");return a}async send(e){if(this.sending)throw new p("A wallet request is already in progress.");if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");if(this.pending(e.placement,e.transaction.from))throw new p("A transaction is still pending for this wallet and placement. Check it before submitting again.","PENDING_TRANSACTION");this.sending=!0;try{let a=await this.ensureWallet(e.transaction.from,e.transaction.chainId);if(e.expiresAt<=Date.now())throw new p("This review expired. Prepare the action again.","REVIEW_EXPIRED");let{chainId:r,...i}=e.transaction,s=await a.request({method:"eth_sendTransaction",params:[i]});if(!L(s))throw new p("The wallet returned an unexpected transaction identifier. Check your wallet before retrying.");return this.persist([...this.records(),{preparation:e,hash:s}]),this.options.onEvent?.({type:"submitted",hash:s}),s}catch(a){throw this.options.onEvent?.({type:"error",message:a instanceof Error?a.message:String(a)}),a}finally{this.sending=!1}}async verify(e){let t=await this.request("verify",{id:e.preparation.id,hash:e.hash});return t.status!=="pending"&&(this.persist(this.records().filter(a=>a.hash!==e.hash)),t.status==="confirmed"&&this.options.onEvent?.({type:"confirmed",hash:t.hash})),t}async reconcile(e,t){if(!L(t))throw new p("Enter a valid replacement transaction hash.");let a=await this.request("verify",{id:e.preparation.id,hash:t});return a.status!=="pending"&&this.persist(this.records().filter(r=>r.hash!==e.hash)),a}storageKey(){return`markee:sdk:v1:pending:${this.apiUrl}`}records(){try{if(typeof localStorage>"u")return this.inMemoryPending;let e=JSON.parse(localStorage.getItem(this.storageKey())||"[]");return Array.isArray(e)?e.filter(t=>L(t?.hash)&&typeof t.preparation?.id=="string"&&C(t.preparation?.transaction?.from)&&t.preparation?.placement):[]}catch{return this.inMemoryPending}}persist(e){this.inMemoryPending=e;try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey(),JSON.stringify(e))}catch{}}pending(e,t){return this.records().find(a=>JSON.stringify(a.preparation.placement).toLowerCase()===JSON.stringify(e).toLowerCase()&&a.preparation.transaction.from.toLowerCase()===t.toLowerCase())}async quote(e){return this.request(`community/quote?${new URLSearchParams({chainId:String(e.chainId),community:e.community})}`)}async authorize(e,t){let a=await this.account();if(!a)throw new p("Connect your community council wallet first.");return this.request(`community/${t}`,{action:"challenge",chainId:e.chainId,community:e.community,account:a})}async executeAuthorization(e,t,a){if(this.pendingAuthorization())throw new p("An earlier community authorization is still processing. Check its status first.");let r=t.typedData,s=await(await this.ensureWallet(a,r.domain.chainId)).request({method:"eth_signTypedData_v4",params:[a,JSON.stringify({...r,types:{...r.types,EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}]}})]});if(typeof s!="string"||!/^0x[\da-f]+$/i.test(s))throw new p("Wallet did not return a typed-data signature.");return this.saveAuthorization({kind:e,nonce:t.nonce,signature:s,account:a,community:r.domain.verifyingContract,chainId:r.domain.chainId}),this.resumeAuthorization()}pendingAuthorization(){try{let e=typeof localStorage>"u"?this.adminMemory:JSON.parse(localStorage.getItem(`${this.storageKey()}:admin`)||"null");return e&&["activate","claim"].includes(e.kind)&&C(e.account)&&C(e.community)&&typeof e.nonce=="string"&&typeof e.signature=="string"?e:null}catch{return this.adminMemory}}saveAuthorization(e){this.adminMemory=e;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:admin`,JSON.stringify(e))}catch{}}async resumeAuthorization(){let e=this.pendingAuthorization();if(!e)throw new p("There is no pending community authorization.");let t=await this.request(`community/${e.kind}`,{action:"verify",nonce:e.nonce,signature:e.signature});if(t.status==="complete"&&t.result){let a=`${e.chainId}:${e.community.toLowerCase()}`;this.communityReceipts[a]=t.result;try{typeof localStorage<"u"&&localStorage.setItem(`${this.storageKey()}:community:${a}`,JSON.stringify(t.result))}catch{}}return(t.status==="complete"||t.status==="failed")&&this.saveAuthorization(null),t}communityReceipt(e){let t=`${e.chainId}:${e.community.toLowerCase()}`;try{let a=typeof localStorage>"u"?this.communityReceipts[t]:JSON.parse(localStorage.getItem(`${this.storageKey()}:community:${t}`)||"null");return a&&L(a.transactionHash)?a:null}catch{return this.communityReceipts[t]||null}}bridgeStatus(e,t,a,r){return this.request(`community/status?${new URLSearchParams({protocol:e,transactionHash:t,fromChainId:String(a),toChainId:String(r)})}`)}recordView(e,t,a){return this.request("views",{address:e,message:t,url:a})}};var F=(n,e)=>`markee:checkout:v1:${n.apiUrl}:${JSON.stringify(e)}`;function X(n,e){try{let t=JSON.parse(localStorage.getItem(F(n,e))||"null");return t&&typeof t.id=="string"&&/^[a-f0-9]{48}$/.test(t.id)&&/^[a-f0-9]{64}$/.test(t.readToken)&&/^[a-f0-9]{64}$/.test(t.writeToken)&&Number.isFinite(t.expiresAt)?t:null}catch{return null}}async function W(n,e){return n.request("checkout/status",{id:e.id,token:e.readToken})}function S(n,e){try{localStorage.removeItem(F(n,e))}catch{}}async function j(n,e,t){let a=n.options.checkoutWindow==="redirect"?null:window.open("about:blank","_blank");a&&(a.opener=null);let r=X(n,e);try{if(r){let s=await W(n,r).catch(o=>{if(o instanceof p&&o.status===404)return S(n,e),r=null,null;throw o});if(s?.result?.status==="confirmed"||s?.result?.status==="reverted")return S(n,e),a?.close(),s.result;r&&s&&r.expiresAt<Date.now()&&["created","ready"].includes(s.status)&&(S(n,e),r=null)}if(!r){r=await n.request("checkout/create",{placement:e,action:t,origin:window.location.origin});try{localStorage.setItem(F(n,e),JSON.stringify(r))}catch{}}let i=new URL(`/checkout/${r.id}`,r.checkoutOrigin||n.apiUrl);if(i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1"].includes(i.hostname)))throw new Error("Invalid Markee checkout destination.");if(i.hash=new URLSearchParams({token:r.writeToken}).toString(),a)a.location.replace(i.href);else throw window.location.assign(i.href),new Error("Continuing payment on Markee.");for(let s=0;s<1800;s++){let o=await W(n,r);if(o.result&&o.status==="confirmed")return S(n,e),a.close(),o.result;if(o.status==="reverted")throw S(n,e),new Error("Payment reverted. Any unspent funds remain in your Markee wallet.");if(a.closed)throw new Error("Markee checkout closed. Choose Pay again to resume; funding alone does not complete payment.");await new Promise(c=>setTimeout(c,3e3))}throw new Error("Checkout is still pending. Reopen it to check the payment; do not pay again.")}catch(i){throw r||a?.close(),i}}function x(n,e=!1){let t=n.trim();if(!/^\d+(\.\d{0,18})?$/.test(t))throw new Error("Enter an ETH amount with up to 18 decimal places.");let[a,r=""]=t.split("."),i=BigInt(a)*10n**18n+BigInt(r.padEnd(18,"0"));if(!e&&i===0n||i>=2n**256n)throw new Error("Enter a positive amount.");return i.toString()}function m(n,e=6){let t=BigInt(n),a=t<0n?"-":"",r=t<0n?-t:t,i=(r%10n**18n).toString().padStart(18,"0").slice(0,e).replace(/0+$/,"");return r>0n&&r<10n**BigInt(18-e)?`${a}<0.${"0".repeat(e-1)}1`:`${a}${r/10n**18n}${i?`.${i}`:""}`}function E(n){return`${n.slice(0,6)}\u2026${n.slice(-4)}`}function l(n){return String(n).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}var K=`
|
|
2
2
|
:host{all:initial;font-family:var(--markee-font-family);color:var(--markee-text);font-size:14px;line-height:1.5;color-scheme:var(--markee-color-scheme)}
|
|
3
3
|
|
|
4
4
|
*{box-sizing:border-box}
|
|
@@ -56,7 +56,6 @@ form{display:grid;gap:16px}
|
|
|
56
56
|
.divider{height:1px;background:var(--markee-border);margin:20px 0}
|
|
57
57
|
a{color:var(--markee-link);text-decoration:none;overflow-wrap:anywhere}
|
|
58
58
|
ul{padding-left:20px;font-size:14px}
|
|
59
|
-
.review li{margin-bottom:9px;overflow-wrap:anywhere}
|
|
60
59
|
.loading{padding:40px;text-align:center;color:var(--markee-muted)}
|
|
61
60
|
.empty{padding:24px 8px;text-align:center}
|
|
62
61
|
.spinner{display:inline-block;width:14px;height:14px;border-radius:100%;border:2px solid var(--markee-border);border-top-color:var(--markee-muted);animation:spin 1s linear infinite;margin-right:8px}
|
|
@@ -64,7 +63,26 @@ ul{padding-left:20px;font-size:14px}
|
|
|
64
63
|
}
|
|
65
64
|
footer{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border);background:var(--markee-background);color:var(--markee-muted);font-size:11px}
|
|
66
65
|
.mono{font-family:ui-monospace,monospace}
|
|
67
|
-
.
|
|
66
|
+
.payment-review{display:grid;gap:16px}
|
|
67
|
+
.review-message{border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-input-background);padding:16px 18px;min-width:0}
|
|
68
|
+
.review-message .message{font-size:14px;margin:0}
|
|
69
|
+
.review-summary{padding:0 4px}
|
|
70
|
+
.review-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px solid var(--markee-border);font-size:13px}
|
|
71
|
+
.review-row:last-child{border-bottom:0}
|
|
72
|
+
.review-row>span{color:var(--markee-muted)}
|
|
73
|
+
.review-row strong{text-align:right;font-family:ui-monospace,monospace;font-size:13px;overflow-wrap:anywhere}
|
|
74
|
+
.review-callout{padding:16px;border:1px solid var(--markee-accent-border);border-radius:var(--markee-control-radius);background:var(--markee-accent-surface);color:var(--markee-accent-surface-text)}
|
|
75
|
+
.review-callout strong{display:block;font-family:ui-monospace,monospace;font-size:13px;line-height:1.45}
|
|
76
|
+
.review-callout p{margin:6px 0 0;font-size:12px;line-height:1.5}
|
|
77
|
+
.review-details{font-size:11px;color:var(--markee-muted)}
|
|
78
|
+
.review-details summary{cursor:pointer;color:var(--markee-link);font-size:12px}
|
|
79
|
+
.review-details .review-row{font-size:11px;padding:7px 0}
|
|
80
|
+
.review-details .review-row strong{font-size:11px;color:var(--markee-text)}
|
|
81
|
+
.review-address{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0}
|
|
82
|
+
.review-copy{padding:3px 7px;font-size:10px;line-height:1.3;color:var(--markee-link);white-space:nowrap}
|
|
83
|
+
.review-details p{margin:8px 0}
|
|
84
|
+
.review-footer .footer-actions{justify-content:flex-end}
|
|
85
|
+
.review-footer .footer-actions>.primary:last-child{margin-left:0}
|
|
68
86
|
.wallets{display:grid;gap:10px}
|
|
69
87
|
|
|
70
88
|
|
|
@@ -88,6 +106,7 @@ footer{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border)
|
|
|
88
106
|
.funding-card>label{font-size:11px;color:var(--markee-muted);font-weight:500;margin-bottom:8px}.amount-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.amount-value{display:flex;gap:6px;align-items:baseline;min-width:0;flex:1 1 140px}.amount-value input{background:transparent;border:0;border-radius:2px;box-shadow:none;font-family:ui-monospace,monospace;font-size:23px;font-weight:600;min-width:0;width:100%;padding:3px 0;color:var(--markee-text)}.amount-value>span{font-size:11px;color:var(--markee-muted);white-space:nowrap}.amount-presets{display:flex;gap:6px;margin-left:auto}.amount-presets button{color:var(--markee-link)}.amount-presets button[aria-pressed=true]{border-color:var(--markee-link);background:var(--markee-selected);color:var(--markee-selected-text)}
|
|
89
107
|
.funding-caption{display:flex;justify-content:space-between;flex-wrap:wrap;gap:4px 10px;margin-top:9px;color:var(--markee-muted);font-size:10px}.funding-tools{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;border-top:1px solid var(--markee-border);margin-top:13px;padding-top:12px}.funding-tools .meta{font-size:10px}.funding-hint{font-size:11px;margin:0}.funding-hint+.note{margin:0;font-size:11px}
|
|
90
108
|
.footer-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.footer-actions>.primary:last-child{margin-left:auto}.footer-actions:empty{display:none}.footer-meta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px;margin-top:10px;font-size:10px}.footer-meta .text-button{font-size:10px}
|
|
109
|
+
.payment-choice-footer .footer-actions{justify-content:flex-end}.payment-choice-footer .footer-actions>.primary:last-child{margin-left:0}
|
|
91
110
|
|
|
92
111
|
@media(max-width:560px){.overlay{padding:8px;align-items:flex-end}
|
|
93
112
|
.panel{border-radius:var(--markee-radius) var(--markee-radius) var(--markee-control-radius) var(--markee-control-radius);max-height:94dvh}
|
|
@@ -99,9 +118,25 @@ header{padding:20px 18px}
|
|
|
99
118
|
footer{padding:12px 18px}
|
|
100
119
|
.btn{padding:10px 12px}
|
|
101
120
|
.compact{padding:5px 9px}.text-button{padding:0}.footer-actions>.btn{flex:1;white-space:normal}.footer-actions>.primary:last-child{margin-left:0}
|
|
121
|
+
.review-footer .footer-actions>.btn{flex:0 1 auto}
|
|
122
|
+
.payment-choice-footer .footer-actions>.btn{flex:0 1 auto}
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
@media(prefers-reduced-motion:reduce){*{animation:none!important;scroll-behavior:auto!important}
|
|
105
126
|
}
|
|
106
127
|
|
|
107
|
-
`;var F={background:"#fbfcff",surface:"#ffffff",text:"#181b21",muted:"#687080",border:"#dce1ea",inputBackground:"#ffffff",inputText:"#202737",primary:"#282e3e",primaryText:"#ffffff",accent:"#c9f1a7",accentText:"#2b3c20",accentSurface:"#f1f7ea",accentSurfaceText:"#4e6535",accentBorder:"#cde3b5",selected:"#e9edf7",selectedText:"#242c47",info:"#edf1f9",infoText:"#52617b",error:"#fff0f0",errorText:"#9c3540",success:"#edf7e6",successText:"#40602f",link:"#4762a5",focusRing:"#5871c8",overlay:"#17203888"},D={background:"#151923",surface:"#202633",text:"#f0f3f8",muted:"#a6b1c3",border:"#434f63",inputBackground:"#10151e",inputText:"#f0f3f8",primary:"#dde6fa",primaryText:"#182238",accent:"#c9f1a7",accentText:"#24361a",accentSurface:"#243221",accentSurfaceText:"#c4e5ad",accentBorder:"#526b40",selected:"#313d53",selectedText:"#edf3ff",info:"#243149",infoText:"#bdcff1",error:"#44262e",errorText:"#ffbdc5",success:"#233b2b",successText:"#b5e4bf",link:"#adc5ff",focusRing:"#a1b4ff",overlay:"#030711b8"},q='Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',W=n=>`--markee-${n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`;function R(n,e){let t,a=(i={})=>{t?.(),t=void 0;let r=i.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)"):void 0,s=()=>{let d=i.mode==="dark"||r?.matches?"dark":"light",c=d==="dark"?D:F;n.dataset.markeeTheme=d,n.style.setProperty("--markee-color-scheme",d);for(let u of Object.keys(c)){let w=i.colors?.[u];n.style.setProperty(W(u),w&&CSS.supports("color",w)?w:c[u])}n.style.setProperty("--markee-font-family",i.fontFamily&&CSS.supports("font-family",i.fontFamily)?i.fontFamily:q);let f=typeof i.radius=="number"&&Number.isFinite(i.radius)?Math.max(0,Math.min(48,i.radius)):22;n.style.setProperty("--markee-radius",`${f}px`),n.style.setProperty("--markee-card-radius",`${f*.64}px`),n.style.setProperty("--markee-control-radius",`${f*.45}px`),n.style.setProperty("--markee-small-radius",`${f*.32}px`)};s(),r&&(r.addEventListener("change",s),t=()=>r.removeEventListener("change",s))};return a(e),{set:a,destroy(){t?.(),t=void 0}}}var g=2628000n,k=10n**15n,C=(...n)=>n.reduce((e,t)=>e>t?e:t,0n);function S(n,e){let t=n.strategy==="rent",a=t?(BigInt(n.minimum)+k-1n)/k*k:e?1n:BigInt(n.minimum),i=n.entries.filter(u=>u.address.toLowerCase()!==e?.address.toLowerCase()),r=C(...i.map(u=>BigInt(u.score))),s=!!e&&e.address.toLowerCase()===n.top?.toLowerCase();if(!t){let u=BigInt(e?.totalFunds??"0");return{minimum:a,boost:C(a,r+k-u,s?u:0n),double:s&&u>0n}}let c=!!e&&n.wallet?.backedMarkee?.toLowerCase()===e.address.toLowerCase()?BigInt(n.wallet.flowRate):0n,f=C(BigInt(e?.aggregateRate??"0")-c);return{minimum:a,boost:C(a,(r-f)*g+k,s?c*g*2n:0n),double:s&&c>0n}}var A=n=>{let e=BigInt(n);return`${e/10n**18n}.${(e%10n**18n).toString().padStart(18,"0")}`.replace(/\.?0+$/,"")||"0"},o=(n,e,t="",a="")=>`<button type="button" class="btn ${t}" data-cmd="${n}" ${a}>${e}</button>`,L=(n,e)=>/^https:\/\//.test(n)?`<a href="${l(n)}" target="_blank" rel="noopener noreferrer">${l(e)} \u2197</a>`:"",z=class{constructor(e,t){this.client=e;this.options=t;if(typeof document>"u")throw new Error("Open the Markee modal in a browser.");this.previousFocus=document.activeElement,this.previousOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.host=document.createElement("div"),this.host.setAttribute("data-markee-modal",""),this.root=this.host.attachShadow({mode:"open"}),this.theme=R(this.host,t.theme??e.options.theme),document.body.appendChild(this.host),this.root.addEventListener("click",this.onClick),this.root.addEventListener("submit",this.onSubmit),this.root.addEventListener("keydown",this.onKey),this.root.addEventListener("input",()=>{this.captureDraft(),this.updateFields()}),this.render(),this.root.querySelector('[data-cmd="close"]')?.focus(),this.reload(),this.watchAccount()}host;root;theme;snapshot;account=null;tab="main";leaderboardOpen=!1;initialSelection=!1;renderedView="";form;review;authorization;adminResult;adminProcessing=!1;result;pending;wallets;busy=!1;error="";closed=!1;epoch=0;timer;accountTimer;watched;previousFocus;previousOverflow;abort=new AbortController;drafts=new Map;viewObserver;viewed=new Set;walletChanged=()=>{this.initialSelection=!1,this.review=void 0,this.authorization=void 0,this.form=void 0,this.result=void 0,this.error="Wallet changed. Refreshing this placement\u2026",this.reload()};close(){this.closed||(this.closed=!0,this.abort.abort(),clearTimeout(this.timer),clearTimeout(this.accountTimer),this.viewObserver?.disconnect(),this.theme.destroy(),this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.host.remove(),document.body.style.overflow=this.previousOverflow,this.previousFocus?.focus(),this.options.onClose?.())}setTheme(e){this.closed||this.theme.set(e)}async watchAccount(){try{let e=await this.client.provider();e!==this.watched&&(this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.watched=e||void 0,e?.on?.("accountsChanged",this.walletChanged),e?.on?.("chainChanged",this.walletChanged)),(await this.client.account())?.toLowerCase()!==this.account?.toLowerCase()&&!this.busy&&this.walletChanged()}catch{}this.closed||(this.accountTimer=setTimeout(()=>void this.watchAccount(),2e3))}async reload(e){let t=++this.epoch;try{let a=await this.client.account(),i=await this.client.snapshot(this.options.placement,a,e,this.abort.signal);if(this.closed||t!==this.epoch)return;if(this.account=a,this.snapshot=i,this.error="",this.form&&(this.form.entry=i.entries.find(s=>s.address.toLowerCase()===this.form.entry.address.toLowerCase())??this.form.entry),!this.initialSelection&&a){this.initialSelection=!0;let s=i.entries.find(d=>d.address.toLowerCase()===i.wallet?.backedMarkee?.toLowerCase())??i.entries.find(d=>d.owner.toLowerCase()===a.toLowerCase());s&&!this.form&&!this.drafts.get("create")?.message&&(this.form={kind:i.strategy==="rent"?"stream":"fund",entry:s})}this.options.placement.kind==="gardens-community"&&(this.adminResult=this.client.communityReceipt(this.options.placement)||void 0),this.pending=a?this.client.pending(this.options.placement,a):void 0;let r=this.client.pendingAuthorization();this.adminProcessing=!!r&&this.options.placement.kind==="gardens-community"&&r.account.toLowerCase()===a?.toLowerCase()&&r.community.toLowerCase()===this.options.placement.community.toLowerCase()&&r.chainId===this.options.placement.chainId,this.render(),this.pending&&this.poll()}catch(a){!this.closed&&t===this.epoch&&this.fail(a)}}fail(e){this.error=e instanceof Error?e.message:String(e),this.render()}async task(e){if(!this.busy){this.busy=!0,this.error="",this.render();try{await e()}catch(t){this.fail(t)}finally{this.busy=!1,this.render()}}}async connect(){if(!this.client.options.wallet){let e=await P();if(e.length>1){this.wallets=e,this.render();return}}this.host.style.visibility="hidden";try{await this.client.connect()}finally{this.host.style.visibility=""}await this.reload()}async prepare(e){if(this.pending)throw new Error("Check your pending transaction before preparing another action.");if(!this.account){await this.connect();return}this.review=await this.client.prepare(this.options.placement,e),this.authorization=void 0}async poll(){if(clearTimeout(this.timer),!(!this.pending||this.closed)){try{let e=this.pending,t=await this.client.verify(e);if(this.closed||this.pending?.hash!==e.hash)return;if(t.status!=="pending"){if(this.pending=void 0,this.result=t,this.error="",await this.reload(),t.createdMarkee&&this.snapshot?.strategy==="rent"){let a=this.snapshot.entries.find(r=>r.address.toLowerCase()===t.createdMarkee.toLowerCase()),i=e.preparation.action;if(i.kind==="create"){this.form={kind:"stream",entry:a||{address:t.createdMarkee,owner:e.preparation.transaction.from,message:i.message,name:i.name,score:"0",totalFunds:"0",aggregateRate:"0",legacyFloor:"0",moderated:!1,views:0}};let r=this.drafts.get("create")?.amount;r&&this.drafts.set(this.draftKey(),{amount:r})}}this.render();return}}catch(e){this.closed||this.fail(e)}!this.closed&&this.pending&&(this.timer=setTimeout(()=>void this.poll(),5e3))}}async applyAdmin(e){if(this.authorization=void 0,this.adminProcessing=e.status==="working"||e.status==="submitted",e.status==="complete"&&(this.adminResult=e.result,await this.reload()),e.status==="failed")throw new Error(e.error||"Community action failed.")}onClick=e=>{let t=e.target.closest("[data-cmd]");if(!t)return;let a=t.dataset.cmd;if(a==="close"){this.close();return}if(!this.busy){if(this.captureDraft(),a==="leaderboard"){this.leaderboardOpen=!this.leaderboardOpen,this.render();return}if(a==="create"){this.tab="main",this.form=void 0,this.review=void 0,this.render();return}if(a.startsWith("tab:")){this.tab=a.slice(4),this.review=void 0,this.authorization=void 0,this.render();return}if(a==="back"){this.review||this.authorization||this.wallets?(this.review=void 0,this.authorization=void 0,this.wallets=void 0):this.tab!=="main"?this.tab="main":this.form?.kind.startsWith("edit")?this.form={kind:this.snapshot.strategy==="rent"?"stream":"fund",entry:this.form.entry}:this.form=void 0,this.render();return}if(a.startsWith("preset:")&&this.snapshot){let i=this.root.querySelector("#amount");if(i){let r=S(this.snapshot,this.form?.entry);i.value=A((a==="preset:min"?r.minimum:r.boost).toString()),this.captureDraft(),this.updateFields()}return}if(a.startsWith("form:")){let[,i,r]=a.split(":"),s=this.snapshot?.entries.find(d=>d.address===r);s&&(this.form={kind:i,entry:s},this.tab="main"),this.render();return}this.task(async()=>{if(a==="connect")await this.connect();else if(a.startsWith("wallet:"))await this.client.connect(this.wallets[Number(a.slice(7))].provider),this.wallets=void 0,await this.reload();else if(a==="refresh")await this.reload();else if(a==="more")await this.reload(this.snapshot?.nextOffset??void 0);else if(a==="send"&&this.review){let i=this.review,r=await this.client.send(i);this.pending={preparation:i,hash:r},this.review=void 0,this.form=void 0,this.result=void 0,this.poll()}else if(a==="check")await this.poll();else if(["stop","withdraw-buffer","settle"].includes(a))await this.prepare({kind:a});else if(a.startsWith("claim-refund:")||a.startsWith("connect-refund:")||a.startsWith("claim-top:")){let[i,r]=a.split(":");await this.prepare({kind:i,markee:r})}else if(a==="activate"||a==="claim"){let i=this.options.placement;if(i.kind!=="gardens-community"||!this.account)return;let r=this.account;this.authorization={kind:a,account:r,value:await this.client.authorize(i,a)},this.review=void 0}else if(a==="sign"&&this.authorization){let i=this.authorization;try{await this.applyAdmin(await this.client.executeAuthorization(i.kind,i.value,i.account))}finally{this.client.pendingAuthorization()&&(this.authorization=void 0,this.adminProcessing=!0)}}else if(a==="admin-check")await this.applyAdmin(await this.client.resumeAuthorization());else if(a==="bridge"&&this.adminResult){let i=await this.client.bridgeStatus(this.adminResult.bridgeProtocol||"none",this.adminResult.transactionHash,this.snapshot.chainId,this.options.placement.chainId);this.error=`Treasury transfer status: ${i.status.replace(/_/g," ")}.`}})}};onSubmit=e=>{if(e.preventDefault(),this.busy)return;this.captureDraft();let t=e.target,a=new FormData(t),i=r=>String(a.get(r)||"");this.task(async()=>{if(t.dataset.form==="create")this.snapshot?.strategy==="rent"&&v(i("amount")),await this.prepare({kind:"create",message:i("message"),name:i("name"),...this.snapshot?.strategy==="sale"?{amount:v(i("amount"),!0)}:{}});else if(t.dataset.form==="balance")await this.prepare({kind:i("kind"),amount:v(i("amount"))});else if(this.form){let{kind:r,entry:s}=this.form;r==="fund"?await this.prepare({kind:r,markee:s.address,amount:v(i("amount"))}):r==="stream"?await this.prepare({kind:r,markee:s.address,monthlyAmount:v(i("amount"))}):r==="edit-message"?await this.prepare({kind:r,markee:s.address,message:i("message")}):await this.prepare({kind:r,markee:s.address,name:i("name")})}})};draftKey(){return this.tab!=="main"?this.tab:this.form?`${this.form.kind}:${this.form.entry.address}`:"create"}captureDraft(){let e=this.root.querySelector("form");e&&this.drafts.set(this.draftKey(),Object.fromEntries([...new FormData(e)].map(([t,a])=>[t,String(a)])))}onKey=e=>{let t=e;if(t.key==="Escape"&&(t.preventDefault(),this.close()),t.key!=="Tab"||this.host.style.visibility==="hidden")return;let a=[...this.root.querySelectorAll("button:not(:disabled),a[href],input,textarea,select")],i=a[0],r=a[a.length-1];t.shiftKey&&this.root.activeElement===i?(t.preventDefault(),r?.focus()):!t.shiftKey&&this.root.activeElement===r&&(t.preventDefault(),i?.focus())};field(e,t,a="",i="",r=!1){let s=e==="message"?this.snapshot?.maxMessageBytes:e==="name"?this.snapshot?.maxNameBytes:void 0,d=`${e==="name"?"":"required"} ${s===void 0?"":`data-byte-limit="${s}"`} aria-describedby="${e}-hint"`;return`<div class="field"><label for="${e}">${t}${s===void 0?"":`<span class="field-count" aria-hidden="true" data-count-for="${e}"></span>`}</label>${r?`<textarea id="${e}" name="${e}" ${d} placeholder="Your message on the sign">${l(a)}</textarea>`:`<input id="${e}" name="${e}" ${e==="amount"?'inputmode="decimal"':""} value="${l(a)}" ${d}>`}${i?`<small id="${e}-hint">${i}</small>`:""}</div>`}reviewHtml(){let e=this.review,t=e.action,a=t.kind==="create"||t.kind==="edit-message"?t.message:this.form?this.entryMessage(this.form.entry):void 0,i=e.review.lines.filter(r=>!r.startsWith("Message: "));return`<h2 class="review-title">${l(e.review.title)}</h2>${a?`<section class="message-card"><p class="message">${l(a)}</p></section>`:""}<section class="review"><ul>${i.map(r=>`<li>${l(r)}</li>`).join("")}</ul><div class="stat"><span>Estimated network fee</span><strong>${m(e.review.estimatedGasCost)} ETH</strong></div><div class="stat"><span>Wallet</span><strong class="mono">${E(e.transaction.from)}</strong></div></section><p class="note">${l(e.review.reward)}</p><p class="meta">This review expires in 5 minutes. Your wallet shows the final network fee.</p>`}authorizationHtml(){let e=this.authorization,t=e.value.typedData.message;return`<div class="eyebrow">Community authorization</div><h2>${e.kind==="activate"?"Activate this community\u2019s Markee":"Claim community revenue"}</h2><p>A signed authorization lets Markee\u2019s keeper execute this action. The server rechecks your current council role before submitting it.</p><div class="card stack">${["registryCommunity","recipient","leaderboardFactory"].filter(a=>t[a]).map(a=>`<div class="meta">${l(a)}<br><strong class="mono">${l(t[a])}</strong></div>`).join("")}${["claimAmount","gasCost","maxFeeAmount"].filter(a=>t[a]!==void 0).map(a=>`<div class="stat"><span>${a==="claimAmount"?"Revenue":a==="gasCost"?"Keeper network fee":"Maximum bridge fee"}</span><strong>${m(String(t[a]))} ETH</strong></div>`).join("")}</div><p class="note">${e.kind==="claim"?"Revenue is sent to the community council treasury. Bridged claims remain pending until destination delivery is confirmed.":"This creates the community board and its revenue vault on the Markee chain."}</p>`}entryMessage(e){return e.moderated===!1?e.message:e.moderated?"This message is hidden by moderation.":"Message unavailable while moderation loads."}entriesHtml(){let e=this.snapshot,t=[...e.entries].sort((r,s)=>BigInt(r.score)>BigInt(s.score)?-1:BigInt(r.score)<BigInt(s.score)?1:0),a=[...t.filter(r=>r.owner.toLowerCase()===this.account?.toLowerCase()),...t.filter(r=>r.owner.toLowerCase()!==this.account?.toLowerCase())],i=e.board&&[8453,11155111].includes(e.chainId)?`https://${e.chainId===8453?"www":"2staging"}.markee.xyz/markee/${e.board}`:"";return`<section class="leaderboard" aria-label="Markee leaderboard"><div class="row between">${o("leaderboard",`<span class="chevron" aria-hidden="true">${this.leaderboardOpen?"\u2303":"\u2304"}</span> Leaderboard`,"text-button",`aria-expanded="${this.leaderboardOpen}" aria-controls="markee-leaderboard"`)}${L(i,"Open in Markee")}</div>${this.leaderboardOpen?`<div class="leaderboard-list" id="markee-leaderboard">${a.map(r=>{let s=r.owner.toLowerCase()===this.account?.toLowerCase(),d=r.address.toLowerCase()===e.top?.toLowerCase(),c=r.address.toLowerCase()===this.form?.entry.address.toLowerCase();return`<article class="leaderboard-entry ${d?"winner":""} ${c?"selected-entry":""}"><div class="grow"><p class="message">${l(this.entryMessage(r))}</p><div class="row entry-caption">${d?'<span class="pill">Winner</span>':""}${s?'<span class="meta">Yours</span>':""}${r.moderated===!1&&r.name?`<span class="name">${l(r.name)}</span>`:""}</div></div><div class="entry-funding"><div class="meta mono">${e.strategy==="rent"?`${m((BigInt(r.score)*g).toString())} ETH/mo`:`${m(r.totalFunds)} ETH`}</div><span class="meta">${r.views===null?"Views unavailable":`${r.views.toLocaleString()} views`}</span>${o(`form:${e.strategy==="sale"?"fund":"stream"}:${r.address}`,c?"Selected":"Fund",`compact ${c?"primary":""}`,`aria-pressed="${c}" aria-label="${c?"Selected":"Fund"} message ${E(r.address)}"`)}</div></article>`}).join("")||'<p class="empty">No Markees yet. Create the first one.</p>'}${e.strategy==="rent"&&e.rankedTop&&e.rankedTop.toLowerCase()!==e.top?.toLowerCase()?`<p class="note">The ranking has changed. ${o(`claim-top:${e.rankedTop}`,"Refresh winner","compact")}</p>`:""}${e.nextOffset!==null?o("more","Browse more messages","full"):""}</div>`:""}</section>`}selectedMessageHtml(e){let t=this.snapshot,a=t.wallet,i=e.owner.toLowerCase()===this.account?.toLowerCase(),r=t.entries.find(c=>c.owner.toLowerCase()===this.account?.toLowerCase()),s=e.address.toLowerCase()===t.top?.toLowerCase(),d=e.address.toLowerCase()===a?.backedMarkee?.toLowerCase()&&BigInt(a?.flowRate??"0")>0n;return`<section class="message-card ${s?"winner":""}"><div class="row between"><span class="eyebrow">${i?"Your Markee":"Markee you\u2019re funding"}</span>${s?'<span class="pill">Winner</span>':""}</div><p class="message">${l(this.entryMessage(e))}</p>${e.moderated===!1&&e.name?`<p class="name">${l(e.name)}</p>`:""}<div class="row message-tools">${i?o(`form:edit-message:${e.address}`,"Edit message","text-button")+o(`form:edit-name:${e.address}`,"Edit name","text-button"):""}${!i&&r?o(`form:${t.strategy==="rent"?"stream":"fund"}:${r.address}`,"Back to your Markee","text-button"):""}${o("create","Create your own Markee","text-button")}${t.strategy==="rent"&&this.account?o(`claim-refund:${e.address}`,"Collect refund","text-button"):""}</div><div class="message-stats">${t.strategy==="rent"?`<span class="meta">${d?s?"\u25CF Active stream":a?.poolConnected?"\u25CF Stream refunded while not the winner":"\u25CF Connect your refund pool in Deposit manager":"No active stream from your wallet to this message"}</span><div class="stats-grid"><div><span class="stat-label">Ranking rate</span><strong>${m((BigInt(e.score)*g).toString())} ETH/mo</strong></div><div><span class="stat-label">Your rate</span><strong>${m((d?BigInt(a.flowRate)*g:0n).toString())} ETH/mo</strong></div>${a?`<div><span class="stat-label">ETHx balance</span><strong>${m(a.ethx)} ETHx</strong></div><div><span class="stat-label">Funds remaining</span><strong title="Across all of your ETHx flows">${a.runwaySeconds===null?"No net outflow":`${(Number(a.runwaySeconds)/86400).toFixed(1)} days`}</strong></div>`:""}</div>${BigInt(e.legacyFloor)>0n?`<p class="meta">Ranking includes a decaying legacy floor of ${m((BigInt(e.legacyFloor)*g).toString())} ETH/mo.</p>`:""}`:`<div class="stats-grid"><div><span class="stat-label">Total funded</span><strong>${m(e.totalFunds)} ETH</strong></div><div><span class="stat-label">Views</span><strong>${e.views===null?"Unavailable":e.views.toLocaleString()}</strong></div></div>`}</div></section>`}fundingHtml(e){let t=this.snapshot,a=t.wallet,i=t.strategy==="rent",r=S(t,e),s=!!e&&e.address.toLowerCase()===a?.backedMarkee?.toLowerCase(),d=i&&s?BigInt(a.flowRate)*g:0n,c=BigInt(t.minimum)>r.minimum?BigInt(t.minimum):r.minimum,f=d>c?d:c,u=!i&&e?1n:BigInt(t.minimum);return`<section class="funding-card"><label for="amount">${i?"Monthly streaming rate":"Payment amount"}</label><div class="amount-row"><div class="amount-value"><input id="amount" name="amount" inputmode="decimal" value="${l(A(f.toString()))}" required aria-describedby="amount-hint"><span class="mono">${i?"ETHx/mo":"ETH"}</span></div><div class="amount-presets">${o("preset:min","MIN","compact mono",'title="Use the minimum amount"')}${o("preset:boost",r.double?"2\xD7":"WIN","compact mono",'title="Suggest an amount using the loaded ranking"')}</div></div><div class="funding-caption"><span id="amount-hint">Minimum ${A(u.toString())} ${i?"ETH/mo":"ETH"}</span><span>${a?`Balance ${m(a.eth)} ETH`:"Connect to see your balance"}</span></div><div class="funding-tools">${o("tab:wallet",i?"Deposit manager \u2192":"Wallet & rewards \u2192","text-button")}<span class="meta">${i?a?.runwaySeconds!=null?`${(Number(a.runwaySeconds)/86400).toFixed(1)} days remaining`:a?`${m(a.ethx)} ETHx available`:"ETH funds your ETHx balance":"One-time payment"}</span></div></section><p class="meta funding-hint">${i?"Unspent rent is refunded while your message is not the winner. You can stop streaming at any time.":e?"Adding funds keeps the current message owner.":"Your connected wallet will own this message."} Shortcuts use the loaded ranking; positions can change.</p>`}formHtml(){let e=this.snapshot,t=this.form;return t?.kind.startsWith("edit")?`<form id="markee-action" data-form="entry"><section class="message-card"><div class="eyebrow">Your Markee</div>${t.kind==="edit-message"?this.field("message","Markee message",t.entry.message,`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0):this.field("name","Your name (optional)",t.entry.name,`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section></form>`:`<form id="markee-action" data-form="${t?"entry":"create"}">${t?this.selectedMessageHtml(t.entry):`<section class="message-card editor-card">${this.field("message","Markee message","",`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0)}${this.field("name","Your name (optional)","",`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section>`}${this.fundingHtml(t?.entry)}${!t&&e.strategy==="rent"?'<p class="note">First create your message, then review and confirm its stream. Your chosen rate is kept for the next step.</p>':""}</form>`}updateFields(){for(let t of this.root.querySelectorAll("[data-byte-limit]")){let a=Number(t.dataset.byteLimit),i=new TextEncoder().encode(t.value).length;t.setCustomValidity(i>a?`Use at most ${a} UTF-8 bytes.`:"");let r=this.root.querySelector(`[data-count-for="${t.name}"]`);r&&(r.textContent=`${i}/${a}`)}let e=this.root.querySelector("#markee-action #amount");if(e&&this.snapshot){let t=S(this.snapshot,this.form?.entry),a;try{a=BigInt(v(e.value,this.snapshot.strategy==="sale"))}catch{}let i=this.snapshot.strategy==="sale"&&this.form?1n:BigInt(this.snapshot.minimum);e.setCustomValidity(a===void 0?"Enter a valid ETH amount.":a<i?`Use at least ${A(i.toString())} ETH${this.snapshot.strategy==="rent"?" per month":""}.`:""),this.root.querySelector('[data-cmd="preset:min"]')?.setAttribute("aria-pressed",String(a===t.minimum)),this.root.querySelector('[data-cmd="preset:boost"]')?.setAttribute("aria-pressed",String(a===t.boost))}}walletHtml(){let e=this.snapshot,t=e.wallet;if(!t)return'<p class="empty">Connect your wallet to see balances and manage your Markee.</p>'+o("connect","Connect app wallet","primary full");let a=`<h2>Your wallet</h2><p class="meta mono">${l(t.address)}</p><div class="grid"><div class="card"><span class="meta">Native ETH</span><div class="metric">${m(t.eth)}</div></div><div class="card"><span class="meta">MARKEE</span><div class="metric">${t.markee===null?"Unavailable":m(t.markee,2)}</div></div></div>`;return e.strategy==="sale"?a+'<p class="note">Payments reward the paying wallet when this board has RevNet enabled. Manage your messages from the leaderboard.</p>':(a+=`<div class="divider"></div><div class="card"><div class="stat"><span>Available ETHx</span><strong>${m(t.ethx)} ETHx</strong></div><div class="stat"><span>This board\u2019s monthly rate</span><strong>${m((BigInt(t.flowRate)*2628000n).toString())} ETH</strong></div><div class="stat"><span>Refund flow / month</span><strong>${m((BigInt(t.refundRate)*2628000n).toString())} ETHx</strong></div><div class="stat"><span>Runway across all ETHx flows</span><strong>${t.runwaySeconds===null?"No net outflow":`${(Number(t.runwaySeconds)/86400).toFixed(1)} days`}</strong></div><p class="meta">Snapshot at ${new Date(t.observedAt*1e3).toLocaleTimeString()}. Balances and rates can change.</p><div class="row">${BigInt(t.flowRate)>0n?o("stop","Stop stream","danger"):""}${t.backedMarkee&&!t.poolConnected?o(`connect-refund:${t.backedMarkee}`,"Connect refund pool","accent"):""}${o("refresh","Refresh balances")}</div></div><div class="divider"></div><h3>Manage ETHx</h3><form data-form="balance"><div class="grid"><div><label for="kind">Action</label><select id="kind" name="kind"><option value="wrap">Deposit ETH \u2192 ETHx</option><option value="unwrap">Withdraw ETHx \u2192 ETH</option></select></div>${this.field("amount","Amount","0.001")}</div><button type="submit" class="btn">Review balance change</button></form><div class="divider"></div><div class="card"><h3>Buffer and rewards</h3><div class="stat"><span>Refundable board buffer</span><strong>${m(t.withdrawableDeposit)} ETHx</strong></div><div class="stat"><span>Accrued rent to settle</span><strong>${m(t.pendingSettlement)} ETH</strong></div><p class="meta">Rewards come from actual rent spent, not the ETH deposited into your wallet.</p><div class="row">${BigInt(t.withdrawableDeposit)>0n?o("withdraw-buffer","Recover buffer"):""}${BigInt(t.pendingSettlement)>0n?o("settle",e.revnetEnabled?"Claim MARKEE":"Settle rent","primary"):""}${t.backedMarkee&&BigInt(t.poolClaimable)>0n?o(`claim-refund:${t.backedMarkee}`,"Collect pool refund"):""}</div></div>`,a)}communityHtml(){let e=this.snapshot.community;return e?`<h2>Community treasury</h2><p class="muted">Community council members can activate Markee and collect community revenue.</p><div class="card"><div class="stat"><span>Integration</span><strong>${e.integration.status==="active"?"Active":"Not activated"}</strong></div><div class="stat"><span>Available revenue</span><strong>${m(e.revenue.claimableAmount)} ETH</strong></div>${e.permissions?.councilSafe?`<p class="meta">Council treasury<br><span class="mono">${l(e.permissions.councilSafe)}</span></p>`:""}<div class="row">${this.adminProcessing?'<p class="note">A signed community action is processing. Check it before authorizing another.</p>'+o("admin-check","Check community action","primary"):this.account?e.integration.status!=="active"&&e.permissions?.canActivate?o("activate","Activate community Markee","primary"):e.permissions?.canClaim&&BigInt(e.revenue.claimableAmount)>0n?o("claim","Review revenue claim","primary"):'<span class="meta">No authorized action is currently available for this wallet.</span>':o("connect","Connect council wallet","primary")}</div></div>${this.adminResult?`<div class="success">Source transaction confirmed. ${L(this.adminResult.transactionUrl||"","View transaction")}${this.adminResult.bridged?"<p>Bridge delivery is tracked separately from the source transaction.</p>":""}${o("bridge","Check transfer status")}</div>`:""}`:""}title(){let e=this.snapshot;return this.wallets?"Connect your wallet":this.review?"Review payment":this.authorization?"Review authorization":this.pending?"Payment in progress":this.tab==="wallet"?e?.strategy==="rent"?"Deposit manager":"Wallet & rewards":this.tab==="community"||e&&!e.board?"Community treasury":this.form?.kind.startsWith("edit")?"Edit your Markee":this.form?this.form.entry.owner.toLowerCase()!==this.account?.toLowerCase()?"Fund a Markee":e?.strategy==="sale"?"Fund your Markee":BigInt(e?.wallet?.flowRate??"0")>0n?"Manage your Markee stream":"Stream to your Markee":"Change the Markee Sign"}footerHtml(){let e=this.snapshot,t="";if(this.wallets)t=o("back","Back");else if(this.review)t=o("back","Back")+o("send","Confirm in wallet","primary");else if(this.authorization)t=o("back","Back")+o("sign","Sign authorization","primary");else if(this.pending)t=o("check","Check transaction","primary");else if(e&&this.tab==="main"&&e.board){let a=this.form?.kind.startsWith("edit");t=(a?o("back","Cancel"):e.strategy==="rent"&&BigInt(e.wallet?.flowRate??"0")>0n?o("stop","Stop streaming","danger"):"")+(this.account?`<button class="btn primary" type="submit" form="markee-action">${a?"Review change":!this.form&&e.strategy==="rent"?"Review creation":"Review payment info"}</button>`:o("connect","Connect wallet","primary"))}else e&&(t=o("tab:main","Back to Markee"));return`<footer><div class="footer-actions">${t}</div><div class="footer-meta"><span>Powered by Markee${this.account?` \xB7 ${E(this.account)}`:""}</span>${e?.community&&e.board&&this.tab!=="community"&&!this.review&&!this.authorization&&!this.pending?o("tab:community","Community treasury","text-button"):""}</div></footer>`}render(){if(this.closed)return;let e=this.root.activeElement,t=e?.dataset.cmd,a=e?.id,i=this.wallets?"wallets":this.review?`review:${this.review.id}`:this.authorization?`authorization:${this.authorization.value.nonce}`:this.pending?`pending:${this.pending.hash}`:`${this.tab}:${this.form?.kind??"create"}:${this.form?.entry.address??""}`,r=i===this.renderedView?this.root.querySelector(".content")?.scrollTop??0:0;this.renderedView=i;let s=!document.activeElement||document.activeElement===document.body||document.activeElement===this.host,d=this.snapshot,c="";this.wallets?c=`<h2>Choose your wallet</h2><div class="wallets">${this.wallets.map((h,b)=>o(`wallet:${b}`,l(h.name))).join("")}</div>`:this.review?c=this.reviewHtml():this.authorization?c=this.authorizationHtml():d?this.pending?c=`<h2>Waiting for confirmation</h2><p>Your transaction was sent. You can close this modal and come back to check it.</p><p class="meta mono">${l(this.pending.hash)}</p><p class="note">Do not send a second payment while this transaction is pending.</p>`:!d.board||this.tab==="community"?c=this.communityHtml():this.tab==="wallet"?c=this.walletHtml():c=`${this.form?.kind.startsWith("edit")?"":this.entriesHtml()}${this.formHtml()}`:c=this.error?o("refresh","Retry","primary"):'<div class="loading"><span class="spinner"></span>Loading Markee\u2026</div>';let f=this.result?`<div class="${this.result.status==="reverted"||this.result.settlement==="deferred"?"error":"success"}">${this.result.status==="reverted"?"Transaction reverted. No action was completed.":this.result.settlement==="deferred"?"The transaction confirmed, but reward settlement was deferred. Your claim remains available.":`Transaction confirmed.${this.result.tokensReceived&&BigInt(this.result.tokensReceived)>0n?` ${m(this.result.tokensReceived,2)} MARKEE delivered to your wallet.`:""}`} ${L(this.result.explorerUrl,"View receipt")}</div>`:"";this.root.innerHTML=`<style>${H}</style><div class="overlay"><section class="panel" role="dialog" aria-modal="true" aria-labelledby="markee-title"><header><div class="grow"><h1 id="markee-title">${l(this.title())}</h1><p class="header-caption">${l(d?.name||"Markee")}${d?` \xB7 ${d.strategy==="rent"?"For rent":"For sale"}${d.chainId===8453?" \xB7 Base":d.chainId===11155111?" \xB7 Sepolia testnet":""}`:""}</p></div><button class="close" data-cmd="close" aria-label="Close Markee">\xD7</button></header><main class="content" aria-busy="${this.busy}"><div role="status" aria-live="polite">${this.busy?'<p class="meta"><span class="spinner"></span>Working\u2026</p>':""}${this.error?`<div class="error">${l(this.error)}</div>`:""}${f}</div>${d?.warnings.map(h=>`<div class="note">${l(h)}</div>`).join("")||""}${c}</main>${this.footerHtml()}</section></div>`,this.busy&&this.root.querySelectorAll('button:not([data-cmd="close"])').forEach(h=>{h.disabled=!0});let u=this.drafts.get(this.draftKey());if(u)for(let h of this.root.querySelectorAll("input,textarea,select"))u[h.name]!==void 0&&(h.value=u[h.name]);this.updateFields();let w=this.root.querySelector(".content");w&&(w.scrollTop=r),this.viewObserver?.disconnect();let I=this.root.querySelector(".winner"),y=d?.entries.find(h=>h.address.toLowerCase()===d.top?.toLowerCase()),M=y?`${y.address}:${y.message}`:"";I&&y?.moderated===!1&&!this.viewed.has(M)&&typeof IntersectionObserver<"u"&&(this.viewObserver=new IntersectionObserver(h=>{h.some(b=>b.isIntersecting)&&(this.viewObserver?.disconnect(),this.viewed.add(M),this.client.recordView(y.address,y.message,window.location.origin).catch(()=>{this.viewed.delete(M)}))},{threshold:.5}),this.viewObserver.observe(I)),s&&((a?this.root.getElementById(a):t?[...this.root.querySelectorAll("[data-cmd]")].find(b=>b.dataset.cmd===t):null)??this.root.querySelector('[data-cmd="close"]'))?.focus({preventScroll:!0})}};function B(n){let e=new T(n),t,a=n.theme;return{client:e,open(i){return t?.close(),t=new z(e,{...i,theme:i.theme??a}),t},setTheme(i){a=i??{},t?.setTheme(a)},close(){t?.close(),t=void 0}}}function ie(n){let e=N(n);e.current=n;let t=N(),a=JSON.stringify(n.placement);return O(()=>{if(!n.open)return;let i=B({apiUrl:n.apiUrl,fetch:n.fetch,theme:e.current.theme,wallet:n.wallet?{getProvider:()=>e.current.wallet.getProvider(),connect:()=>{let s=e.current.wallet?.connect;return s?s():Promise.reject(new Error("Connect the app wallet first."))}}:void 0,onEvent:s=>e.current.onEvent?.(s)});t.current=i;let r=!1;return i.open({placement:n.placement,onClose:()=>{r||e.current.onClose()}}),()=>{r=!0,i.close(),t.current=void 0}},[n.open,n.apiUrl,n.fetch,!!n.wallet,a]),O(()=>{t.current?.setTheme(n.theme)},[n.theme]),null}function re({children:n="Open Markee",onClick:e,...t}){return j("button",{...t,type:"button",onClick:e},n)}export{re as MarkeeButton,ie as MarkeeModal};
|
|
128
|
+
`;var Z={background:"#fbfcff",surface:"#ffffff",text:"#181b21",muted:"#687080",border:"#dce1ea",inputBackground:"#ffffff",inputText:"#202737",primary:"#282e3e",primaryText:"#ffffff",accent:"#c9f1a7",accentText:"#2b3c20",accentSurface:"#f1f7ea",accentSurfaceText:"#4e6535",accentBorder:"#cde3b5",selected:"#e9edf7",selectedText:"#242c47",info:"#edf1f9",infoText:"#52617b",error:"#fff0f0",errorText:"#9c3540",success:"#edf7e6",successText:"#40602f",link:"#4762a5",focusRing:"#5871c8",overlay:"#17203888"},ee={background:"#151923",surface:"#202633",text:"#f0f3f8",muted:"#a6b1c3",border:"#434f63",inputBackground:"#10151e",inputText:"#f0f3f8",primary:"#dde6fa",primaryText:"#182238",accent:"#c9f1a7",accentText:"#24361a",accentSurface:"#243221",accentSurfaceText:"#c4e5ad",accentBorder:"#526b40",selected:"#313d53",selectedText:"#edf3ff",info:"#243149",infoText:"#bdcff1",error:"#44262e",errorText:"#ffbdc5",success:"#233b2b",successText:"#b5e4bf",link:"#adc5ff",focusRing:"#a1b4ff",overlay:"#030711b8"},te='Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',ae=n=>`--markee-${n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`;function z(n,e){let t,a=(r={})=>{t?.(),t=void 0;let i=r.mode==="system"?window.matchMedia("(prefers-color-scheme: dark)"):void 0,s=()=>{let o=r.mode==="dark"||i?.matches?"dark":"light",c=o==="dark"?ee:Z;n.dataset.markeeTheme=o,n.style.setProperty("--markee-color-scheme",o);for(let u of Object.keys(c)){let w=r.colors?.[u];n.style.setProperty(ae(u),w&&CSS.supports("color",w)?w:c[u])}n.style.setProperty("--markee-font-family",r.fontFamily&&CSS.supports("font-family",r.fontFamily)?r.fontFamily:te);let f=typeof r.radius=="number"&&Number.isFinite(r.radius)?Math.max(0,Math.min(48,r.radius)):22;n.style.setProperty("--markee-radius",`${f}px`),n.style.setProperty("--markee-card-radius",`${f*.64}px`),n.style.setProperty("--markee-control-radius",`${f*.45}px`),n.style.setProperty("--markee-small-radius",`${f*.32}px`)};s(),i&&(i.addEventListener("change",s),t=()=>i.removeEventListener("change",s))};return a(e),{set:a,destroy(){t?.(),t=void 0}}}var $=2628000n,M=10n**15n,I=(...n)=>n.reduce((e,t)=>e>t?e:t,0n);function R(n,e){let t=n.strategy==="rent",a=t?(BigInt(n.minimum)+M-1n)/M*M:e?1n:BigInt(n.minimum),r=n.entries.filter(u=>u.address.toLowerCase()!==e?.address.toLowerCase()),i=I(...r.map(u=>BigInt(u.score))),s=!!e&&e.address.toLowerCase()===n.top?.toLowerCase();if(!t){let u=BigInt(e?.totalFunds??"0");return{minimum:a,boost:I(a,i+M-u,s?u:0n),double:s&&u>0n}}let c=!!e&&n.wallet?.backedMarkee?.toLowerCase()===e.address.toLowerCase()?BigInt(n.wallet.flowRate):0n,f=I(BigInt(e?.aggregateRate??"0")-c);return{minimum:a,boost:I(a,(i-f)*$+M,s?c*$*2n:0n),double:s&&c>0n}}var H=n=>{let e=BigInt(n);return`${e/10n**18n}.${(e%10n**18n).toString().padStart(18,"0")}`.replace(/\.?0+$/,"")||"0"},d=(n,e,t="",a="")=>`<button type="button" class="btn ${t}" data-cmd="${n}" ${a}>${e}</button>`,D=(n,e)=>/^https:\/\//.test(n)?`<a href="${l(n)}" target="_blank" rel="noopener noreferrer">${l(e)} \u2197</a>`:"",U=class{constructor(e,t){this.client=e;this.options=t;if(typeof document>"u")throw new Error("Open the Markee modal in a browser.");e.registerSite(t.placement),this.previousFocus=document.activeElement,this.previousOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.host=document.createElement("div"),this.host.setAttribute("data-markee-modal",""),this.root=this.host.attachShadow({mode:"open"}),this.theme=z(this.host,t.theme??e.options.theme),document.body.appendChild(this.host),this.root.addEventListener("click",this.onClick),this.root.addEventListener("submit",this.onSubmit),this.root.addEventListener("keydown",this.onKey),this.root.addEventListener("input",()=>{this.captureDraft(),this.updateFields()}),e.request("checkout/config").then(a=>{this.cardAvailable=a.enabled}).catch(()=>{}).finally(()=>{this.checkoutChecked=!0,this.render()}),this.render(),this.root.querySelector('[data-cmd="close"]')?.focus(),this.reload(),this.watchAccount()}host;root;theme;snapshot;cardAvailable=!1;checkoutChecked=!1;account=null;tab="main";leaderboardOpen=!1;initialSelection=!1;renderedView="";form;review;authorization;adminResult;adminProcessing=!1;result;pending;wallets;busy=!1;error="";closed=!1;epoch=0;timer;accountTimer;watched;previousFocus;previousOverflow;abort=new AbortController;drafts=new Map;viewObserver;viewed=new Set;walletChanged=()=>{this.initialSelection=!1,this.review=void 0,this.authorization=void 0,this.form=void 0,this.tab="main",this.result=void 0,this.error="Wallet changed. Refreshing this placement\u2026",this.reload()};close(){this.closed||(this.closed=!0,this.abort.abort(),clearTimeout(this.timer),clearTimeout(this.accountTimer),this.viewObserver?.disconnect(),this.theme.destroy(),this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.host.remove(),document.body.style.overflow=this.previousOverflow,this.previousFocus?.focus(),this.options.onClose?.())}setTheme(e){this.closed||this.theme.set(e)}async watchAccount(){try{let e=await this.client.provider();e!==this.watched&&(this.watched?.removeListener?.("accountsChanged",this.walletChanged),this.watched?.removeListener?.("chainChanged",this.walletChanged),this.watched=e||void 0,e?.on?.("accountsChanged",this.walletChanged),e?.on?.("chainChanged",this.walletChanged)),(await this.client.account())?.toLowerCase()!==this.account?.toLowerCase()&&!this.busy&&this.walletChanged()}catch{}this.closed||(this.accountTimer=setTimeout(()=>void this.watchAccount(),2e3))}async reload(e){let t=++this.epoch;try{let a=await this.client.account().catch(()=>null),r=await this.client.snapshot(this.options.placement,a,e,this.abort.signal);if(this.closed||t!==this.epoch)return;if(this.account=a,this.snapshot=r,this.error="",this.form&&(this.form.entry=r.entries.find(s=>s.address.toLowerCase()===this.form.entry.address.toLowerCase())??this.form.entry),!this.initialSelection&&a){this.initialSelection=!0;let s=r.entries.find(o=>o.address.toLowerCase()===r.wallet?.backedMarkee?.toLowerCase())??r.entries.find(o=>o.owner.toLowerCase()===a.toLowerCase());s&&!this.form&&!this.drafts.get("create")?.message&&(this.form={kind:r.strategy==="rent"?"stream":"fund",entry:s})}this.options.placement.kind==="gardens-community"&&(this.adminResult=this.client.communityReceipt(this.options.placement)||void 0),this.pending=a?this.client.pending(this.options.placement,a):void 0;let i=this.client.pendingAuthorization();this.adminProcessing=!!i&&this.options.placement.kind==="gardens-community"&&i.account.toLowerCase()===a?.toLowerCase()&&i.community.toLowerCase()===this.options.placement.community.toLowerCase()&&i.chainId===this.options.placement.chainId,this.render(),this.pending&&this.poll()}catch(a){!this.closed&&t===this.epoch&&this.fail(a)}}fail(e){this.error=e instanceof Error?e.message:String(e),this.render()}async task(e){if(!this.busy){this.busy=!0,this.error="",this.render();try{await e()}catch(t){this.fail(t)}finally{this.busy=!1,this.render()}}}async connect(){if(!this.client.options.wallet){let e=await q();if(e.length>1){this.wallets=e,this.render();return}}this.host.style.visibility="hidden";try{await this.client.connect()}finally{this.host.style.visibility=""}await this.reload()}async prepare(e){if(this.pending)throw new Error("Check your pending transaction before preparing another action.");if(!this.account){await this.connect();return}this.review=await this.client.prepare(this.options.placement,e),this.authorization=void 0}async poll(){if(clearTimeout(this.timer),!(!this.pending||this.closed)){try{let e=this.pending,t=await this.client.verify(e);if(this.closed||this.pending?.hash!==e.hash)return;if(t.status!=="pending"){if(this.pending=void 0,this.result=t,this.error="",await this.reload(),t.createdMarkee&&this.snapshot?.strategy==="rent"){let a=this.snapshot.entries.find(i=>i.address.toLowerCase()===t.createdMarkee.toLowerCase()),r=e.preparation.action;if(r.kind==="create"){this.form={kind:"stream",entry:a||{address:t.createdMarkee,owner:e.preparation.transaction.from,message:r.message,name:r.name,score:"0",totalFunds:"0",aggregateRate:"0",legacyFloor:"0",moderated:!1,views:0}};let i=this.drafts.get("create")?.amount;i&&this.drafts.set(this.draftKey(),{amount:i})}}this.render();return}}catch(e){this.closed||this.fail(e)}!this.closed&&this.pending&&(this.timer=setTimeout(()=>void this.poll(),5e3))}}async applyAdmin(e){if(this.authorization=void 0,this.adminProcessing=e.status==="working"||e.status==="submitted",e.status==="complete"&&(this.adminResult=e.result,await this.reload()),e.status==="failed")throw new Error(e.error||"Community action failed.")}onClick=e=>{let t=e.target.closest("[data-cmd]");if(!t)return;let a=t.dataset.cmd;if(a==="close"){this.close();return}if((a==="copy-recipient"||a==="copy-wallet")&&this.review){let r=a==="copy-recipient"?this.review.transaction.to:this.review.transaction.from,i=navigator.clipboard?.writeText(r);if(!i){t.textContent="Copy unavailable";return}i.then(()=>{t.textContent="Copied",setTimeout(()=>{t.isConnected&&(t.textContent="Copy")},2e3)}).catch(()=>{t.textContent="Copy failed"});return}if(!this.busy){if(this.captureDraft(),a==="leaderboard"){this.leaderboardOpen=!this.leaderboardOpen,this.render();return}if(a==="create"){this.tab="main",this.form=void 0,this.review=void 0,this.render();return}if(a.startsWith("tab:")){this.tab=a.slice(4),this.review=void 0,this.authorization=void 0,this.render();return}if(a==="back"){this.review||this.authorization||this.wallets?(this.review=void 0,this.authorization=void 0,this.wallets=void 0):this.tab!=="main"?this.tab="main":this.form?.kind.startsWith("edit")?this.form={kind:this.snapshot.strategy==="rent"?"stream":"fund",entry:this.form.entry}:this.form=void 0,this.render();return}if(a.startsWith("preset:")&&this.snapshot){let r=this.root.querySelector("#amount");if(r){let i=R(this.snapshot,this.form?.entry);r.value=H((a==="preset:min"?i.minimum:i.boost).toString()),this.captureDraft(),this.updateFields()}return}if(a.startsWith("form:")){let[,r,i]=a.split(":"),s=this.snapshot?.entries.find(o=>o.address===i);s&&(this.form={kind:r,entry:s},this.tab="main"),this.render();return}if(a==="card"&&this.hostedEligible()&&this.cardAvailable){this.captureDraft();let r=this.root.querySelector("#markee-action");if(!r||!r.reportValidity())return;let i=new FormData(r),s;try{let c=x(String(i.get("amount")||""));s=this.form?.kind==="fund"?{kind:"fund",markee:this.form.entry.address,amount:c}:{kind:"create",message:String(i.get("message")||""),name:String(i.get("name")||""),amount:c}}catch(c){this.error=c.message,this.render();return}let o=j(this.client,this.options.placement,s);this.task(async()=>{let c=await o;if(c.status!=="confirmed")throw new Error("Payment was not confirmed.");this.result=c,this.client.options.onEvent?.({type:"confirmed",hash:c.hash}),await this.reload()});return}this.task(async()=>{if(a==="connect")await this.connect();else if(a.startsWith("wallet:"))await this.client.connect(this.wallets[Number(a.slice(7))].provider),this.wallets=void 0,await this.reload();else if(a==="refresh")await this.reload();else if(a==="more")await this.reload(this.snapshot?.nextOffset??void 0);else if(a==="send"&&this.review){let r=this.review,i=await this.client.send(r);this.pending={preparation:r,hash:i},this.review=void 0,this.form=void 0,this.result=void 0,this.poll()}else if(a==="check")await this.poll();else if(["stop","withdraw-buffer","settle"].includes(a))await this.prepare({kind:a});else if(a.startsWith("claim-refund:")||a.startsWith("connect-refund:")||a.startsWith("claim-top:")){let[r,i]=a.split(":");await this.prepare({kind:r,markee:i})}else if(a==="activate"||a==="claim"){let r=this.options.placement;if(r.kind!=="gardens-community"||!this.account)return;let i=this.account;this.authorization={kind:a,account:i,value:await this.client.authorize(r,a)},this.review=void 0}else if(a==="sign"&&this.authorization){let r=this.authorization;try{await this.applyAdmin(await this.client.executeAuthorization(r.kind,r.value,r.account))}finally{this.client.pendingAuthorization()&&(this.authorization=void 0,this.adminProcessing=!0)}}else if(a==="admin-check")await this.applyAdmin(await this.client.resumeAuthorization());else if(a==="bridge"&&this.adminResult){let r=await this.client.bridgeStatus(this.adminResult.bridgeProtocol||"none",this.adminResult.transactionHash,this.snapshot.chainId,this.options.placement.chainId);this.error=`Treasury transfer status: ${r.status.replace(/_/g," ")}.`}})}};onSubmit=e=>{if(e.preventDefault(),this.busy)return;if(!this.account){this.root.querySelector('[data-cmd="card"]:not(:disabled)')?.click();return}this.captureDraft();let t=e.target,a=new FormData(t),r=i=>String(a.get(i)||"");this.task(async()=>{if(t.dataset.form==="create")this.snapshot?.strategy==="rent"&&x(r("amount")),await this.prepare({kind:"create",message:r("message"),name:r("name"),...this.snapshot?.strategy==="sale"?{amount:x(r("amount"),!0)}:{}});else if(t.dataset.form==="balance")await this.prepare({kind:r("kind"),amount:x(r("amount"))});else if(this.form){let{kind:i,entry:s}=this.form;i==="fund"?await this.prepare({kind:i,markee:s.address,amount:x(r("amount"))}):i==="stream"?await this.prepare({kind:i,markee:s.address,monthlyAmount:x(r("amount"))}):i==="edit-message"?await this.prepare({kind:i,markee:s.address,message:r("message")}):await this.prepare({kind:i,markee:s.address,name:r("name")})}})};draftKey(){return this.tab!=="main"?this.tab:this.form?`${this.form.kind}:${this.form.entry.address}`:"create"}captureDraft(){let e=this.root.querySelector("form");e&&this.drafts.set(this.draftKey(),Object.fromEntries([...new FormData(e)].map(([t,a])=>[t,String(a)])))}onKey=e=>{let t=e;if(t.key==="Escape"&&(t.preventDefault(),this.close()),t.key!=="Tab"||this.host.style.visibility==="hidden")return;let a=[...this.root.querySelectorAll("button:not(:disabled),a[href],input,textarea,select")],r=a[0],i=a[a.length-1];t.shiftKey&&this.root.activeElement===r?(t.preventDefault(),i?.focus()):!t.shiftKey&&this.root.activeElement===i&&(t.preventDefault(),r?.focus())};field(e,t,a="",r="",i=!1){let s=e==="message"?this.snapshot?.maxMessageBytes:e==="name"?this.snapshot?.maxNameBytes:void 0,o=`${e==="name"?"":"required"} ${s===void 0?"":`data-byte-limit="${s}"`} aria-describedby="${e}-hint"`;return`<div class="field"><label for="${e}">${t}${s===void 0?"":`<span class="field-count" aria-hidden="true" data-count-for="${e}"></span>`}</label>${i?`<textarea id="${e}" name="${e}" ${o} placeholder="Your message on the sign">${l(a)}</textarea>`:`<input id="${e}" name="${e}" ${e==="amount"?'inputmode="decimal"':""} value="${l(a)}" ${o}>`}${r?`<small id="${e}-hint">${r}</small>`:""}</div>`}reviewHtml(){let e=this.review,t=e.action,a="markee"in t?this.snapshot?.entries.find(h=>h.address.toLowerCase()===t.markee.toLowerCase()):void 0,r=t.kind==="create"||t.kind==="edit-message"?t.message:this.form?this.entryMessage(this.form.entry):a?this.entryMessage(a):void 0,i=BigInt(e.transaction.value),s=t.kind==="stream"?`${m(t.monthlyAmount)} ETHx/mo`:t.kind==="fund"||t.kind==="create"&&i>0n?`${m(i.toString())} ETH`:null,o=s!==null,c=o?[["Paying",s],[t.kind==="stream"&&i>0n?"Depositing now":"Estimated network fee",t.kind==="stream"&&i>0n?`${m(i.toString())} ETH`:`${m(e.review.estimatedGasCost)} ETH`],["You'll earn",e.review.estimatedTokens!==void 0?`${m(e.review.estimatedTokens,4)} MARKEE (estimated)`:this.snapshot?.revnetEnabled?t.kind==="stream"?"MARKEE while winning":"MARKEE to your wallet":"No MARKEE on this board"]]:[["Action",e.review.title],["Native ETH sent",`${m(i.toString())} ETH`],["Estimated network fee",`${m(e.review.estimatedGasCost)} ETH`]],f=e.review.lines.filter(h=>!/^(Message: |Name: |Native ETH sent: |Network: |Recipient: )/.test(h)),u=c.map(([h,y])=>`<div class="review-row"><span>${l(h)}</span><strong>${l(y)}</strong></div>`).join(""),w=t.kind==="stream"?"Your payment only streams while your message is winning":t.kind==="fund"?"Funding keeps the current message owner":t.kind==="create"&&o?"Your payment gives you this Markee message":"Review this wallet action",b=t.kind==="stream"?"Anyone can overtake your message. The refund pool offsets rent while you are not winning; you can stop the stream at any time.":e.review.reward;return`<div class="payment-review">${r?`<section class="review-message" aria-label="Markee message"><p class="message">${l(r)}</p></section>`:""}<section class="review-summary" aria-label="Payment summary">${u}</section><section class="review-callout"><strong>${l(w)}</strong><p>${l(b)}</p></section><details class="review-details"><summary>Transaction details</summary><div class="review-row"><span>Network</span><strong>${l(this.snapshot?.chainId===8453?"Base":this.snapshot?.chainId===11155111?"Sepolia testnet":String(e.transaction.chainId))}</strong></div><div class="review-row"><span>Recipient</span><div class="review-address"><strong class="mono" title="${l(e.transaction.to)}">${l(E(e.transaction.to))}</strong>${d("copy-recipient","Copy","review-copy",'aria-label="Copy recipient address"')}</div></div><div class="review-row"><span>Wallet</span><div class="review-address"><strong class="mono" title="${l(e.transaction.from)}">${l(E(e.transaction.from))}</strong>${d("copy-wallet","Copy","review-copy",'aria-label="Copy wallet address"')}</div></div>${t.kind==="stream"&&i>0n?`<div class="review-row"><span>Estimated network fee</span><strong>${m(e.review.estimatedGasCost)} ETH</strong></div>`:""}${f.map(h=>`<p>${l(h)}</p>`).join("")}${t.kind==="stream"?`<p>${l(e.review.reward)}</p>`:""}<p>This review expires in 5 minutes. Your wallet shows the final network fee.</p></details></div>`}authorizationHtml(){let e=this.authorization,t=e.value.typedData.message;return`<div class="eyebrow">Community authorization</div><h2>${e.kind==="activate"?"Activate this community\u2019s Markee":"Claim community revenue"}</h2><p>A signed authorization lets Markee\u2019s keeper execute this action. The server rechecks your current council role before submitting it.</p><div class="card stack">${["registryCommunity","recipient","leaderboardFactory"].filter(a=>t[a]).map(a=>`<div class="meta">${l(a)}<br><strong class="mono">${l(t[a])}</strong></div>`).join("")}${["claimAmount","gasCost","maxFeeAmount"].filter(a=>t[a]!==void 0).map(a=>`<div class="stat"><span>${a==="claimAmount"?"Revenue":a==="gasCost"?"Keeper network fee":"Maximum bridge fee"}</span><strong>${m(String(t[a]))} ETH</strong></div>`).join("")}</div><p class="note">${e.kind==="claim"?"Revenue is sent to the community council treasury. Bridged claims remain pending until destination delivery is confirmed.":"This creates the community board and its revenue vault on the Markee chain."}</p>`}entryMessage(e){return e.moderated===!1?e.message:e.moderated?"This message is hidden by moderation.":"Message unavailable while moderation loads."}entriesHtml(){let e=this.snapshot,t=[...e.entries].sort((i,s)=>BigInt(i.score)>BigInt(s.score)?-1:BigInt(i.score)<BigInt(s.score)?1:0),a=[...t.filter(i=>i.owner.toLowerCase()===this.account?.toLowerCase()),...t.filter(i=>i.owner.toLowerCase()!==this.account?.toLowerCase())],r=e.board&&[8453,11155111].includes(e.chainId)?`https://${e.chainId===8453?"www":"2staging"}.markee.xyz/markee/${e.board}`:"";return`<section class="leaderboard" aria-label="Markee leaderboard"><div class="row between">${d("leaderboard",`<span class="chevron" aria-hidden="true">${this.leaderboardOpen?"\u2303":"\u2304"}</span> Leaderboard`,"text-button",`aria-expanded="${this.leaderboardOpen}" aria-controls="markee-leaderboard"`)}${D(r,"Open in Markee")}</div>${this.leaderboardOpen?`<div class="leaderboard-list" id="markee-leaderboard">${a.map(i=>{let s=i.owner.toLowerCase()===this.account?.toLowerCase(),o=i.address.toLowerCase()===e.top?.toLowerCase(),c=i.address.toLowerCase()===this.form?.entry.address.toLowerCase();return`<article class="leaderboard-entry ${o?"winner":""} ${c?"selected-entry":""}"><div class="grow"><p class="message">${l(this.entryMessage(i))}</p><div class="row entry-caption">${o?'<span class="pill">Winner</span>':""}${s?'<span class="meta">Yours</span>':""}${i.moderated===!1&&i.name?`<span class="name">${l(i.name)}</span>`:""}</div></div><div class="entry-funding"><div class="meta mono">${e.strategy==="rent"?`${m((BigInt(i.score)*$).toString())} ETH/mo`:`${m(i.totalFunds)} ETH`}</div><span class="meta">${i.views===null?"Views unavailable":`${i.views.toLocaleString()} views`}</span>${d(`form:${e.strategy==="sale"?"fund":"stream"}:${i.address}`,c?"Selected":"Fund",`compact ${c?"primary":""}`,`aria-pressed="${c}" aria-label="${c?"Selected":"Fund"} message ${E(i.address)}"`)}</div></article>`}).join("")||'<p class="empty">No Markees yet. Create the first one.</p>'}${e.strategy==="rent"&&e.rankedTop&&e.rankedTop.toLowerCase()!==e.top?.toLowerCase()?`<p class="note">The ranking has changed. ${d(`claim-top:${e.rankedTop}`,"Refresh winner","compact")}</p>`:""}${e.nextOffset!==null?d("more","Browse more messages","full"):""}</div>`:""}</section>`}selectedMessageHtml(e){let t=this.snapshot,a=t.wallet,r=e.owner.toLowerCase()===this.account?.toLowerCase(),i=t.entries.find(c=>c.owner.toLowerCase()===this.account?.toLowerCase()),s=e.address.toLowerCase()===t.top?.toLowerCase(),o=e.address.toLowerCase()===a?.backedMarkee?.toLowerCase()&&BigInt(a?.flowRate??"0")>0n;return`<section class="message-card ${s?"winner":""}"><div class="row between"><span class="eyebrow">${r?"Your Markee":"Markee you\u2019re funding"}</span>${s?'<span class="pill">Winner</span>':""}</div><p class="message">${l(this.entryMessage(e))}</p>${e.moderated===!1&&e.name?`<p class="name">${l(e.name)}</p>`:""}<div class="row message-tools">${r?d(`form:edit-message:${e.address}`,"Edit message","text-button")+d(`form:edit-name:${e.address}`,"Edit name","text-button"):""}${!r&&i?d(`form:${t.strategy==="rent"?"stream":"fund"}:${i.address}`,"Back to your Markee","text-button"):""}${d("create","Create your own Markee","text-button")}${t.strategy==="rent"&&this.account?d(`claim-refund:${e.address}`,"Collect refund","text-button"):""}</div><div class="message-stats">${t.strategy==="rent"?`<span class="meta">${this.account?o?s?"\u25CF Active stream":a?.poolConnected?"\u25CF Stream refunded while not the winner":"\u25CF Connect your refund pool in Deposit manager":"No active stream from your wallet to this message":"Live message ranking"}</span><div class="stats-grid"><div><span class="stat-label">Ranking rate</span><strong>${m((BigInt(e.score)*$).toString())} ETH/mo</strong></div>${this.account?`<div><span class="stat-label">Your rate</span><strong>${m((o?BigInt(a.flowRate)*$:0n).toString())} ETH/mo</strong></div>`:""}${a?`<div><span class="stat-label">ETHx balance</span><strong>${m(a.ethx)} ETHx</strong></div><div><span class="stat-label">Funds remaining</span><strong title="Across all of your ETHx flows">${a.runwaySeconds===null?"No net outflow":`${(Number(a.runwaySeconds)/86400).toFixed(1)} days`}</strong></div>`:""}</div>${BigInt(e.legacyFloor)>0n?`<p class="meta">Ranking includes a decaying legacy floor of ${m((BigInt(e.legacyFloor)*$).toString())} ETH/mo.</p>`:""}`:`<div class="stats-grid"><div><span class="stat-label">Total funded</span><strong>${m(e.totalFunds)} ETH</strong></div><div><span class="stat-label">Views</span><strong>${e.views===null?"Unavailable":e.views.toLocaleString()}</strong></div></div>`}</div></section>`}fundingHtml(e){let t=this.snapshot,a=t.wallet,r=t.strategy==="rent",i=R(t,e),s=!!e&&e.address.toLowerCase()===a?.backedMarkee?.toLowerCase(),o=r&&s?BigInt(a.flowRate)*$:0n,c=BigInt(t.minimum)>i.minimum?BigInt(t.minimum):i.minimum,f=o>c?o:c,u=!r&&e?1n:BigInt(t.minimum);return`<section class="funding-card"><label for="amount">${r?"Monthly streaming rate":"Payment amount"}</label><div class="amount-row"><div class="amount-value"><input id="amount" name="amount" inputmode="decimal" value="${l(H(f.toString()))}" required aria-describedby="amount-hint"><span class="mono">${r?"ETHx/mo":"ETH"}</span></div><div class="amount-presets">${d("preset:min","MIN","compact mono",'title="Use the minimum amount"')}${d("preset:boost",i.double?"2\xD7":"WIN","compact mono",'title="Suggest an amount using the loaded ranking"')}</div></div><div class="funding-caption"><span id="amount-hint">Minimum ${H(u.toString())} ${r?"ETH/mo":"ETH"}</span>${this.account&&a?`<span>Balance ${m(a.eth)} ETH</span>`:""}</div><div class="funding-tools">${this.account?d("tab:wallet",r?"Deposit manager \u2192":"Wallet & rewards \u2192","text-button"):""}<span class="meta">${r?a?.runwaySeconds!=null?`${(Number(a.runwaySeconds)/86400).toFixed(1)} days remaining`:a?`${m(a.ethx)} ETHx available`:"ETH funds your ETHx balance":"One-time payment"}</span></div></section><p class="meta funding-hint">${r?"Unspent rent is refunded while your message is not the winner. You can stop streaming at any time.":e?"Adding funds keeps the current message owner.":"The paying wallet will own this message."} Shortcuts use the loaded ranking; positions can change.</p>`}formHtml(){let e=this.snapshot,t=this.form;return t?.kind.startsWith("edit")?`<form id="markee-action" data-form="entry"><section class="message-card"><div class="eyebrow">Your Markee</div>${t.kind==="edit-message"?this.field("message","Markee message",t.entry.message,`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0):this.field("name","Your name (optional)",t.entry.name,`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section></form>`:`<form id="markee-action" data-form="${t?"entry":"create"}">${t?this.selectedMessageHtml(t.entry):`<section class="message-card editor-card">${this.field("message","Markee message","",`${e.maxMessageBytes} UTF-8 bytes maximum.`,!0)}${this.field("name","Your name (optional)","",`${e.maxNameBytes} UTF-8 bytes maximum.`)}</section>`}${this.fundingHtml(t?.entry)}${!t&&e.strategy==="rent"?'<p class="note">First create your message, then review and confirm its stream. Your chosen rate is kept for the next step.</p>':""}</form>`}updateFields(){for(let t of this.root.querySelectorAll("[data-byte-limit]")){let a=Number(t.dataset.byteLimit),r=new TextEncoder().encode(t.value).length;t.setCustomValidity(r>a?`Use at most ${a} UTF-8 bytes.`:"");let i=this.root.querySelector(`[data-count-for="${t.name}"]`);i&&(i.textContent=`${r}/${a}`)}let e=this.root.querySelector("#markee-action #amount");if(e&&this.snapshot){let t=R(this.snapshot,this.form?.entry),a;try{a=BigInt(x(e.value,this.snapshot.strategy==="sale"))}catch{}let r=this.snapshot.strategy==="sale"&&this.form?1n:BigInt(this.snapshot.minimum);e.setCustomValidity(a===void 0?"Enter a valid ETH amount.":a<r?`Use at least ${H(r.toString())} ETH${this.snapshot.strategy==="rent"?" per month":""}.`:""),this.root.querySelector('[data-cmd="preset:min"]')?.setAttribute("aria-pressed",String(a===t.minimum)),this.root.querySelector('[data-cmd="preset:boost"]')?.setAttribute("aria-pressed",String(a===t.boost))}}walletHtml(){let e=this.snapshot,t=e.wallet;if(!t)return'<p class="empty">Connect your wallet to see balances and manage your Markee.</p>'+d("connect","Connect app wallet","primary full");let a=`<h2>Your wallet</h2><p class="meta mono">${l(t.address)}</p><div class="grid"><div class="card"><span class="meta">Native ETH</span><div class="metric">${m(t.eth)}</div></div><div class="card"><span class="meta">MARKEE</span><div class="metric">${t.markee===null?"Unavailable":m(t.markee,2)}</div></div></div>`;return e.strategy==="sale"?a+'<p class="note">Payments reward the paying wallet when this board has RevNet enabled. Manage your messages from the leaderboard.</p>':(a+=`<div class="divider"></div><div class="card"><div class="stat"><span>Available ETHx</span><strong>${m(t.ethx)} ETHx</strong></div><div class="stat"><span>This board\u2019s monthly rate</span><strong>${m((BigInt(t.flowRate)*2628000n).toString())} ETH</strong></div><div class="stat"><span>Refund flow / month</span><strong>${m((BigInt(t.refundRate)*2628000n).toString())} ETHx</strong></div><div class="stat"><span>Runway across all ETHx flows</span><strong>${t.runwaySeconds===null?"No net outflow":`${(Number(t.runwaySeconds)/86400).toFixed(1)} days`}</strong></div><p class="meta">Snapshot at ${new Date(t.observedAt*1e3).toLocaleTimeString()}. Balances and rates can change.</p><div class="row">${BigInt(t.flowRate)>0n?d("stop","Stop stream","danger"):""}${t.backedMarkee&&!t.poolConnected?d(`connect-refund:${t.backedMarkee}`,"Connect refund pool","accent"):""}${d("refresh","Refresh balances")}</div></div><div class="divider"></div><h3>Manage ETHx</h3><form data-form="balance"><div class="grid"><div><label for="kind">Action</label><select id="kind" name="kind"><option value="wrap">Deposit ETH \u2192 ETHx</option><option value="unwrap">Withdraw ETHx \u2192 ETH</option></select></div>${this.field("amount","Amount","0.001")}</div><button type="submit" class="btn">Review balance change</button></form><div class="divider"></div><div class="card"><h3>Buffer and rewards</h3><div class="stat"><span>Refundable board buffer</span><strong>${m(t.withdrawableDeposit)} ETHx</strong></div><div class="stat"><span>Accrued rent to settle</span><strong>${m(t.pendingSettlement)} ETH</strong></div><p class="meta">Rewards come from actual rent spent, not the ETH deposited into your wallet.</p><div class="row">${BigInt(t.withdrawableDeposit)>0n?d("withdraw-buffer","Recover buffer"):""}${BigInt(t.pendingSettlement)>0n?d("settle",e.revnetEnabled?"Claim MARKEE":"Settle rent","primary"):""}${t.backedMarkee&&BigInt(t.poolClaimable)>0n?d(`claim-refund:${t.backedMarkee}`,"Collect pool refund"):""}</div></div>`,a)}communityHtml(){let e=this.snapshot.community;return e?`<h2>Community treasury</h2><p class="muted">Community council members can activate Markee and collect community revenue.</p><div class="card"><div class="stat"><span>Integration</span><strong>${e.integration.status==="active"?"Active":"Not activated"}</strong></div><div class="stat"><span>Available revenue</span><strong>${m(e.revenue.claimableAmount)} ETH</strong></div>${e.permissions?.councilSafe?`<p class="meta">Council treasury<br><span class="mono">${l(e.permissions.councilSafe)}</span></p>`:""}<div class="row">${this.adminProcessing?'<p class="note">A signed community action is processing. Check it before authorizing another.</p>'+d("admin-check","Check community action","primary"):this.account?e.integration.status!=="active"&&e.permissions?.canActivate?d("activate","Activate community Markee","primary"):e.permissions?.canClaim&&BigInt(e.revenue.claimableAmount)>0n?d("claim","Review revenue claim","primary"):'<span class="meta">No authorized action is currently available for this wallet.</span>':d("connect","Connect council wallet","primary")}</div></div>${this.adminResult?`<div class="success">Source transaction confirmed. ${D(this.adminResult.transactionUrl||"","View transaction")}${this.adminResult.bridged?"<p>Bridge delivery is tracked separately from the source transaction.</p>":""}${d("bridge","Check transfer status")}</div>`:""}`:""}title(){let e=this.snapshot;return this.wallets?"Connect your wallet":this.review?this.review.action.kind==="create"&&BigInt(this.review.transaction.value)===0n?"Review creation":this.review.action.kind.startsWith("edit-")?"Review change":"Review payment":this.authorization?"Review authorization":this.pending?"Payment in progress":this.tab==="wallet"?e?.strategy==="rent"?"Deposit manager":"Wallet & rewards":this.tab==="community"||e&&!e.board?"Community treasury":this.form?.kind.startsWith("edit")?"Edit your Markee":this.form?this.form.entry.owner.toLowerCase()!==this.account?.toLowerCase()?"Fund a Markee":e?.strategy==="sale"?"Fund your Markee":BigInt(e?.wallet?.flowRate??"0")>0n?"Manage your Markee stream":"Stream to your Markee":"Change the Markee Sign"}hostedEligible(){let e=this.snapshot;return!!e&&e.strategy==="sale"&&e.chainId===8453&&e.placement.kind==="board"&&e.revnetEnabled&&!!e.token}footerHtml(){let e=this.snapshot,t="",a=!1;if(this.wallets)t=d("back","Back");else if(this.review)t=d("back","Back")+d("send",this.review.action.kind==="fund"||this.review.action.kind==="stream"||this.review.action.kind==="create"&&BigInt(this.review.transaction.value)>0n?"Confirm payment":"Confirm in wallet","primary");else if(this.authorization)t=d("back","Back")+d("sign","Sign authorization","primary");else if(this.pending)t=d("check","Check transaction","primary");else if(e&&this.tab==="main"&&e.board){let r=this.form?.kind.startsWith("edit"),i=r?d("back","Cancel"):e.strategy==="rent"&&BigInt(e.wallet?.flowRate??"0")>0n?d("stop","Stop streaming","danger"):"";this.account?(a=this.cardAvailable&&this.hostedEligible()&&!r,t=(a?d("card","Pay by card","primary"):"")+i+`<button class="btn primary" type="submit" form="markee-action">${r?"Review change":!this.form&&e.strategy==="rent"?"Review creation":"Review payment info"}</button>`):t=d("card","Pay","primary",!this.checkoutChecked||!this.cardAvailable||!this.hostedEligible()?"disabled":"")}else e&&(t=d("tab:main","Back to Markee"));return`<footer${this.review?' class="review-footer"':a?' class="payment-choice-footer"':""}><div class="footer-actions">${t}</div>${this.review?"":`<div class="footer-meta"><span>Powered by Markee${this.account?` \xB7 ${E(this.account)}`:""}</span>${this.account&&e?.community&&e.board&&this.tab!=="community"&&!this.authorization&&!this.pending?d("tab:community","Community treasury","text-button"):""}</div>`}</footer>`}render(){if(this.closed)return;let e=this.root.activeElement,t=e?.dataset.cmd,a=e?.id,r=this.wallets?"wallets":this.review?`review:${this.review.id}`:this.authorization?`authorization:${this.authorization.value.nonce}`:this.pending?`pending:${this.pending.hash}`:`${this.tab}:${this.form?.kind??"create"}:${this.form?.entry.address??""}`,i=r===this.renderedView?this.root.querySelector(".content")?.scrollTop??0:0;this.renderedView=r;let s=!document.activeElement||document.activeElement===document.body||document.activeElement===this.host,o=this.snapshot,c="";this.wallets?c=`<h2>Choose your wallet</h2><div class="wallets">${this.wallets.map((g,v)=>d(`wallet:${v}`,l(g.name))).join("")}</div>`:this.review?c=this.reviewHtml():this.authorization?c=this.authorizationHtml():o?this.pending?c=`<h2>Waiting for confirmation</h2><p>Your transaction was sent. You can close this modal and come back to check it.</p><p class="meta mono">${l(this.pending.hash)}</p><p class="note">Do not send a second payment while this transaction is pending.</p>`:!o.board||this.tab==="community"?c=this.communityHtml():this.tab==="wallet"?c=this.walletHtml():c=`${this.form?.kind.startsWith("edit")?"":this.entriesHtml()}${this.formHtml()}${this.account?"":`<p class="note">${this.checkoutChecked?this.hostedEligible()?this.cardAvailable?"Sign in and pay on Markee. Your payment wallet and rewards are managed there.":"Pay in Markee is temporarily unavailable. Please try again later.":"Pay in Markee is not supported for this board yet.":"Checking Markee checkout availability\u2026"}</p>`}`:c=this.error?d("refresh","Retry","primary"):'<div class="loading"><span class="spinner"></span>Loading Markee\u2026</div>';let f=this.result?`<div class="${this.result.status==="reverted"||this.result.settlement==="deferred"?"error":"success"}">${this.result.status==="reverted"?"Transaction reverted. No action was completed.":this.result.settlement==="deferred"?"The transaction confirmed, but reward settlement was deferred. Your claim remains available.":`Transaction confirmed.${this.result.tokensReceived&&BigInt(this.result.tokensReceived)>0n?` ${m(this.result.tokensReceived,2)} MARKEE delivered to your wallet.`:""}`} ${D(this.result.explorerUrl,"View receipt")}</div>`:"";this.root.innerHTML=`<style>${K}</style><div class="overlay"><section class="panel" role="dialog" aria-modal="true" aria-labelledby="markee-title"><header><div class="grow"><h1 id="markee-title">${l(this.title())}</h1><p class="header-caption">${l(o?.name||"Markee")}${o?` \xB7 ${o.strategy==="rent"?"For rent":"For sale"}${o.chainId===8453?" \xB7 Base":o.chainId===11155111?" \xB7 Sepolia testnet":""}`:""}</p></div><button class="close" data-cmd="close" aria-label="Close Markee">\xD7</button></header><main class="content" aria-busy="${this.busy}"><div role="status" aria-live="polite">${this.busy?'<p class="meta"><span class="spinner"></span>Working\u2026</p>':""}${this.error?`<div class="error">${l(this.error)}</div>`:""}${f}</div>${o?.warnings.map(g=>`<div class="note">${l(g)}</div>`).join("")||""}${c}</main>${this.footerHtml()}</section></div>`,this.busy&&this.root.querySelectorAll('button:not([data-cmd="close"])').forEach(g=>{g.disabled=!0});let u=this.drafts.get(this.draftKey());if(u)for(let g of this.root.querySelectorAll("input,textarea,select"))u[g.name]!==void 0&&(g.value=u[g.name]);this.updateFields();let w=this.root.querySelector(".content");w&&(w.scrollTop=i),this.viewObserver?.disconnect();let b=this.root.querySelector(".winner"),h=o?.entries.find(g=>g.address.toLowerCase()===o.top?.toLowerCase()),y=h?`${h.address}:${h.message}`:"";b&&h?.moderated===!1&&!this.viewed.has(y)&&typeof IntersectionObserver<"u"&&(this.viewObserver=new IntersectionObserver(g=>{g.some(v=>v.isIntersecting)&&(this.viewObserver?.disconnect(),this.viewed.add(y),this.client.recordView(h.address,h.message,window.location.origin).catch(()=>{this.viewed.delete(y)}))},{threshold:.5}),this.viewObserver.observe(b)),s&&((a?this.root.getElementById(a):t?[...this.root.querySelectorAll("[data-cmd]")].find(v=>v.dataset.cmd===t):null)??this.root.querySelector('[data-cmd="close"]'))?.focus({preventScroll:!0})}};function O(n={}){let e=new k(n),t,a=n.theme;return{client:e,open(r){return t?.close(),t=new U(e,{...r,theme:r.theme??a}),t},setTheme(r){a=r??{},t?.setTheme(a)},close(){t?.close(),t=void 0}}}function _(n){let e=n.entries.find(t=>t.address.toLowerCase()===n.top?.toLowerCase())??null;return{entry:e,visibility:!e||e.moderated===null?"unavailable":e.moderated?"flagged":"visible"}}var re=`
|
|
129
|
+
:host{display:block;color:var(--markee-text);font-family:var(--markee-font-family);color-scheme:var(--markee-color-scheme)}
|
|
130
|
+
*,*::before,*::after{box-sizing:border-box}
|
|
131
|
+
.sign{position:relative;overflow:hidden;border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:22px;min-height:190px}
|
|
132
|
+
.eyebrow{color:var(--markee-muted);font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
|
|
133
|
+
.board{margin:5px 0 20px;color:var(--markee-muted);font-size:13px}
|
|
134
|
+
.message{font-size:clamp(20px,4vw,30px);line-height:1.3;white-space:pre-wrap;overflow-wrap:anywhere;margin:0 0 16px}
|
|
135
|
+
.author{color:var(--markee-muted);font-size:13px;margin:0 0 16px}
|
|
136
|
+
.obscured{filter:blur(8px);user-select:none;pointer-events:none}
|
|
137
|
+
.veil{position:absolute;inset:55px 12px 62px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--markee-surface) 75%,transparent);color:var(--markee-muted);font-size:14px;text-align:center;padding:15px}
|
|
138
|
+
.notice{color:var(--markee-muted);font-size:14px;min-height:54px}
|
|
139
|
+
.action{appearance:none;border:0;border-radius:var(--markee-control-radius);background:var(--markee-primary);color:var(--markee-primary-text);font:inherit;font-weight:700;padding:11px 16px;cursor:pointer}
|
|
140
|
+
.action:focus-visible{outline:2px solid var(--markee-focus-ring);outline-offset:3px}
|
|
141
|
+
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}
|
|
142
|
+
`;function ie(n,e,t=!1){let a=n?.name||"Markee",r=n?n.strategy==="rent"?"For rent":"For sale":"",{entry:i,visibility:s}=n?_(n):{entry:null,visibility:"unavailable"},o=t?'<p class="notice" role="status">Markee sign is temporarily unavailable.</p>':n?i?s==="unavailable"?'<p class="notice" role="status">Message unavailable while moderation loads.</p>':`<div class="${s==="flagged"?"obscured":""}" ${s==="flagged"?'aria-hidden="true"':""}><p class="message">${l(i.message)}</p><p class="author">${l(i.name||E(i.owner))}</p></div>${s==="flagged"?'<div class="veil" role="status">This message has been flagged.</div>':""}`:'<p class="notice">The sign is waiting for its first message.</p>':'<p class="notice" role="status">Loading the Markee sign\u2026</p>';return`<style>${re}</style><section class="sign" aria-label="${l(a)} Markee sign"><div class="eyebrow">Current Markee sign</div><p class="board">${l(a)}${r?` \xB7 ${r}`:""}</p>${o}${e&&n?.board?'<button class="action" type="button" data-markee-open>Open Markee</button>':""}</section>`}function V(n,e){if(typeof document>"u")throw new Error("Mount the Markee sign in a browser.");let t=document.createElement("div");t.setAttribute("data-markee-sign","");let a=t.attachShadow({mode:"open"});n.appendChild(t);let r=z(t,e.theme),i=new k(e),s=O(e),o=Number.isFinite(e.refreshIntervalMs)?Math.max(1e4,e.refreshIntervalMs):3e4,c=!0,f,u,w,b=new Set,h=null,y=(v=!1)=>{if(w?.disconnect(),a.innerHTML=ie(h,e.showAction!==!1,v),v||!h||typeof IntersectionObserver>"u")return;let{entry:T,visibility:Y}=_(h);if(!T||Y!=="visible")return;let N=`${T.address}:${T.message}`;b.has(N)||(w=new IntersectionObserver(J=>{J.some(G=>G.isIntersecting)&&(w?.disconnect(),b.add(N),i.recordView(T.address,T.message,window.location.origin).catch(()=>{b.delete(N)}))},{threshold:.5}),w.observe(t))},g=async()=>{if(!c)return;clearTimeout(u),f?.abort();let v=new AbortController;f=v;try{let T=await i.snapshot(e.placement,null,void 0,v.signal);c&&f===v&&(h=T,y())}catch{c&&f===v&&!v.signal.aborted&&(h=null,y(!0))}finally{c&&f===v&&(u=setTimeout(()=>void g(),o))}};return a.addEventListener("click",v=>{v.target.closest("[data-markee-open]")&&s.open({placement:e.placement})}),y(),e.siteUrl&&i.registerSite(e.placement),g(),{refresh:g,setTheme:r.set,destroy(){c=!1,f?.abort(),clearTimeout(u),w?.disconnect(),s.close(),r.destroy(),t.remove()}}}function Me(n){let e=P(n);e.current=n;let t=P(),a=JSON.stringify(n.placement);return A(()=>{if(!n.siteUrl)return;new k({apiUrl:n.apiUrl,fetch:n.fetch,siteUrl:n.siteUrl,onSiteVerification:i=>e.current.onSiteVerification?.(i)}).registerSite(n.placement)},[n.siteUrl,n.apiUrl,n.fetch,a]),A(()=>{if(!n.open)return;let r=O({apiUrl:n.apiUrl,fetch:n.fetch,theme:e.current.theme,checkoutWindow:n.checkoutWindow,wallet:n.wallet?{getProvider:()=>e.current.wallet.getProvider(),connect:()=>{let s=e.current.wallet?.connect;return s?s():Promise.reject(new Error("Connect the app wallet first."))}}:void 0,onEvent:s=>e.current.onEvent?.(s)});t.current=r;let i=!1;return r.open({placement:n.placement,onClose:()=>{i||e.current.onClose()}}),()=>{i=!0,r.close(),t.current=void 0}},[n.open,n.apiUrl,n.fetch,n.checkoutWindow,!!n.wallet,a]),A(()=>{t.current?.setTheme(n.theme)},[n.theme]),n.placement.kind==="board"?B("span",{hidden:!0,"data-markee-address":n.placement.address}):null}function Ae({children:n="Open Markee",onClick:e,...t}){return B("button",{...t,type:"button",onClick:e},n)}function Pe(n){let e=P(null),t=P(n);t.current=n;let a=P(),r=JSON.stringify(n.placement);return A(()=>{if(!e.current)return;let i=V(e.current,{...t.current,wallet:t.current.wallet?{getProvider:()=>t.current.wallet.getProvider(),connect:()=>t.current.wallet?.connect?.()??Promise.reject(new Error("Connect the app wallet first."))}:void 0,onEvent:s=>t.current.onEvent?.(s),onSiteVerification:s=>t.current.onSiteVerification?.(s)});return a.current=i,()=>{i.destroy(),a.current=void 0}},[r,n.apiUrl,n.fetch,n.showAction,n.refreshIntervalMs,n.siteUrl,!!n.wallet]),A(()=>{a.current?.setTheme(n.theme)},[n.theme]),B("div",{ref:e,className:n.className},n.placement.kind==="board"?B("span",{hidden:!0,"data-markee-address":n.placement.address}):null)}export{Ae as MarkeeButton,Me as MarkeeModal,Pe as MarkeeSign};
|
package/dist/sign.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Entry, Placement, SDKOptions, Snapshot } from './types.js';
|
|
2
|
+
export interface MarkeeSignOptions extends SDKOptions {
|
|
3
|
+
placement: Placement;
|
|
4
|
+
/** Show a button that opens the SDK payment modal. Defaults to true. */
|
|
5
|
+
showAction?: boolean;
|
|
6
|
+
/** Refresh board and moderation state while mounted. Minimum 10 seconds; default 30 seconds. */
|
|
7
|
+
refreshIntervalMs?: number;
|
|
8
|
+
}
|
|
9
|
+
/** Board flags apply on integrations; Markee-only site flags deliberately do not. */
|
|
10
|
+
export declare function signContent(snapshot: Snapshot): {
|
|
11
|
+
entry: Entry | null;
|
|
12
|
+
visibility: 'visible' | 'flagged' | 'unavailable';
|
|
13
|
+
};
|
|
14
|
+
/** @internal Pure renderer kept separate so hidden-content behavior can be verified. */
|
|
15
|
+
export declare function signHtml(snapshot: Snapshot | null, showAction: boolean, unavailable?: boolean): string;
|
|
16
|
+
/** Mount a live, isolated sign in any app. The Markee API supplies its content and moderation status. */
|
|
17
|
+
export declare function createMarkeeSign(container: HTMLElement, options: MarkeeSignOptions): {
|
|
18
|
+
refresh: () => Promise<void>;
|
|
19
|
+
setTheme: (theme?: import("./types.js").MarkeeTheme) => void;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
};
|
package/dist/styles.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const styles = "\n:host{all:initial;font-family:var(--markee-font-family);color:var(--markee-text);font-size:14px;line-height:1.5;color-scheme:var(--markee-color-scheme)}\n\n*{box-sizing:border-box}\nbutton,input,textarea,select{font:inherit}\nbutton{cursor:pointer}\nbutton:disabled{opacity:.5;cursor:wait}\nbutton:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,a:focus-visible{outline:3px solid var(--markee-focus-ring);outline-offset:3px}\n\n.overlay{position:fixed;inset:0;z-index:10000;background:var(--markee-overlay);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;padding:24px}\n\n.panel{background:var(--markee-background);border:1px solid var(--markee-border);border-radius:var(--markee-radius);width:min(512px,100%);max-height:92dvh;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 24px 100px #10183244;position:relative}\n\nheader{flex-shrink:0;padding:18px 24px;display:flex;gap:16px;align-items:flex-start;border-bottom:1px solid var(--markee-border)}\n.brand{width:40px;height:40px;display:grid;place-items:center;border-radius:var(--markee-control-radius);background:var(--markee-primary);color:var(--markee-primary-text);font-weight:900;font-size:24px}\n.grow{flex:1;min-width:0}\nh1{font-size:18px;line-height:1.25;margin:0 0 4px}\nh2{font-size:18px;line-height:1.3;margin:0 0 12px}\nh3{font-size:16px;margin:0 0 8px}\np{margin:8px 0 14px}\n.muted,small{color:var(--markee-muted)}\n.eyebrow{font-size:11px;text-transform:uppercase;letter-spacing:1.3px;font-weight:700;color:var(--markee-accent-surface-text)}\n.pill{display:inline-flex;border-radius:var(--markee-small-radius);background:var(--markee-accent-surface);color:var(--markee-accent-surface-text);padding:3px 7px;font-size:11px;font-weight:700}\n.close{border:0;background:none;color:var(--markee-muted);font-size:23px;padding:5px 10px;border-radius:var(--markee-small-radius)}\n.nav{display:flex;gap:4px;padding:12px 24px 0;overflow:auto}\n.nav button{white-space:nowrap;border:0;background:transparent;padding:10px 12px;color:var(--markee-muted);border-radius:var(--markee-control-radius);font-size:13px}\n.nav button[aria-selected=true]{background:var(--markee-selected);color:var(--markee-selected-text);font-weight:650}\n.content{padding:20px 24px;overflow-y:auto;overflow-x:hidden;min-height:0;overscroll-behavior:contain}\n.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}\n.between{justify-content:space-between}\n.stack{display:grid;gap:12px}\n.btn{border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);background:var(--markee-surface);color:var(--markee-text);padding:10px 15px;font-weight:600;font-size:13px}\n.primary{background:var(--markee-primary);border-color:var(--markee-primary);color:var(--markee-primary-text)}\n.accent{background:var(--markee-accent);border-color:var(--markee-accent);color:var(--markee-accent-text)}\n.danger{color:var(--markee-error-text)}\n.full{width:100%}\n.card{border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:17px 18px}\n.winner{background:var(--markee-accent-surface);border-color:var(--markee-accent-border)}\n.message{font-family:ui-monospace,monospace;font-size:15px;overflow-wrap:anywhere;white-space:pre-wrap;line-height:1.5;margin:10px 0}\n.name{font-size:12px;color:var(--markee-muted)}\n.meta{font-size:12px;color:var(--markee-muted)}\n.stat{display:flex;justify-content:space-between;gap:16px;margin:8px 0;font-size:13px}\n.stat strong{text-align:right;overflow-wrap:anywhere}\n.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.metric{font-size:23px;font-weight:650;letter-spacing:-.6px}\n.note,.error,.success{padding:12px 14px;border-radius:var(--markee-control-radius);font-size:13px;overflow-wrap:anywhere;margin-bottom:14px}\n.note{background:var(--markee-info);color:var(--markee-info-text)}\n.error{background:var(--markee-error);color:var(--markee-error-text)}\n.success{background:var(--markee-success);color:var(--markee-success-text)}\nlabel{display:block;font-size:13px;font-weight:600;margin-bottom:6px}\ninput,textarea,select{display:block;width:100%;border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);background:var(--markee-input-background);color:var(--markee-input-text);padding:12px;min-width:0}\ninput::placeholder,textarea::placeholder{color:var(--markee-muted);opacity:1}\ntextarea{font-family:ui-monospace,monospace;font-size:14px;min-height:88px;max-height:220px;resize:vertical}\nform{display:grid;gap:16px}\n.field small{display:block;margin-top:5px;font-weight:400;font-size:12px}\n.divider{height:1px;background:var(--markee-border);margin:20px 0}\na{color:var(--markee-link);text-decoration:none;overflow-wrap:anywhere}\nul{padding-left:20px;font-size:14px}\n.review li{margin-bottom:9px;overflow-wrap:anywhere}\n.loading{padding:40px;text-align:center;color:var(--markee-muted)}\n.empty{padding:24px 8px;text-align:center}\n.spinner{display:inline-block;width:14px;height:14px;border-radius:100%;border:2px solid var(--markee-border);border-top-color:var(--markee-muted);animation:spin 1s linear infinite;margin-right:8px}\n@keyframes spin{to{transform:rotate(360deg)}\n}\nfooter{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border);background:var(--markee-background);color:var(--markee-muted);font-size:11px}\n.mono{font-family:ui-monospace,monospace}\n.review{margin:16px 0}.review ul{padding-left:18px}.review .stat{border-top:1px solid var(--markee-border);padding-top:10px}.review-title{font-size:14px;color:var(--markee-muted);font-weight:500}\n.wallets{display:grid;gap:10px}\n\n\n.header-caption{font-size:12px;color:var(--markee-muted);margin:5px 0 0}\n.close{line-height:1;padding:4px 6px;flex-shrink:0}\n.text-button{border:0;background:transparent;color:var(--markee-link);padding:0;font-size:12px;font-weight:500;text-align:left}\n.compact{padding:5px 9px;font-size:11px;line-height:1.4}\n.leaderboard{border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);padding:12px 14px;background:var(--markee-surface);margin-bottom:20px}\n.leaderboard>.row{gap:8px}.leaderboard a{font-size:11px}.leaderboard .text-button{color:var(--markee-muted)}.chevron{display:inline-block;width:15px;font-size:16px}\n.leaderboard-list{display:grid;gap:10px;margin-top:12px;padding-top:12px;border-top:1px solid var(--markee-border)}\n.leaderboard-entry{display:flex;gap:12px;align-items:center;justify-content:space-between;border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);padding:10px}\n.selected-entry{border-color:var(--markee-link)}.leaderboard-entry .message{font-size:12px;line-height:1.5;margin:0}.entry-caption{gap:5px;margin-top:5px}.entry-caption:empty{display:none}.entry-caption .pill{font-size:9px}.entry-caption .name,.entry-caption .meta{font-size:10px}\n.entry-funding{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:0 0 auto;max-width:44%;text-align:right;overflow-wrap:anywhere}.entry-funding .meta{font-size:10px}\n.message-card{padding:16px;border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);min-width:0}\n.message-card.winner{background:var(--markee-accent-surface);border-color:var(--markee-accent-border)}\n.message-card>.message{font-size:17px;margin:12px 0 6px}.message-card .eyebrow{font-size:10px}.message-card>.name{margin:4px 0}\n.message-tools{margin-top:12px;gap:10px 16px}.message-tools .text-button{font-size:11px}.editor-card{display:grid;gap:16px}\n.field label{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.field-count{font-size:10px;font-weight:400;color:var(--markee-muted)}.field small{font-size:10px}\n.message-stats{border-top:1px solid var(--markee-border);margin-top:16px;padding-top:12px}.message-stats>.meta{font-size:11px}.stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:8px}.stats-grid>div{min-width:0}.stats-grid strong{display:block;font-family:ui-monospace,monospace;font-size:12px;overflow-wrap:anywhere}.stat-label{display:block;font-size:9px;letter-spacing:.6px;text-transform:uppercase;color:var(--markee-muted);margin-bottom:4px}\n.funding-card{border:1px solid var(--markee-link);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:16px;min-width:0}\n.funding-card>label{font-size:11px;color:var(--markee-muted);font-weight:500;margin-bottom:8px}.amount-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.amount-value{display:flex;gap:6px;align-items:baseline;min-width:0;flex:1 1 140px}.amount-value input{background:transparent;border:0;border-radius:2px;box-shadow:none;font-family:ui-monospace,monospace;font-size:23px;font-weight:600;min-width:0;width:100%;padding:3px 0;color:var(--markee-text)}.amount-value>span{font-size:11px;color:var(--markee-muted);white-space:nowrap}.amount-presets{display:flex;gap:6px;margin-left:auto}.amount-presets button{color:var(--markee-link)}.amount-presets button[aria-pressed=true]{border-color:var(--markee-link);background:var(--markee-selected);color:var(--markee-selected-text)}\n.funding-caption{display:flex;justify-content:space-between;flex-wrap:wrap;gap:4px 10px;margin-top:9px;color:var(--markee-muted);font-size:10px}.funding-tools{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;border-top:1px solid var(--markee-border);margin-top:13px;padding-top:12px}.funding-tools .meta{font-size:10px}.funding-hint{font-size:11px;margin:0}.funding-hint+.note{margin:0;font-size:11px}\n.footer-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.footer-actions>.primary:last-child{margin-left:auto}.footer-actions:empty{display:none}.footer-meta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px;margin-top:10px;font-size:10px}.footer-meta .text-button{font-size:10px}\n\n@media(max-width:560px){.overlay{padding:8px;align-items:flex-end}\n.panel{border-radius:var(--markee-radius) var(--markee-radius) var(--markee-control-radius) var(--markee-control-radius);max-height:94dvh}\n.content{padding:20px 18px}\nheader{padding:20px 18px}\n.nav{padding-left:10px;padding-right:10px}\n.grid{grid-template-columns:1fr 1fr}\n.metric{font-size:19px}\nfooter{padding:12px 18px}\n.btn{padding:10px 12px}\n.compact{padding:5px 9px}.text-button{padding:0}.footer-actions>.btn{flex:1;white-space:normal}.footer-actions>.primary:last-child{margin-left:0}\n}\n\n@media(prefers-reduced-motion:reduce){*{animation:none!important;scroll-behavior:auto!important}\n}\n\n";
|
|
1
|
+
export declare const styles = "\n:host{all:initial;font-family:var(--markee-font-family);color:var(--markee-text);font-size:14px;line-height:1.5;color-scheme:var(--markee-color-scheme)}\n\n*{box-sizing:border-box}\nbutton,input,textarea,select{font:inherit}\nbutton{cursor:pointer}\nbutton:disabled{opacity:.5;cursor:wait}\nbutton:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,a:focus-visible{outline:3px solid var(--markee-focus-ring);outline-offset:3px}\n\n.overlay{position:fixed;inset:0;z-index:10000;background:var(--markee-overlay);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;padding:24px}\n\n.panel{background:var(--markee-background);border:1px solid var(--markee-border);border-radius:var(--markee-radius);width:min(512px,100%);max-height:92dvh;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 24px 100px #10183244;position:relative}\n\nheader{flex-shrink:0;padding:18px 24px;display:flex;gap:16px;align-items:flex-start;border-bottom:1px solid var(--markee-border)}\n.brand{width:40px;height:40px;display:grid;place-items:center;border-radius:var(--markee-control-radius);background:var(--markee-primary);color:var(--markee-primary-text);font-weight:900;font-size:24px}\n.grow{flex:1;min-width:0}\nh1{font-size:18px;line-height:1.25;margin:0 0 4px}\nh2{font-size:18px;line-height:1.3;margin:0 0 12px}\nh3{font-size:16px;margin:0 0 8px}\np{margin:8px 0 14px}\n.muted,small{color:var(--markee-muted)}\n.eyebrow{font-size:11px;text-transform:uppercase;letter-spacing:1.3px;font-weight:700;color:var(--markee-accent-surface-text)}\n.pill{display:inline-flex;border-radius:var(--markee-small-radius);background:var(--markee-accent-surface);color:var(--markee-accent-surface-text);padding:3px 7px;font-size:11px;font-weight:700}\n.close{border:0;background:none;color:var(--markee-muted);font-size:23px;padding:5px 10px;border-radius:var(--markee-small-radius)}\n.nav{display:flex;gap:4px;padding:12px 24px 0;overflow:auto}\n.nav button{white-space:nowrap;border:0;background:transparent;padding:10px 12px;color:var(--markee-muted);border-radius:var(--markee-control-radius);font-size:13px}\n.nav button[aria-selected=true]{background:var(--markee-selected);color:var(--markee-selected-text);font-weight:650}\n.content{padding:20px 24px;overflow-y:auto;overflow-x:hidden;min-height:0;overscroll-behavior:contain}\n.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}\n.between{justify-content:space-between}\n.stack{display:grid;gap:12px}\n.btn{border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);background:var(--markee-surface);color:var(--markee-text);padding:10px 15px;font-weight:600;font-size:13px}\n.primary{background:var(--markee-primary);border-color:var(--markee-primary);color:var(--markee-primary-text)}\n.accent{background:var(--markee-accent);border-color:var(--markee-accent);color:var(--markee-accent-text)}\n.danger{color:var(--markee-error-text)}\n.full{width:100%}\n.card{border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:17px 18px}\n.winner{background:var(--markee-accent-surface);border-color:var(--markee-accent-border)}\n.message{font-family:ui-monospace,monospace;font-size:15px;overflow-wrap:anywhere;white-space:pre-wrap;line-height:1.5;margin:10px 0}\n.name{font-size:12px;color:var(--markee-muted)}\n.meta{font-size:12px;color:var(--markee-muted)}\n.stat{display:flex;justify-content:space-between;gap:16px;margin:8px 0;font-size:13px}\n.stat strong{text-align:right;overflow-wrap:anywhere}\n.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.metric{font-size:23px;font-weight:650;letter-spacing:-.6px}\n.note,.error,.success{padding:12px 14px;border-radius:var(--markee-control-radius);font-size:13px;overflow-wrap:anywhere;margin-bottom:14px}\n.note{background:var(--markee-info);color:var(--markee-info-text)}\n.error{background:var(--markee-error);color:var(--markee-error-text)}\n.success{background:var(--markee-success);color:var(--markee-success-text)}\nlabel{display:block;font-size:13px;font-weight:600;margin-bottom:6px}\ninput,textarea,select{display:block;width:100%;border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);background:var(--markee-input-background);color:var(--markee-input-text);padding:12px;min-width:0}\ninput::placeholder,textarea::placeholder{color:var(--markee-muted);opacity:1}\ntextarea{font-family:ui-monospace,monospace;font-size:14px;min-height:88px;max-height:220px;resize:vertical}\nform{display:grid;gap:16px}\n.field small{display:block;margin-top:5px;font-weight:400;font-size:12px}\n.divider{height:1px;background:var(--markee-border);margin:20px 0}\na{color:var(--markee-link);text-decoration:none;overflow-wrap:anywhere}\nul{padding-left:20px;font-size:14px}\n.loading{padding:40px;text-align:center;color:var(--markee-muted)}\n.empty{padding:24px 8px;text-align:center}\n.spinner{display:inline-block;width:14px;height:14px;border-radius:100%;border:2px solid var(--markee-border);border-top-color:var(--markee-muted);animation:spin 1s linear infinite;margin-right:8px}\n@keyframes spin{to{transform:rotate(360deg)}\n}\nfooter{flex-shrink:0;padding:14px 20px;border-top:1px solid var(--markee-border);background:var(--markee-background);color:var(--markee-muted);font-size:11px}\n.mono{font-family:ui-monospace,monospace}\n.payment-review{display:grid;gap:16px}\n.review-message{border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-input-background);padding:16px 18px;min-width:0}\n.review-message .message{font-size:14px;margin:0}\n.review-summary{padding:0 4px}\n.review-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px solid var(--markee-border);font-size:13px}\n.review-row:last-child{border-bottom:0}\n.review-row>span{color:var(--markee-muted)}\n.review-row strong{text-align:right;font-family:ui-monospace,monospace;font-size:13px;overflow-wrap:anywhere}\n.review-callout{padding:16px;border:1px solid var(--markee-accent-border);border-radius:var(--markee-control-radius);background:var(--markee-accent-surface);color:var(--markee-accent-surface-text)}\n.review-callout strong{display:block;font-family:ui-monospace,monospace;font-size:13px;line-height:1.45}\n.review-callout p{margin:6px 0 0;font-size:12px;line-height:1.5}\n.review-details{font-size:11px;color:var(--markee-muted)}\n.review-details summary{cursor:pointer;color:var(--markee-link);font-size:12px}\n.review-details .review-row{font-size:11px;padding:7px 0}\n.review-details .review-row strong{font-size:11px;color:var(--markee-text)}\n.review-address{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0}\n.review-copy{padding:3px 7px;font-size:10px;line-height:1.3;color:var(--markee-link);white-space:nowrap}\n.review-details p{margin:8px 0}\n.review-footer .footer-actions{justify-content:flex-end}\n.review-footer .footer-actions>.primary:last-child{margin-left:0}\n.wallets{display:grid;gap:10px}\n\n\n.header-caption{font-size:12px;color:var(--markee-muted);margin:5px 0 0}\n.close{line-height:1;padding:4px 6px;flex-shrink:0}\n.text-button{border:0;background:transparent;color:var(--markee-link);padding:0;font-size:12px;font-weight:500;text-align:left}\n.compact{padding:5px 9px;font-size:11px;line-height:1.4}\n.leaderboard{border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);padding:12px 14px;background:var(--markee-surface);margin-bottom:20px}\n.leaderboard>.row{gap:8px}.leaderboard a{font-size:11px}.leaderboard .text-button{color:var(--markee-muted)}.chevron{display:inline-block;width:15px;font-size:16px}\n.leaderboard-list{display:grid;gap:10px;margin-top:12px;padding-top:12px;border-top:1px solid var(--markee-border)}\n.leaderboard-entry{display:flex;gap:12px;align-items:center;justify-content:space-between;border:1px solid var(--markee-border);border-radius:var(--markee-control-radius);padding:10px}\n.selected-entry{border-color:var(--markee-link)}.leaderboard-entry .message{font-size:12px;line-height:1.5;margin:0}.entry-caption{gap:5px;margin-top:5px}.entry-caption:empty{display:none}.entry-caption .pill{font-size:9px}.entry-caption .name,.entry-caption .meta{font-size:10px}\n.entry-funding{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:0 0 auto;max-width:44%;text-align:right;overflow-wrap:anywhere}.entry-funding .meta{font-size:10px}\n.message-card{padding:16px;border:1px solid var(--markee-border);border-radius:var(--markee-card-radius);background:var(--markee-surface);min-width:0}\n.message-card.winner{background:var(--markee-accent-surface);border-color:var(--markee-accent-border)}\n.message-card>.message{font-size:17px;margin:12px 0 6px}.message-card .eyebrow{font-size:10px}.message-card>.name{margin:4px 0}\n.message-tools{margin-top:12px;gap:10px 16px}.message-tools .text-button{font-size:11px}.editor-card{display:grid;gap:16px}\n.field label{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.field-count{font-size:10px;font-weight:400;color:var(--markee-muted)}.field small{font-size:10px}\n.message-stats{border-top:1px solid var(--markee-border);margin-top:16px;padding-top:12px}.message-stats>.meta{font-size:11px}.stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:8px}.stats-grid>div{min-width:0}.stats-grid strong{display:block;font-family:ui-monospace,monospace;font-size:12px;overflow-wrap:anywhere}.stat-label{display:block;font-size:9px;letter-spacing:.6px;text-transform:uppercase;color:var(--markee-muted);margin-bottom:4px}\n.funding-card{border:1px solid var(--markee-link);border-radius:var(--markee-card-radius);background:var(--markee-surface);padding:16px;min-width:0}\n.funding-card>label{font-size:11px;color:var(--markee-muted);font-weight:500;margin-bottom:8px}.amount-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.amount-value{display:flex;gap:6px;align-items:baseline;min-width:0;flex:1 1 140px}.amount-value input{background:transparent;border:0;border-radius:2px;box-shadow:none;font-family:ui-monospace,monospace;font-size:23px;font-weight:600;min-width:0;width:100%;padding:3px 0;color:var(--markee-text)}.amount-value>span{font-size:11px;color:var(--markee-muted);white-space:nowrap}.amount-presets{display:flex;gap:6px;margin-left:auto}.amount-presets button{color:var(--markee-link)}.amount-presets button[aria-pressed=true]{border-color:var(--markee-link);background:var(--markee-selected);color:var(--markee-selected-text)}\n.funding-caption{display:flex;justify-content:space-between;flex-wrap:wrap;gap:4px 10px;margin-top:9px;color:var(--markee-muted);font-size:10px}.funding-tools{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;border-top:1px solid var(--markee-border);margin-top:13px;padding-top:12px}.funding-tools .meta{font-size:10px}.funding-hint{font-size:11px;margin:0}.funding-hint+.note{margin:0;font-size:11px}\n.footer-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.footer-actions>.primary:last-child{margin-left:auto}.footer-actions:empty{display:none}.footer-meta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px;margin-top:10px;font-size:10px}.footer-meta .text-button{font-size:10px}\n.payment-choice-footer .footer-actions{justify-content:flex-end}.payment-choice-footer .footer-actions>.primary:last-child{margin-left:0}\n\n@media(max-width:560px){.overlay{padding:8px;align-items:flex-end}\n.panel{border-radius:var(--markee-radius) var(--markee-radius) var(--markee-control-radius) var(--markee-control-radius);max-height:94dvh}\n.content{padding:20px 18px}\nheader{padding:20px 18px}\n.nav{padding-left:10px;padding-right:10px}\n.grid{grid-template-columns:1fr 1fr}\n.metric{font-size:19px}\nfooter{padding:12px 18px}\n.btn{padding:10px 12px}\n.compact{padding:5px 9px}.text-button{padding:0}.footer-actions>.btn{flex:1;white-space:normal}.footer-actions>.primary:last-child{margin-left:0}\n.review-footer .footer-actions>.btn{flex:0 1 auto}\n.payment-choice-footer .footer-actions>.btn{flex:0 1 auto}\n}\n\n@media(prefers-reduced-motion:reduce){*{animation:none!important;scroll-behavior:auto!important}\n}\n\n";
|
package/dist/types.d.ts
CHANGED
|
@@ -141,6 +141,7 @@ export interface PreparedAction {
|
|
|
141
141
|
lines: string[];
|
|
142
142
|
estimatedGasCost: string;
|
|
143
143
|
reward: string;
|
|
144
|
+
estimatedTokens?: string;
|
|
144
145
|
};
|
|
145
146
|
}
|
|
146
147
|
export interface TransactionResult {
|
|
@@ -251,9 +252,14 @@ export interface MarkeeTheme {
|
|
|
251
252
|
radius?: number;
|
|
252
253
|
}
|
|
253
254
|
export interface SDKOptions {
|
|
254
|
-
|
|
255
|
+
/** Optional development override; defaults to the Markee-hosted API. */
|
|
256
|
+
checkoutWindow?: 'tab' | 'redirect';
|
|
257
|
+
apiUrl?: string;
|
|
255
258
|
wallet?: WalletAdapter;
|
|
256
259
|
fetch?: typeof fetch;
|
|
260
|
+
/** Public page/domain to verify for this board; omit to disable automatic registration. */
|
|
261
|
+
siteUrl?: string;
|
|
262
|
+
onSiteVerification?: (result: SiteVerification) => void;
|
|
257
263
|
theme?: MarkeeTheme;
|
|
258
264
|
onEvent?: (event: {
|
|
259
265
|
type: 'submitted' | 'confirmed' | 'error';
|
|
@@ -261,3 +267,23 @@ export interface SDKOptions {
|
|
|
261
267
|
message?: string;
|
|
262
268
|
}) => void;
|
|
263
269
|
}
|
|
270
|
+
export interface SiteVerification {
|
|
271
|
+
verified: boolean;
|
|
272
|
+
url: string;
|
|
273
|
+
verifiedUrls?: string[];
|
|
274
|
+
message?: string;
|
|
275
|
+
}
|
|
276
|
+
export interface CheckoutSession {
|
|
277
|
+
checkoutOrigin?: string;
|
|
278
|
+
id: string;
|
|
279
|
+
readToken: string;
|
|
280
|
+
writeToken: string;
|
|
281
|
+
expiresAt: number;
|
|
282
|
+
}
|
|
283
|
+
export interface CheckoutStatus {
|
|
284
|
+
id: string;
|
|
285
|
+
status: 'created' | 'ready' | 'signing' | 'submitted' | 'confirmed' | 'reverted';
|
|
286
|
+
account?: Address;
|
|
287
|
+
result?: TransactionResult;
|
|
288
|
+
expiresAt: number;
|
|
289
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markee_team/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.10",
|
|
4
4
|
"description": "Self-contained Markee modal and API client, with an optional React adapter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public",
|
|
58
|
-
"tag": "
|
|
58
|
+
"tag": "latest",
|
|
59
59
|
"registry": "https://registry.npmjs.org/"
|
|
60
60
|
},
|
|
61
61
|
"main": "./dist/index.js",
|