@1sat/permission-module-ui 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/OneSatPermissionPrompt.d.ts +1 -1
- package/dist/OneSatPermissionPrompt.d.ts.map +1 -1
- package/dist/index.js +589 -122
- package/dist/styles.d.ts +2 -2
- package/dist/styles.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -15,7 +15,7 @@ export interface OneSatPermissionPromptProps {
|
|
|
15
15
|
*
|
|
16
16
|
* The host wallet feeds in the `request` it received from its promptHandler
|
|
17
17
|
* callback and wires `onApprove`/`onReject` to resolve the same Promise.
|
|
18
|
-
* Layout mirrors
|
|
18
|
+
* Layout mirrors `docs/plans/mockups/p1sat-permissions.pen` — 1Sat coin
|
|
19
19
|
* badge, intent title, asset detail card, network/fee, approve/reject.
|
|
20
20
|
*/
|
|
21
21
|
export declare function OneSatPermissionPrompt({ request, onApprove, onReject, theme, }: OneSatPermissionPromptProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OneSatPermissionPrompt.d.ts","sourceRoot":"","sources":["../src/OneSatPermissionPrompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAU5D,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAE7C,MAAM,WAAW,2BAA2B;IAC3C,mEAAmE;IACnE,OAAO,EAAE,aAAa,CAAA;IACtB,yFAAyF;IACzF,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAA;CACb;
|
|
1
|
+
{"version":3,"file":"OneSatPermissionPrompt.d.ts","sourceRoot":"","sources":["../src/OneSatPermissionPrompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAU5D,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAE7C,MAAM,WAAW,2BAA2B;IAC3C,mEAAmE;IACnE,OAAO,EAAE,aAAa,CAAA;IACtB,yFAAyF;IACzF,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAA;CACb;AA8DD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACtC,OAAO,EACP,SAAS,EACT,QAAQ,EACR,KAAc,GACd,EAAE,2BAA2B,+BAyL7B"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,31 @@ var ORDINALS_BASKET = "p 1sat ordinals";
|
|
|
5
5
|
var BSV21_BASKET = "p 1sat bsv21";
|
|
6
6
|
var OPNS_BASKET = "p 1sat opns";
|
|
7
7
|
var LOCK_BASKET = "p 1sat lock";
|
|
8
|
+
var P1SAT_INTENTS = {
|
|
9
|
+
OPNS_REGISTER: "opns.register",
|
|
10
|
+
OPNS_DEREGISTER: "opns.deregister",
|
|
11
|
+
OPNS_LIST: "opns.list",
|
|
12
|
+
OPNS_TRANSFER: "opns.transfer",
|
|
13
|
+
OPNS_CANCEL_LISTING: "opns.cancel-listing",
|
|
14
|
+
OPNS_PURCHASE: "opns.purchase",
|
|
15
|
+
ORDINAL_TRANSFER: "ordinal.transfer",
|
|
16
|
+
ORDINAL_LIST: "ordinal.list",
|
|
17
|
+
ORDINAL_CANCEL_LISTING: "ordinal.cancel-listing",
|
|
18
|
+
ORDINAL_PURCHASE: "ordinal.purchase",
|
|
19
|
+
ORDINAL_BURN: "ordinal.burn",
|
|
20
|
+
ORDINAL_INSCRIBE: "ordinal.inscribe",
|
|
21
|
+
ORDINAL_INSCRIBE_SIGMA: "ordinal.inscribe-sigma",
|
|
22
|
+
ORDINAL_MINT_COLLECTION: "ordinal.mint-collection",
|
|
23
|
+
ORDINAL_MINT_ITEM: "ordinal.mint-item",
|
|
24
|
+
LOCK_LOCK: "lock.lock",
|
|
25
|
+
LOCK_UNLOCK: "lock.unlock",
|
|
26
|
+
BSV21_TRANSFER: "bsv21.transfer",
|
|
27
|
+
BSV21_PURCHASE: "bsv21.purchase",
|
|
28
|
+
BSV21_MINT: "bsv21.mint",
|
|
29
|
+
BSV21_DEPLOY: "bsv21.deploy"
|
|
30
|
+
};
|
|
31
|
+
var P1SAT_INTENT_IDS = new Set(Object.values(P1SAT_INTENTS));
|
|
32
|
+
var OPNS_REGISTER_LOCK_PLACEHOLDER_HEX = "00".repeat(142);
|
|
8
33
|
var MAX_INSCRIPTION_BYTES = 50 * 1024 * 1024;
|
|
9
34
|
var EXCHANGE_RATE_CACHE_TTL = 5 * 60 * 1000;
|
|
10
35
|
var DEFAULT_STREAM_CHUNK_SIZE = 1024 * 1024;
|
|
@@ -53,6 +78,12 @@ var promptStyles = `
|
|
|
53
78
|
--opp-reject-border: #d1d5db;
|
|
54
79
|
--opp-status-bg: #FFFBE6;
|
|
55
80
|
--opp-status-fg: #E5A920;
|
|
81
|
+
--opp-trust-ok-bg: #ECFDF5;
|
|
82
|
+
--opp-trust-ok-fg: #059669;
|
|
83
|
+
--opp-trust-warn-bg: #FFFBEB;
|
|
84
|
+
--opp-trust-warn-fg: #D97706;
|
|
85
|
+
--opp-trust-bad-bg: #FEF2F2;
|
|
86
|
+
--opp-trust-bad-fg: #DC2626;
|
|
56
87
|
|
|
57
88
|
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
58
89
|
background: var(--opp-bg);
|
|
@@ -84,6 +115,12 @@ var promptStyles = `
|
|
|
84
115
|
--opp-reject-border: #2D3142;
|
|
85
116
|
--opp-status-bg: #2A2408;
|
|
86
117
|
--opp-status-fg: #E5A920;
|
|
118
|
+
--opp-trust-ok-bg: #0A2E1F;
|
|
119
|
+
--opp-trust-ok-fg: #34D399;
|
|
120
|
+
--opp-trust-warn-bg: #2A2008;
|
|
121
|
+
--opp-trust-warn-fg: #FBBF24;
|
|
122
|
+
--opp-trust-bad-bg: #2A1215;
|
|
123
|
+
--opp-trust-bad-fg: #F87171;
|
|
87
124
|
}
|
|
88
125
|
|
|
89
126
|
.opp-body {
|
|
@@ -145,7 +182,7 @@ var promptStyles = `
|
|
|
145
182
|
background: var(--opp-card-bg);
|
|
146
183
|
border: 1px solid var(--opp-card-border);
|
|
147
184
|
border-radius: 10px;
|
|
148
|
-
margin: 0 20px;
|
|
185
|
+
margin: 0 20px 8px;
|
|
149
186
|
padding: 16px;
|
|
150
187
|
}
|
|
151
188
|
|
|
@@ -154,15 +191,30 @@ var promptStyles = `
|
|
|
154
191
|
height: 80px;
|
|
155
192
|
border-radius: 8px;
|
|
156
193
|
object-fit: cover;
|
|
157
|
-
background: rgba(0, 0, 0, 0.
|
|
194
|
+
background: rgba(0, 0, 0, 0.08);
|
|
158
195
|
flex-shrink: 0;
|
|
159
196
|
}
|
|
160
197
|
|
|
198
|
+
.opp-featured-image-token {
|
|
199
|
+
width: 48px;
|
|
200
|
+
height: 48px;
|
|
201
|
+
border-radius: 999px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.opp-featured-placeholder {
|
|
205
|
+
display: flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
justify-content: center;
|
|
208
|
+
color: var(--opp-muted);
|
|
209
|
+
font-size: 18px;
|
|
210
|
+
}
|
|
211
|
+
|
|
161
212
|
.opp-featured-meta {
|
|
162
213
|
display: flex;
|
|
163
214
|
flex-direction: column;
|
|
164
215
|
gap: 4px;
|
|
165
216
|
min-width: 0;
|
|
217
|
+
flex: 1;
|
|
166
218
|
}
|
|
167
219
|
|
|
168
220
|
.opp-featured-title {
|
|
@@ -176,9 +228,71 @@ var promptStyles = `
|
|
|
176
228
|
.opp-featured-subtitle {
|
|
177
229
|
font-size: 12px;
|
|
178
230
|
color: var(--opp-muted);
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
gap: 6px;
|
|
234
|
+
min-width: 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.opp-featured-subtitle-text {
|
|
179
238
|
white-space: nowrap;
|
|
180
239
|
overflow: hidden;
|
|
181
240
|
text-overflow: ellipsis;
|
|
241
|
+
min-width: 0;
|
|
242
|
+
font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, monospace;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.opp-trust-wrap {
|
|
246
|
+
display: flex;
|
|
247
|
+
flex-direction: column;
|
|
248
|
+
gap: 8px;
|
|
249
|
+
margin: 0 20px 8px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.opp-trust {
|
|
253
|
+
display: inline-flex;
|
|
254
|
+
align-self: flex-start;
|
|
255
|
+
padding: 3px 8px;
|
|
256
|
+
border-radius: 999px;
|
|
257
|
+
font-size: 10px;
|
|
258
|
+
font-weight: 600;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.opp-trust-verified {
|
|
262
|
+
background: var(--opp-trust-ok-bg);
|
|
263
|
+
color: var(--opp-trust-ok-fg);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.opp-trust-unverified {
|
|
267
|
+
background: var(--opp-trust-warn-bg);
|
|
268
|
+
color: var(--opp-trust-warn-fg);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.opp-trust-mismatch {
|
|
272
|
+
background: var(--opp-trust-bad-bg);
|
|
273
|
+
color: var(--opp-trust-bad-fg);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.opp-trust-note {
|
|
277
|
+
padding: 10px;
|
|
278
|
+
border-radius: 8px;
|
|
279
|
+
font-size: 11px;
|
|
280
|
+
line-height: 1.35;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.opp-trust-note-verified {
|
|
284
|
+
background: var(--opp-trust-ok-bg);
|
|
285
|
+
color: var(--opp-trust-ok-fg);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.opp-trust-note-unverified {
|
|
289
|
+
background: var(--opp-trust-warn-bg);
|
|
290
|
+
color: var(--opp-trust-warn-fg);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.opp-trust-note-mismatch {
|
|
294
|
+
background: var(--opp-trust-bad-bg);
|
|
295
|
+
color: var(--opp-trust-bad-fg);
|
|
182
296
|
}
|
|
183
297
|
|
|
184
298
|
.opp-row {
|
|
@@ -190,31 +304,54 @@ var promptStyles = `
|
|
|
190
304
|
|
|
191
305
|
.opp-row-key {
|
|
192
306
|
color: var(--opp-muted);
|
|
307
|
+
flex-shrink: 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.opp-row-value-wrap {
|
|
311
|
+
display: flex;
|
|
312
|
+
align-items: center;
|
|
313
|
+
gap: 6px;
|
|
314
|
+
min-width: 0;
|
|
315
|
+
max-width: 70%;
|
|
316
|
+
justify-content: flex-end;
|
|
193
317
|
}
|
|
194
318
|
|
|
195
319
|
.opp-row-value {
|
|
196
320
|
font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, monospace;
|
|
197
|
-
font-size:
|
|
321
|
+
font-size: 12px;
|
|
198
322
|
font-weight: 500;
|
|
199
323
|
text-align: right;
|
|
200
324
|
white-space: nowrap;
|
|
201
325
|
overflow: hidden;
|
|
202
326
|
text-overflow: ellipsis;
|
|
203
327
|
min-width: 0;
|
|
204
|
-
max-width: 60%;
|
|
205
328
|
}
|
|
206
329
|
|
|
207
|
-
.opp-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
330
|
+
.opp-copy {
|
|
331
|
+
flex-shrink: 0;
|
|
332
|
+
width: 22px;
|
|
333
|
+
height: 22px;
|
|
334
|
+
padding: 0;
|
|
335
|
+
display: inline-flex;
|
|
336
|
+
align-items: center;
|
|
337
|
+
justify-content: center;
|
|
338
|
+
border-radius: 6px;
|
|
339
|
+
border: 1px solid var(--opp-reject-border);
|
|
340
|
+
background: var(--opp-bg);
|
|
341
|
+
color: var(--opp-fg);
|
|
342
|
+
cursor: pointer;
|
|
213
343
|
}
|
|
214
344
|
|
|
215
|
-
.opp-
|
|
216
|
-
color: var(--opp-
|
|
217
|
-
|
|
345
|
+
.opp-copy:hover {
|
|
346
|
+
border-color: var(--opp-accent);
|
|
347
|
+
color: var(--opp-accent);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.opp-fee-note {
|
|
351
|
+
font-size: 11px;
|
|
352
|
+
color: var(--opp-muted);
|
|
353
|
+
line-height: 1.3;
|
|
354
|
+
margin-top: -4px;
|
|
218
355
|
}
|
|
219
356
|
|
|
220
357
|
.opp-actions {
|
|
@@ -264,7 +401,7 @@ var promptStyles = `
|
|
|
264
401
|
`;
|
|
265
402
|
|
|
266
403
|
// src/OneSatPermissionPrompt.tsx
|
|
267
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
404
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
268
405
|
function OneSatPermissionPrompt({
|
|
269
406
|
request,
|
|
270
407
|
onApprove,
|
|
@@ -272,8 +409,25 @@ function OneSatPermissionPrompt({
|
|
|
272
409
|
theme = "auto"
|
|
273
410
|
}) {
|
|
274
411
|
const resolvedTheme = useResolvedTheme(theme);
|
|
275
|
-
const
|
|
412
|
+
const base = summarizeRequest(request);
|
|
276
413
|
const [busy, setBusy] = useState(false);
|
|
414
|
+
const [verified, setVerified] = useState(undefined);
|
|
415
|
+
const verification = request.intent?.verification;
|
|
416
|
+
useEffect(() => {
|
|
417
|
+
if (!verification)
|
|
418
|
+
return;
|
|
419
|
+
let live = true;
|
|
420
|
+
verification.then((res) => {
|
|
421
|
+
if (live && res)
|
|
422
|
+
setVerified(res);
|
|
423
|
+
}).catch(() => {
|
|
424
|
+
return;
|
|
425
|
+
});
|
|
426
|
+
return () => {
|
|
427
|
+
live = false;
|
|
428
|
+
};
|
|
429
|
+
}, [verification]);
|
|
430
|
+
const summary = verified ? applyVerification(base, verified) : base;
|
|
277
431
|
const handle = (action) => () => {
|
|
278
432
|
if (busy)
|
|
279
433
|
return;
|
|
@@ -289,6 +443,8 @@ function OneSatPermissionPrompt({
|
|
|
289
443
|
};
|
|
290
444
|
useEffect(() => {
|
|
291
445
|
const onKey = (e) => {
|
|
446
|
+
if (busy)
|
|
447
|
+
return;
|
|
292
448
|
if (e.key === "Escape")
|
|
293
449
|
onReject();
|
|
294
450
|
else if (e.key === "Enter")
|
|
@@ -296,8 +452,9 @@ function OneSatPermissionPrompt({
|
|
|
296
452
|
};
|
|
297
453
|
window.addEventListener("keydown", onKey);
|
|
298
454
|
return () => window.removeEventListener("keydown", onKey);
|
|
299
|
-
}, [onApprove, onReject]);
|
|
455
|
+
}, [onApprove, onReject, busy]);
|
|
300
456
|
const className = `opp-root${resolvedTheme === "dark" ? " opp-dark" : ""}`;
|
|
457
|
+
const featuredVariant = summary.featured?.variant ?? "ordinal";
|
|
301
458
|
return /* @__PURE__ */ jsxs("div", {
|
|
302
459
|
className,
|
|
303
460
|
children: [
|
|
@@ -355,12 +512,16 @@ function OneSatPermissionPrompt({
|
|
|
355
512
|
]
|
|
356
513
|
}),
|
|
357
514
|
summary.featured && /* @__PURE__ */ jsxs("div", {
|
|
358
|
-
className: "opp-featured"
|
|
515
|
+
className: `opp-featured${featuredVariant === "token" ? " opp-featured-token" : ""}`,
|
|
359
516
|
children: [
|
|
360
|
-
/* @__PURE__ */ jsx("img", {
|
|
361
|
-
className: "opp-featured-image",
|
|
517
|
+
summary.featured.imageUrl ? /* @__PURE__ */ jsx("img", {
|
|
518
|
+
className: featuredVariant === "token" ? "opp-featured-image opp-featured-image-token" : "opp-featured-image",
|
|
362
519
|
src: summary.featured.imageUrl,
|
|
363
520
|
alt: summary.featured.title
|
|
521
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
522
|
+
className: featuredVariant === "token" ? "opp-featured-image opp-featured-image-token opp-featured-placeholder" : "opp-featured-image opp-featured-placeholder",
|
|
523
|
+
"aria-hidden": true,
|
|
524
|
+
children: featuredVariant === "token" ? "◎" : "▭"
|
|
364
525
|
}),
|
|
365
526
|
/* @__PURE__ */ jsxs("div", {
|
|
366
527
|
className: "opp-featured-meta",
|
|
@@ -369,61 +530,89 @@ function OneSatPermissionPrompt({
|
|
|
369
530
|
className: "opp-featured-title",
|
|
370
531
|
children: summary.featured.title
|
|
371
532
|
}),
|
|
372
|
-
summary.featured.subtitle && /* @__PURE__ */
|
|
533
|
+
summary.featured.subtitle && /* @__PURE__ */ jsxs("div", {
|
|
373
534
|
className: "opp-featured-subtitle",
|
|
374
|
-
children:
|
|
535
|
+
children: [
|
|
536
|
+
/* @__PURE__ */ jsx("span", {
|
|
537
|
+
className: "opp-featured-subtitle-text",
|
|
538
|
+
children: summary.featured.subtitle
|
|
539
|
+
}),
|
|
540
|
+
summary.featured.subtitleCopy && /* @__PURE__ */ jsx(CopyButton, {
|
|
541
|
+
text: summary.featured.subtitleCopy
|
|
542
|
+
})
|
|
543
|
+
]
|
|
375
544
|
})
|
|
376
545
|
]
|
|
377
546
|
})
|
|
378
547
|
]
|
|
379
548
|
}),
|
|
380
|
-
summary.
|
|
381
|
-
className: "opp-
|
|
382
|
-
children:
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
})
|
|
393
|
-
]
|
|
394
|
-
}, `${row.key}:${row.value}`))
|
|
549
|
+
summary.trust && /* @__PURE__ */ jsxs("div", {
|
|
550
|
+
className: "opp-trust-wrap",
|
|
551
|
+
children: [
|
|
552
|
+
/* @__PURE__ */ jsx("span", {
|
|
553
|
+
className: `opp-trust opp-trust-${summary.trust.state}`,
|
|
554
|
+
children: trustLabel(summary.trust.state)
|
|
555
|
+
}),
|
|
556
|
+
summary.trust.note && /* @__PURE__ */ jsx("div", {
|
|
557
|
+
className: `opp-trust-note opp-trust-note-${summary.trust.state}`,
|
|
558
|
+
children: summary.trust.note
|
|
559
|
+
})
|
|
560
|
+
]
|
|
395
561
|
}),
|
|
396
|
-
/* @__PURE__ */ jsxs("div", {
|
|
397
|
-
className: "opp-
|
|
562
|
+
(summary.rows.length > 0 || summary.indexerFee) && /* @__PURE__ */ jsxs("div", {
|
|
563
|
+
className: "opp-card",
|
|
398
564
|
children: [
|
|
399
|
-
|
|
400
|
-
className: "opp-
|
|
565
|
+
summary.rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
566
|
+
className: "opp-row",
|
|
401
567
|
children: [
|
|
402
|
-
|
|
568
|
+
/* @__PURE__ */ jsx("span", {
|
|
569
|
+
className: "opp-row-key",
|
|
570
|
+
children: row.key
|
|
571
|
+
}),
|
|
572
|
+
/* @__PURE__ */ jsxs("span", {
|
|
573
|
+
className: "opp-row-value-wrap",
|
|
403
574
|
children: [
|
|
404
|
-
"Network",
|
|
405
|
-
" ",
|
|
406
575
|
/* @__PURE__ */ jsx("span", {
|
|
407
|
-
className: "opp-
|
|
408
|
-
|
|
576
|
+
className: "opp-row-value",
|
|
577
|
+
title: row.copyValue ?? row.value,
|
|
578
|
+
children: row.value
|
|
579
|
+
}),
|
|
580
|
+
row.copyValue && /* @__PURE__ */ jsx(CopyButton, {
|
|
581
|
+
text: row.copyValue
|
|
409
582
|
})
|
|
410
583
|
]
|
|
411
|
-
})
|
|
412
|
-
|
|
584
|
+
})
|
|
585
|
+
]
|
|
586
|
+
}, `${row.key}:${row.value}`)),
|
|
587
|
+
summary.indexerFee && /* @__PURE__ */ jsxs(Fragment, {
|
|
588
|
+
children: [
|
|
589
|
+
/* @__PURE__ */ jsxs("div", {
|
|
590
|
+
className: "opp-row",
|
|
413
591
|
children: [
|
|
414
|
-
|
|
415
|
-
|
|
592
|
+
/* @__PURE__ */ jsx("span", {
|
|
593
|
+
className: "opp-row-key",
|
|
594
|
+
children: "Indexer fee"
|
|
595
|
+
}),
|
|
416
596
|
/* @__PURE__ */ jsxs("span", {
|
|
417
|
-
className: "opp-
|
|
597
|
+
className: "opp-row-value",
|
|
418
598
|
children: [
|
|
419
|
-
summary.
|
|
599
|
+
formatSats(summary.indexerFee.sats),
|
|
420
600
|
" sats"
|
|
421
601
|
]
|
|
422
602
|
})
|
|
423
603
|
]
|
|
604
|
+
}),
|
|
605
|
+
summary.indexerFee.note && /* @__PURE__ */ jsx("div", {
|
|
606
|
+
className: "opp-fee-note",
|
|
607
|
+
children: summary.indexerFee.note
|
|
424
608
|
})
|
|
425
609
|
]
|
|
426
|
-
})
|
|
610
|
+
})
|
|
611
|
+
]
|
|
612
|
+
}),
|
|
613
|
+
/* @__PURE__ */ jsxs("div", {
|
|
614
|
+
className: "opp-bottom",
|
|
615
|
+
children: [
|
|
427
616
|
/* @__PURE__ */ jsxs("div", {
|
|
428
617
|
className: "opp-actions",
|
|
429
618
|
children: [
|
|
@@ -454,6 +643,72 @@ function OneSatPermissionPrompt({
|
|
|
454
643
|
]
|
|
455
644
|
});
|
|
456
645
|
}
|
|
646
|
+
function trustLabel(state) {
|
|
647
|
+
if (state === "verified")
|
|
648
|
+
return "Verified";
|
|
649
|
+
if (state === "mismatch")
|
|
650
|
+
return "Mismatch";
|
|
651
|
+
return "Unverified";
|
|
652
|
+
}
|
|
653
|
+
function formatSats(n) {
|
|
654
|
+
return n.toLocaleString("en-US");
|
|
655
|
+
}
|
|
656
|
+
function CopyButton({ text }) {
|
|
657
|
+
const [copied, setCopied] = useState(false);
|
|
658
|
+
const onCopy = () => {
|
|
659
|
+
navigator.clipboard?.writeText(text).then(() => {
|
|
660
|
+
setCopied(true);
|
|
661
|
+
window.setTimeout(() => setCopied(false), 1200);
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
return /* @__PURE__ */ jsx("button", {
|
|
665
|
+
type: "button",
|
|
666
|
+
className: "opp-copy",
|
|
667
|
+
onClick: onCopy,
|
|
668
|
+
"aria-label": copied ? "Copied" : "Copy full value",
|
|
669
|
+
title: copied ? "Copied" : "Copy",
|
|
670
|
+
children: copied ? /* @__PURE__ */ jsx("svg", {
|
|
671
|
+
width: "12",
|
|
672
|
+
height: "12",
|
|
673
|
+
viewBox: "0 0 24 24",
|
|
674
|
+
fill: "none",
|
|
675
|
+
"aria-hidden": true,
|
|
676
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
677
|
+
d: "M5 13l4 4L19 7",
|
|
678
|
+
stroke: "currentColor",
|
|
679
|
+
strokeWidth: "2.5",
|
|
680
|
+
strokeLinecap: "round",
|
|
681
|
+
strokeLinejoin: "round"
|
|
682
|
+
})
|
|
683
|
+
}) : /* @__PURE__ */ jsxs("svg", {
|
|
684
|
+
width: "12",
|
|
685
|
+
height: "12",
|
|
686
|
+
viewBox: "0 0 24 24",
|
|
687
|
+
fill: "none",
|
|
688
|
+
"aria-hidden": true,
|
|
689
|
+
children: [
|
|
690
|
+
/* @__PURE__ */ jsx("rect", {
|
|
691
|
+
x: "9",
|
|
692
|
+
y: "9",
|
|
693
|
+
width: "11",
|
|
694
|
+
height: "11",
|
|
695
|
+
rx: "2",
|
|
696
|
+
stroke: "currentColor",
|
|
697
|
+
strokeWidth: "2"
|
|
698
|
+
}),
|
|
699
|
+
/* @__PURE__ */ jsx("path", {
|
|
700
|
+
d: "M5 15V5a2 2 0 012-2h10",
|
|
701
|
+
stroke: "currentColor",
|
|
702
|
+
strokeWidth: "2",
|
|
703
|
+
strokeLinecap: "round"
|
|
704
|
+
})
|
|
705
|
+
]
|
|
706
|
+
})
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
function copyable(key, full) {
|
|
710
|
+
return { key, value: shortenValue(full), copyValue: full };
|
|
711
|
+
}
|
|
457
712
|
function useResolvedTheme(theme) {
|
|
458
713
|
const [resolved, setResolved] = useState(() => theme === "auto" ? readSystemTheme() : theme);
|
|
459
714
|
useEffect(() => {
|
|
@@ -474,9 +729,38 @@ function readSystemTheme() {
|
|
|
474
729
|
return "light";
|
|
475
730
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
476
731
|
}
|
|
732
|
+
function applyVerification(base, res) {
|
|
733
|
+
const rows = base.rows.map((row) => {
|
|
734
|
+
if (row.key === "Origin" && res.origin)
|
|
735
|
+
return copyable("Origin", res.origin);
|
|
736
|
+
if (row.key === "Type" && res.contentType) {
|
|
737
|
+
return { key: "Type", value: res.contentType };
|
|
738
|
+
}
|
|
739
|
+
return row;
|
|
740
|
+
});
|
|
741
|
+
if (res.contentLength !== undefined && !rows.some((r) => r.key === "Size")) {
|
|
742
|
+
rows.push({
|
|
743
|
+
key: "Size",
|
|
744
|
+
value: `${res.contentLength.toLocaleString("en-US")} bytes`
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
return {
|
|
748
|
+
...base,
|
|
749
|
+
rows,
|
|
750
|
+
trust: { state: res.state, note: res.note },
|
|
751
|
+
featured: base.featured ? {
|
|
752
|
+
...base.featured,
|
|
753
|
+
title: res.name ?? base.featured.title,
|
|
754
|
+
imageUrl: res.contentUrl ?? base.featured.imageUrl
|
|
755
|
+
} : undefined
|
|
756
|
+
};
|
|
757
|
+
}
|
|
477
758
|
function summarizeRequest(req) {
|
|
478
759
|
if (req.kind === "transaction") {
|
|
479
760
|
const intent = req.intent;
|
|
761
|
+
const byIntent = summarizeByP1SatIntent(req, intent);
|
|
762
|
+
if (byIntent)
|
|
763
|
+
return byIntent;
|
|
480
764
|
switch (intent.kind) {
|
|
481
765
|
case "ordinal-transfer":
|
|
482
766
|
return summarizeOrdinalTransfer(req, intent);
|
|
@@ -522,6 +806,128 @@ function summarizeBasketAccess(req) {
|
|
|
522
806
|
}))
|
|
523
807
|
};
|
|
524
808
|
}
|
|
809
|
+
var INTENT_TITLES = {
|
|
810
|
+
"opns.register": "Publish name",
|
|
811
|
+
"opns.deregister": "Unpublish name",
|
|
812
|
+
"opns.list": "List name for sale",
|
|
813
|
+
"opns.transfer": "Transfer name",
|
|
814
|
+
"opns.cancel-listing": "Cancel listing",
|
|
815
|
+
"opns.purchase": "Buy name",
|
|
816
|
+
"ordinal.transfer": "Send ordinal",
|
|
817
|
+
"ordinal.list": "List for sale",
|
|
818
|
+
"ordinal.cancel-listing": "Cancel listing",
|
|
819
|
+
"ordinal.purchase": "Buy ordinal",
|
|
820
|
+
"ordinal.burn": "Burn ordinal",
|
|
821
|
+
"ordinal.inscribe": "Create inscription",
|
|
822
|
+
"ordinal.inscribe-sigma": "Create inscription",
|
|
823
|
+
"ordinal.mint-collection": "Mint collection",
|
|
824
|
+
"ordinal.mint-item": "Mint collection item",
|
|
825
|
+
"lock.lock": "Lock BSV",
|
|
826
|
+
"lock.unlock": "Unlock BSV",
|
|
827
|
+
"bsv21.transfer": "Send tokens",
|
|
828
|
+
"bsv21.purchase": "Buy tokens",
|
|
829
|
+
"bsv21.mint": "Mint tokens",
|
|
830
|
+
"bsv21.deploy": "Deploy token"
|
|
831
|
+
};
|
|
832
|
+
function summarizeByP1SatIntent(req, intent) {
|
|
833
|
+
const id = intent.p1satIntent;
|
|
834
|
+
if (!id || !INTENT_TITLES[id])
|
|
835
|
+
return;
|
|
836
|
+
let base;
|
|
837
|
+
switch (intent.kind) {
|
|
838
|
+
case "ordinal-transfer":
|
|
839
|
+
base = summarizeOrdinalTransfer(req, intent);
|
|
840
|
+
break;
|
|
841
|
+
case "token-transfer":
|
|
842
|
+
base = summarizeTokenTransfer(req, intent);
|
|
843
|
+
break;
|
|
844
|
+
case "lock":
|
|
845
|
+
base = summarizeLock(req, intent);
|
|
846
|
+
break;
|
|
847
|
+
case "unlock":
|
|
848
|
+
base = summarizeUnlock(req, intent);
|
|
849
|
+
break;
|
|
850
|
+
case "inscription":
|
|
851
|
+
base = summarizeInscription(req, intent);
|
|
852
|
+
break;
|
|
853
|
+
case "listing":
|
|
854
|
+
base = summarizeListing(req, intent);
|
|
855
|
+
break;
|
|
856
|
+
case "cancel-listing":
|
|
857
|
+
base = summarizeCancelListing(req, intent);
|
|
858
|
+
break;
|
|
859
|
+
case "purchase":
|
|
860
|
+
base = summarizePurchase(req, intent);
|
|
861
|
+
break;
|
|
862
|
+
case "opns":
|
|
863
|
+
base = summarizeOpns(req, intent);
|
|
864
|
+
break;
|
|
865
|
+
default:
|
|
866
|
+
base = summarizeUnknownTx(req, intent);
|
|
867
|
+
}
|
|
868
|
+
return {
|
|
869
|
+
...base,
|
|
870
|
+
title: INTENT_TITLES[id],
|
|
871
|
+
subtitle: intentSubtitle(req, id, intent),
|
|
872
|
+
feeSats: undefined,
|
|
873
|
+
network: undefined,
|
|
874
|
+
trust: intent.trust ?? base.trust,
|
|
875
|
+
indexerFee: intent.indexerFeeSats != null && intent.indexerFeeSats > 0 ? {
|
|
876
|
+
sats: intent.indexerFeeSats,
|
|
877
|
+
note: intent.indexerFeeNote
|
|
878
|
+
} : base.indexerFee
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
function intentSubtitle(req, id, intent) {
|
|
882
|
+
const o = shortenOriginator(req.originator);
|
|
883
|
+
const name = tagValue(intent.inputs[0]?.tags, "name") ?? tagValue(intent.outputs.find((out) => out.tags.some((t) => t.startsWith("name:")))?.tags, "name");
|
|
884
|
+
const quoted = name ? `“${name}”` : undefined;
|
|
885
|
+
switch (id) {
|
|
886
|
+
case "opns.register":
|
|
887
|
+
return `${o} wants to publish ${quoted ?? "an OpNS name"}`;
|
|
888
|
+
case "opns.deregister":
|
|
889
|
+
return `${o} wants to unpublish ${quoted ?? "an OpNS name"}`;
|
|
890
|
+
case "opns.list":
|
|
891
|
+
return `${o} wants to list ${quoted ?? "an OpNS name"} for sale`;
|
|
892
|
+
case "opns.transfer":
|
|
893
|
+
return `${o} wants to transfer ${quoted ?? "an OpNS name"}`;
|
|
894
|
+
case "opns.cancel-listing":
|
|
895
|
+
return `${o} wants to cancel ${quoted ? `the listing of ${quoted}` : "an OpNS listing"}`;
|
|
896
|
+
case "opns.purchase":
|
|
897
|
+
return `${o} wants to buy ${quoted ?? "an OpNS name"}`;
|
|
898
|
+
case "ordinal.transfer":
|
|
899
|
+
return `${o} wants to transfer an ordinal`;
|
|
900
|
+
case "ordinal.list":
|
|
901
|
+
return `${o} wants to list ${quoted ?? "an ordinal"} for sale`;
|
|
902
|
+
case "ordinal.cancel-listing":
|
|
903
|
+
return `${o} wants to cancel ${quoted ? `the listing of ${quoted}` : "an ordinal listing"}`;
|
|
904
|
+
case "ordinal.purchase":
|
|
905
|
+
return `${o} wants to purchase an ordinal into your wallet`;
|
|
906
|
+
case "ordinal.burn":
|
|
907
|
+
return `${o} wants to burn an ordinal`;
|
|
908
|
+
case "ordinal.inscribe":
|
|
909
|
+
case "ordinal.inscribe-sigma":
|
|
910
|
+
return `${o} wants to inscribe content into your wallet`;
|
|
911
|
+
case "ordinal.mint-collection":
|
|
912
|
+
return `${o} wants to mint a collection`;
|
|
913
|
+
case "ordinal.mint-item":
|
|
914
|
+
return `${o} wants to mint a collection item`;
|
|
915
|
+
case "lock.lock":
|
|
916
|
+
return `${o} wants to time-lock funds`;
|
|
917
|
+
case "lock.unlock":
|
|
918
|
+
return `${o} wants to unlock matured locks`;
|
|
919
|
+
case "bsv21.transfer":
|
|
920
|
+
return `${o} wants to send tokens`;
|
|
921
|
+
case "bsv21.purchase":
|
|
922
|
+
return `${o} wants to purchase tokens into your wallet`;
|
|
923
|
+
case "bsv21.mint":
|
|
924
|
+
return `${o} wants to mint tokens`;
|
|
925
|
+
case "bsv21.deploy":
|
|
926
|
+
return `${o} wants to deploy a BSV21 token`;
|
|
927
|
+
default:
|
|
928
|
+
return `${o} wants to ${req.summary.toLowerCase()}`;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
525
931
|
function tagValue(tags, key) {
|
|
526
932
|
if (!tags)
|
|
527
933
|
return;
|
|
@@ -542,21 +948,20 @@ function summarizeOrdinalTransfer(req, intent) {
|
|
|
542
948
|
const imageUrl = origin ? intent.contentUrls?.[origin] : undefined;
|
|
543
949
|
const rows = [];
|
|
544
950
|
if (recipient)
|
|
545
|
-
rows.push(
|
|
951
|
+
rows.push(copyable("Recipient", recipient));
|
|
546
952
|
if (origin)
|
|
547
|
-
rows.push(
|
|
953
|
+
rows.push(copyable("Origin", origin));
|
|
548
954
|
if (contentType)
|
|
549
955
|
rows.push({ key: "Type", value: contentType });
|
|
550
956
|
return {
|
|
551
|
-
title: "
|
|
957
|
+
title: "Send ordinal",
|
|
552
958
|
subtitle: `${shortenOriginator(req.originator)} wants to transfer an ordinal`,
|
|
553
959
|
rows,
|
|
554
960
|
featured: imageUrl ? {
|
|
555
961
|
imageUrl,
|
|
556
962
|
title: name ?? "Untitled ordinal",
|
|
557
963
|
subtitle: collectionId ?? contentType
|
|
558
|
-
} : undefined
|
|
559
|
-
network: networkLabel(intent.chain)
|
|
964
|
+
} : undefined
|
|
560
965
|
};
|
|
561
966
|
}
|
|
562
967
|
function summarizeTokenTransfer(req, intent) {
|
|
@@ -565,12 +970,12 @@ function summarizeTokenTransfer(req, intent) {
|
|
|
565
970
|
const tokenId = tagValue(input.tags, "bsv21");
|
|
566
971
|
if (!tokenId)
|
|
567
972
|
continue;
|
|
568
|
-
const
|
|
973
|
+
const sym2 = tagValue(input.tags, "sym");
|
|
569
974
|
const amt = BigInt(tagValue(input.tags, "amt") ?? "0");
|
|
570
|
-
const cur = totals.get(tokenId) ?? { sym, inAmt: 0n, changeAmt: 0n };
|
|
975
|
+
const cur = totals.get(tokenId) ?? { sym: sym2, inAmt: 0n, changeAmt: 0n };
|
|
571
976
|
cur.inAmt += amt;
|
|
572
|
-
if (!cur.sym &&
|
|
573
|
-
cur.sym =
|
|
977
|
+
if (!cur.sym && sym2)
|
|
978
|
+
cur.sym = sym2;
|
|
574
979
|
totals.set(tokenId, cur);
|
|
575
980
|
}
|
|
576
981
|
for (const output of intent.outputs) {
|
|
@@ -585,36 +990,75 @@ function summarizeTokenTransfer(req, intent) {
|
|
|
585
990
|
cur.changeAmt += amt;
|
|
586
991
|
}
|
|
587
992
|
const rows = [];
|
|
993
|
+
let featured;
|
|
994
|
+
let primaryTokenId;
|
|
588
995
|
for (const [tokenId, info] of totals) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
value: info.sym ? `${info.sym} — ${shortenId(tokenId)}` : shortenId(tokenId)
|
|
592
|
-
});
|
|
996
|
+
if (!primaryTokenId)
|
|
997
|
+
primaryTokenId = tokenId;
|
|
593
998
|
const sent = info.inAmt - info.changeAmt;
|
|
594
|
-
rows.push({ key: "Amount", value: sent.
|
|
999
|
+
rows.push({ key: "Amount", value: sent.toLocaleString("en-US") });
|
|
595
1000
|
}
|
|
596
|
-
const
|
|
597
|
-
if (
|
|
598
|
-
rows.push(
|
|
1001
|
+
const to = intent.outputs.find((o) => o.recipient && o.satoshis === 1)?.recipient;
|
|
1002
|
+
if (to)
|
|
1003
|
+
rows.push(copyable("Recipient", to));
|
|
1004
|
+
const firstIn = intent.inputs.find((i) => tagValue(i.tags, "bsv21"));
|
|
1005
|
+
const sym = (primaryTokenId ? totals.get(primaryTokenId)?.sym : undefined) ?? tagValue(firstIn?.tags, "sym");
|
|
1006
|
+
const iconRef = tagValue(firstIn?.tags, "icon");
|
|
1007
|
+
const iconUrl = iconRef && intent.contentUrls?.[iconRef] || primaryTokenId && intent.contentUrls?.[primaryTokenId] || undefined;
|
|
1008
|
+
if (primaryTokenId) {
|
|
1009
|
+
featured = {
|
|
1010
|
+
variant: "token",
|
|
1011
|
+
imageUrl: iconUrl,
|
|
1012
|
+
title: sym ?? "Token",
|
|
1013
|
+
subtitle: shortenId(primaryTokenId),
|
|
1014
|
+
subtitleCopy: primaryTokenId
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
const indexerFee = resolveIndexerFee(intent);
|
|
599
1018
|
return {
|
|
600
|
-
title: "
|
|
1019
|
+
title: "Send tokens",
|
|
601
1020
|
subtitle: `${shortenOriginator(req.originator)} wants to send tokens`,
|
|
602
1021
|
rows,
|
|
603
|
-
|
|
1022
|
+
featured,
|
|
1023
|
+
indexerFee
|
|
604
1024
|
};
|
|
605
1025
|
}
|
|
1026
|
+
function resolveIndexerFee(intent) {
|
|
1027
|
+
if (intent.indexerFeeSats != null && intent.indexerFeeSats > 0) {
|
|
1028
|
+
return {
|
|
1029
|
+
sats: intent.indexerFeeSats,
|
|
1030
|
+
note: intent.indexerFeeNote
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
const tokenOutCount = intent.outputs.filter((o) => o.basket === BSV21_BASKET || tagValue(o.tags, "bsv21")).length;
|
|
1034
|
+
const feeLike = intent.outputs.filter((o) => !o.basket && o.recipient && o.satoshis > 1);
|
|
1035
|
+
const isPurchase = intent.p1satIntent?.endsWith(".purchase") || intent.kind === "purchase";
|
|
1036
|
+
if (isPurchase || feeLike.length !== 1)
|
|
1037
|
+
return;
|
|
1038
|
+
const fee = feeLike[0];
|
|
1039
|
+
if (!fee || fee.satoshis <= 0)
|
|
1040
|
+
return;
|
|
1041
|
+
const note = tokenOutCount > 0 ? `Overlay processing · ${formatSats(Math.round(fee.satoshis / tokenOutCount))} sats × ${tokenOutCount} token outs` : "Overlay processing fee";
|
|
1042
|
+
return { sats: fee.satoshis, note };
|
|
1043
|
+
}
|
|
606
1044
|
function summarizeLock(req, intent) {
|
|
607
|
-
const
|
|
1045
|
+
const decoded = intent.outputs.filter((o) => o.lockUntilHeight !== undefined);
|
|
1046
|
+
const lockOutputs = decoded.length > 0 ? decoded : intent.outputs.filter((o) => o.basket === LOCK_BASKET);
|
|
608
1047
|
const sats = (lockOutputs.length > 0 ? lockOutputs : intent.outputs).reduce((s, o) => s + o.satoshis, 0);
|
|
609
|
-
const until =
|
|
610
|
-
const rows = [
|
|
611
|
-
|
|
612
|
-
|
|
1048
|
+
const until = decoded[0]?.lockUntilHeight;
|
|
1049
|
+
const rows = [
|
|
1050
|
+
{ key: "Amount", value: `${sats.toLocaleString("en-US")} sats` }
|
|
1051
|
+
];
|
|
1052
|
+
if (until !== undefined) {
|
|
1053
|
+
rows.push({
|
|
1054
|
+
key: "Lock until block",
|
|
1055
|
+
value: until.toLocaleString("en-US")
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
613
1058
|
return {
|
|
614
1059
|
title: "Lock BSV",
|
|
615
1060
|
subtitle: `${shortenOriginator(req.originator)} wants to time-lock funds`,
|
|
616
|
-
rows
|
|
617
|
-
network: networkLabel(intent.chain)
|
|
1061
|
+
rows
|
|
618
1062
|
};
|
|
619
1063
|
}
|
|
620
1064
|
function summarizeUnlock(req, intent) {
|
|
@@ -622,8 +1066,7 @@ function summarizeUnlock(req, intent) {
|
|
|
622
1066
|
return {
|
|
623
1067
|
title: "Unlock Matured",
|
|
624
1068
|
subtitle: `${shortenOriginator(req.originator)} wants to unlock matured locks`,
|
|
625
|
-
rows: [{ key: "Amount", value: `${sats} sats` }]
|
|
626
|
-
network: networkLabel(intent.chain)
|
|
1069
|
+
rows: [{ key: "Amount", value: `${sats} sats` }]
|
|
627
1070
|
};
|
|
628
1071
|
}
|
|
629
1072
|
function summarizeInscription(req, intent) {
|
|
@@ -637,30 +1080,30 @@ function summarizeInscription(req, intent) {
|
|
|
637
1080
|
if (name)
|
|
638
1081
|
rows.push({ key: "Name", value: name });
|
|
639
1082
|
if (recipient)
|
|
640
|
-
rows.push(
|
|
1083
|
+
rows.push(copyable("Recipient", recipient));
|
|
641
1084
|
return {
|
|
642
1085
|
title: "Create Inscription",
|
|
643
1086
|
subtitle: `${shortenOriginator(req.originator)} wants to inscribe content into your wallet`,
|
|
644
|
-
rows
|
|
645
|
-
network: networkLabel(intent.chain)
|
|
1087
|
+
rows
|
|
646
1088
|
};
|
|
647
1089
|
}
|
|
648
1090
|
function summarizeListing(req, intent) {
|
|
649
|
-
const listingOutput = intent.outputs.find((o) => o.tags.some((t) => t.startsWith("price:")));
|
|
1091
|
+
const listingOutput = intent.outputs.find((o) => o.listingPriceSats !== undefined) ?? intent.outputs.find((o) => o.tags.some((t) => t.startsWith("price:")));
|
|
650
1092
|
const ordinal = intent.inputs[0];
|
|
651
1093
|
const origin = tagValue(ordinal?.tags, "origin") ?? tagValue(listingOutput?.tags, "origin");
|
|
652
1094
|
const name = tagValue(ordinal?.tags, "name") ?? tagValue(listingOutput?.tags, "name");
|
|
653
1095
|
const contentType = tagValue(ordinal?.tags, "type") ?? tagValue(listingOutput?.tags, "type");
|
|
654
1096
|
const collectionId = tagValue(ordinal?.tags, "collectionId");
|
|
655
1097
|
const imageUrl = origin ? intent.contentUrls?.[origin] : undefined;
|
|
656
|
-
const price =
|
|
1098
|
+
const price = listingOutput?.listingPriceSats;
|
|
657
1099
|
const rows = [];
|
|
658
1100
|
if (name)
|
|
659
1101
|
rows.push({ key: "Name", value: name });
|
|
660
|
-
if (price)
|
|
661
|
-
rows.push({ key: "Price", value: `${price} sats` });
|
|
1102
|
+
if (price !== undefined) {
|
|
1103
|
+
rows.push({ key: "Price", value: `${price.toLocaleString("en-US")} sats` });
|
|
1104
|
+
}
|
|
662
1105
|
if (origin)
|
|
663
|
-
rows.push(
|
|
1106
|
+
rows.push(copyable("Origin", origin));
|
|
664
1107
|
if (contentType)
|
|
665
1108
|
rows.push({ key: "Type", value: contentType });
|
|
666
1109
|
return {
|
|
@@ -671,8 +1114,7 @@ function summarizeListing(req, intent) {
|
|
|
671
1114
|
imageUrl,
|
|
672
1115
|
title: name ?? "Untitled ordinal",
|
|
673
1116
|
subtitle: collectionId ?? contentType
|
|
674
|
-
} : undefined
|
|
675
|
-
network: networkLabel(intent.chain)
|
|
1117
|
+
} : undefined
|
|
676
1118
|
};
|
|
677
1119
|
}
|
|
678
1120
|
function summarizeCancelListing(req, intent) {
|
|
@@ -690,7 +1132,7 @@ function summarizeCancelListing(req, intent) {
|
|
|
690
1132
|
if (price)
|
|
691
1133
|
rows.push({ key: "Original price", value: `${price} sats` });
|
|
692
1134
|
if (origin)
|
|
693
|
-
rows.push(
|
|
1135
|
+
rows.push(copyable("Origin", origin));
|
|
694
1136
|
if (contentType)
|
|
695
1137
|
rows.push({ key: "Type", value: contentType });
|
|
696
1138
|
return {
|
|
@@ -701,8 +1143,7 @@ function summarizeCancelListing(req, intent) {
|
|
|
701
1143
|
imageUrl,
|
|
702
1144
|
title: name ?? "Untitled ordinal",
|
|
703
1145
|
subtitle: collectionId ?? contentType
|
|
704
|
-
} : undefined
|
|
705
|
-
network: networkLabel(intent.chain)
|
|
1146
|
+
} : undefined
|
|
706
1147
|
};
|
|
707
1148
|
}
|
|
708
1149
|
function summarizePurchase(req, intent) {
|
|
@@ -719,41 +1160,49 @@ function summarizePurchase(req, intent) {
|
|
|
719
1160
|
const price = sellerOutput?.satoshis;
|
|
720
1161
|
const rows = [];
|
|
721
1162
|
if (price !== undefined)
|
|
722
|
-
rows.push({ key: "Price", value: `${price} sats` });
|
|
1163
|
+
rows.push({ key: "Price", value: `${price.toLocaleString("en-US")} sats` });
|
|
723
1164
|
if (isToken) {
|
|
724
1165
|
if (amt)
|
|
725
1166
|
rows.push({ key: "Amount", value: amt });
|
|
726
|
-
if (sym || tokenId) {
|
|
727
|
-
rows.push({
|
|
728
|
-
key: "Token",
|
|
729
|
-
value: sym && tokenId ? `${sym} — ${shortenId(tokenId)}` : sym ?? shortenId(tokenId ?? "")
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
1167
|
} else {
|
|
733
1168
|
if (origin)
|
|
734
|
-
rows.push(
|
|
1169
|
+
rows.push(copyable("Origin", origin));
|
|
735
1170
|
if (contentType)
|
|
736
1171
|
rows.push({ key: "Type", value: contentType });
|
|
737
1172
|
}
|
|
738
1173
|
const featuredImage = !isToken && origin ? intent.contentUrls?.[origin] : undefined;
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
featured
|
|
1174
|
+
const iconRef = tagValue(incoming?.tags, "icon");
|
|
1175
|
+
const iconUrl = iconRef && intent.contentUrls?.[iconRef] || tokenId && intent.contentUrls?.[tokenId] || undefined;
|
|
1176
|
+
let featured;
|
|
1177
|
+
if (isToken && (sym || tokenId)) {
|
|
1178
|
+
featured = {
|
|
1179
|
+
variant: "token",
|
|
1180
|
+
imageUrl: iconUrl,
|
|
1181
|
+
title: sym ?? "Token",
|
|
1182
|
+
subtitle: tokenId ? shortenId(tokenId) : undefined,
|
|
1183
|
+
subtitleCopy: tokenId
|
|
1184
|
+
};
|
|
1185
|
+
} else if (featuredImage) {
|
|
1186
|
+
featured = {
|
|
744
1187
|
imageUrl: featuredImage,
|
|
745
1188
|
title: name ?? "Untitled ordinal",
|
|
746
1189
|
subtitle: collectionId ?? contentType
|
|
747
|
-
}
|
|
748
|
-
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
return {
|
|
1193
|
+
title: isToken ? "Buy tokens" : "Buy ordinal",
|
|
1194
|
+
subtitle: isToken ? `${shortenOriginator(req.originator)} wants to purchase tokens into your wallet` : `${shortenOriginator(req.originator)} wants to purchase an ordinal into your wallet`,
|
|
1195
|
+
rows,
|
|
1196
|
+
featured,
|
|
1197
|
+
trust: intent.trust,
|
|
1198
|
+
indexerFee: resolveIndexerFee(intent)
|
|
749
1199
|
};
|
|
750
1200
|
}
|
|
751
1201
|
function summarizeSocialPost(req, intent) {
|
|
752
1202
|
return {
|
|
753
1203
|
title: "Social Post",
|
|
754
1204
|
subtitle: `${shortenOriginator(req.originator)} wants to publish a post`,
|
|
755
|
-
rows: []
|
|
756
|
-
network: networkLabel(intent.chain)
|
|
1205
|
+
rows: []
|
|
757
1206
|
};
|
|
758
1207
|
}
|
|
759
1208
|
function summarizeOpns(req, intent) {
|
|
@@ -762,34 +1211,52 @@ function summarizeOpns(req, intent) {
|
|
|
762
1211
|
const recipient = intent.outputs.find((o) => !o.basket && o.recipient)?.recipient;
|
|
763
1212
|
const name = tagValue(input?.tags, "name") ?? tagValue(opnsOutput?.tags, "name");
|
|
764
1213
|
const origin = tagValue(input?.tags, "origin") ?? tagValue(opnsOutput?.tags, "origin");
|
|
1214
|
+
const priceTag = intent.outputs.flatMap((o) => o.tags).find((t) => t.startsWith("price:"));
|
|
1215
|
+
const price = priceTag?.slice("price:".length);
|
|
765
1216
|
const rows = [];
|
|
766
1217
|
if (name)
|
|
767
1218
|
rows.push({ key: "Name", value: name });
|
|
768
1219
|
if (recipient)
|
|
769
|
-
rows.push(
|
|
1220
|
+
rows.push(copyable("Recipient", recipient));
|
|
1221
|
+
if (price)
|
|
1222
|
+
rows.push({ key: "Price", value: `${price} sats` });
|
|
770
1223
|
if (origin)
|
|
771
|
-
rows.push(
|
|
772
|
-
const
|
|
1224
|
+
rows.push(copyable("Origin", origin));
|
|
1225
|
+
const copy = opnsCopy(intent.p1satIntent, Boolean(recipient));
|
|
1226
|
+
const nameBit = name ? `“${name}”` : "an OpNS name";
|
|
773
1227
|
return {
|
|
774
|
-
title:
|
|
775
|
-
subtitle: `${shortenOriginator(req.originator)} wants to ${
|
|
776
|
-
rows
|
|
777
|
-
network: networkLabel(intent.chain)
|
|
1228
|
+
title: copy.title,
|
|
1229
|
+
subtitle: `${shortenOriginator(req.originator)} wants to ${copy.verb} ${nameBit}`,
|
|
1230
|
+
rows
|
|
778
1231
|
};
|
|
779
1232
|
}
|
|
1233
|
+
function opnsCopy(p1satIntent, isTransferHeuristic) {
|
|
1234
|
+
switch (p1satIntent) {
|
|
1235
|
+
case "opns.register":
|
|
1236
|
+
return { title: "Publish name", verb: "publish" };
|
|
1237
|
+
case "opns.deregister":
|
|
1238
|
+
return { title: "Unpublish name", verb: "unpublish" };
|
|
1239
|
+
case "opns.list":
|
|
1240
|
+
return { title: "List name for sale", verb: "list" };
|
|
1241
|
+
case "opns.transfer":
|
|
1242
|
+
return { title: "Transfer name", verb: "transfer" };
|
|
1243
|
+
case "opns.cancel-listing":
|
|
1244
|
+
return { title: "Cancel listing", verb: "cancel the listing of" };
|
|
1245
|
+
case "opns.purchase":
|
|
1246
|
+
return { title: "Buy name", verb: "buy" };
|
|
1247
|
+
default:
|
|
1248
|
+
return isTransferHeuristic ? { title: "Transfer OpNS Name", verb: "transfer" } : { title: "Update OpNS Name", verb: "update" };
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
780
1251
|
function summarizeUnknownTx(req, intent) {
|
|
781
1252
|
const ins = intent.inputs.length;
|
|
782
1253
|
const outs = intent.outputs.length;
|
|
783
1254
|
return {
|
|
784
1255
|
title: "Transaction Request",
|
|
785
1256
|
subtitle: `${shortenOriginator(req.originator)} wants to ${req.summary.toLowerCase()}`,
|
|
786
|
-
rows: [{ key: "Inputs / Outputs", value: `${ins} / ${outs}` }]
|
|
787
|
-
network: networkLabel(intent.chain)
|
|
1257
|
+
rows: [{ key: "Inputs / Outputs", value: `${ins} / ${outs}` }]
|
|
788
1258
|
};
|
|
789
1259
|
}
|
|
790
|
-
function networkLabel(chain) {
|
|
791
|
-
return chain === "testnet" ? "BSV Testnet" : "BSV Mainnet";
|
|
792
|
-
}
|
|
793
1260
|
function shortenId(id, max = 24) {
|
|
794
1261
|
if (id.length <= max)
|
|
795
1262
|
return id;
|
package/dist/styles.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CSS string for the OneSatPermissionPrompt component. Inlined as a style
|
|
3
3
|
* tag so the host wallet doesn't have to wire up CSS imports.
|
|
4
4
|
*
|
|
5
|
-
* Colors match
|
|
5
|
+
* Colors match `docs/plans/mockups/p1sat-permissions.pen`.
|
|
6
6
|
*/
|
|
7
|
-
export declare const promptStyles = "\n.opp-root {\n --opp-bg: #ffffff;\n --opp-fg: #111827;\n --opp-muted: #6b7280;\n --opp-card-bg: #f7f8fa;\n --opp-card-border: #eceef2;\n --opp-accent: #E5A920;\n --opp-approve-bg: #E5A920;\n --opp-approve-fg: #ffffff;\n --opp-reject-bg: #ffffff;\n --opp-reject-fg: #111827;\n --opp-reject-border: #d1d5db;\n --opp-status-bg: #FFFBE6;\n --opp-status-fg: #E5A920;\n\n font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: var(--opp-bg);\n color: var(--opp-fg);\n border-radius: 16px;\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: 480px;\n min-height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.opp-bottom {\n margin-top: auto;\n display: flex;\n flex-direction: column;\n}\n\n.opp-root.opp-dark {\n --opp-bg: #0F1117;\n --opp-fg: #F9FAFB;\n --opp-muted: #9ca3af;\n --opp-card-bg: #1A1D27;\n --opp-card-border: #232636;\n --opp-reject-bg: #0F1117;\n --opp-reject-fg: #F9FAFB;\n --opp-reject-border: #2D3142;\n --opp-status-bg: #2A2408;\n --opp-status-fg: #E5A920;\n}\n\n.opp-body {\n padding: 24px 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n}\n\n.opp-coin {\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n}\n\n.opp-title {\n font-size: 16px;\n font-weight: 700;\n margin: 0;\n text-align: center;\n}\n\n.opp-subtitle {\n font-size: 12px;\n color: var(--opp-muted);\n margin: 0;\n text-align: center;\n line-height: 1.4;\n}\n\n.opp-status {\n background: var(--opp-status-bg);\n color: var(--opp-status-fg);\n padding: 4px 12px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n margin-top: 4px;\n border: 1px solid var(--opp-card-border);\n}\n\n.opp-card {\n background: var(--opp-card-bg);\n border: 1px solid var(--opp-card-border);\n border-radius: 10px;\n margin: 0 20px;\n padding: 16px;\n font-size: 13px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.opp-featured {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--opp-card-bg);\n border: 1px solid var(--opp-card-border);\n border-radius: 10px;\n margin: 0 20px;\n padding: 16px;\n}\n\n.opp-featured-image {\n width: 80px;\n height: 80px;\n border-radius: 8px;\n object-fit: cover;\n background: rgba(0, 0, 0, 0.
|
|
7
|
+
export declare const promptStyles = "\n.opp-root {\n --opp-bg: #ffffff;\n --opp-fg: #111827;\n --opp-muted: #6b7280;\n --opp-card-bg: #f7f8fa;\n --opp-card-border: #eceef2;\n --opp-accent: #E5A920;\n --opp-approve-bg: #E5A920;\n --opp-approve-fg: #ffffff;\n --opp-reject-bg: #ffffff;\n --opp-reject-fg: #111827;\n --opp-reject-border: #d1d5db;\n --opp-status-bg: #FFFBE6;\n --opp-status-fg: #E5A920;\n --opp-trust-ok-bg: #ECFDF5;\n --opp-trust-ok-fg: #059669;\n --opp-trust-warn-bg: #FFFBEB;\n --opp-trust-warn-fg: #D97706;\n --opp-trust-bad-bg: #FEF2F2;\n --opp-trust-bad-fg: #DC2626;\n\n font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: var(--opp-bg);\n color: var(--opp-fg);\n border-radius: 16px;\n display: flex;\n flex-direction: column;\n width: 100%;\n max-width: 480px;\n min-height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.opp-bottom {\n margin-top: auto;\n display: flex;\n flex-direction: column;\n}\n\n.opp-root.opp-dark {\n --opp-bg: #0F1117;\n --opp-fg: #F9FAFB;\n --opp-muted: #9ca3af;\n --opp-card-bg: #1A1D27;\n --opp-card-border: #232636;\n --opp-reject-bg: #0F1117;\n --opp-reject-fg: #F9FAFB;\n --opp-reject-border: #2D3142;\n --opp-status-bg: #2A2408;\n --opp-status-fg: #E5A920;\n --opp-trust-ok-bg: #0A2E1F;\n --opp-trust-ok-fg: #34D399;\n --opp-trust-warn-bg: #2A2008;\n --opp-trust-warn-fg: #FBBF24;\n --opp-trust-bad-bg: #2A1215;\n --opp-trust-bad-fg: #F87171;\n}\n\n.opp-body {\n padding: 24px 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n}\n\n.opp-coin {\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n}\n\n.opp-title {\n font-size: 16px;\n font-weight: 700;\n margin: 0;\n text-align: center;\n}\n\n.opp-subtitle {\n font-size: 12px;\n color: var(--opp-muted);\n margin: 0;\n text-align: center;\n line-height: 1.4;\n}\n\n.opp-status {\n background: var(--opp-status-bg);\n color: var(--opp-status-fg);\n padding: 4px 12px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n margin-top: 4px;\n border: 1px solid var(--opp-card-border);\n}\n\n.opp-card {\n background: var(--opp-card-bg);\n border: 1px solid var(--opp-card-border);\n border-radius: 10px;\n margin: 0 20px;\n padding: 16px;\n font-size: 13px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.opp-featured {\n display: flex;\n align-items: center;\n gap: 12px;\n background: var(--opp-card-bg);\n border: 1px solid var(--opp-card-border);\n border-radius: 10px;\n margin: 0 20px 8px;\n padding: 16px;\n}\n\n.opp-featured-image {\n width: 80px;\n height: 80px;\n border-radius: 8px;\n object-fit: cover;\n background: rgba(0, 0, 0, 0.08);\n flex-shrink: 0;\n}\n\n.opp-featured-image-token {\n width: 48px;\n height: 48px;\n border-radius: 999px;\n}\n\n.opp-featured-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--opp-muted);\n font-size: 18px;\n}\n\n.opp-featured-meta {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n flex: 1;\n}\n\n.opp-featured-title {\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.opp-featured-subtitle {\n font-size: 12px;\n color: var(--opp-muted);\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.opp-featured-subtitle-text {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, monospace;\n}\n\n.opp-trust-wrap {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin: 0 20px 8px;\n}\n\n.opp-trust {\n display: inline-flex;\n align-self: flex-start;\n padding: 3px 8px;\n border-radius: 999px;\n font-size: 10px;\n font-weight: 600;\n}\n\n.opp-trust-verified {\n background: var(--opp-trust-ok-bg);\n color: var(--opp-trust-ok-fg);\n}\n\n.opp-trust-unverified {\n background: var(--opp-trust-warn-bg);\n color: var(--opp-trust-warn-fg);\n}\n\n.opp-trust-mismatch {\n background: var(--opp-trust-bad-bg);\n color: var(--opp-trust-bad-fg);\n}\n\n.opp-trust-note {\n padding: 10px;\n border-radius: 8px;\n font-size: 11px;\n line-height: 1.35;\n}\n\n.opp-trust-note-verified {\n background: var(--opp-trust-ok-bg);\n color: var(--opp-trust-ok-fg);\n}\n\n.opp-trust-note-unverified {\n background: var(--opp-trust-warn-bg);\n color: var(--opp-trust-warn-fg);\n}\n\n.opp-trust-note-mismatch {\n background: var(--opp-trust-bad-bg);\n color: var(--opp-trust-bad-fg);\n}\n\n.opp-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n.opp-row-key {\n color: var(--opp-muted);\n flex-shrink: 0;\n}\n\n.opp-row-value-wrap {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n max-width: 70%;\n justify-content: flex-end;\n}\n\n.opp-row-value {\n font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, monospace;\n font-size: 12px;\n font-weight: 500;\n text-align: right;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.opp-copy {\n flex-shrink: 0;\n width: 22px;\n height: 22px;\n padding: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n border: 1px solid var(--opp-reject-border);\n background: var(--opp-bg);\n color: var(--opp-fg);\n cursor: pointer;\n}\n\n.opp-copy:hover {\n border-color: var(--opp-accent);\n color: var(--opp-accent);\n}\n\n.opp-fee-note {\n font-size: 11px;\n color: var(--opp-muted);\n line-height: 1.3;\n margin-top: -4px;\n}\n\n.opp-actions {\n display: flex;\n gap: 12px;\n padding: 20px 20px 12px;\n}\n\n.opp-button {\n flex: 1;\n padding: 0 16px;\n height: 48px;\n border-radius: 10px;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n transition: opacity 120ms ease;\n}\n\n.opp-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.opp-button-reject {\n background: var(--opp-reject-bg);\n color: var(--opp-reject-fg);\n border-color: var(--opp-reject-border);\n}\n\n.opp-button-approve {\n background: var(--opp-approve-bg);\n color: var(--opp-approve-fg);\n}\n\n.opp-footer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 8px 20px 16px;\n font-size: 11px;\n font-weight: 500;\n color: var(--opp-muted);\n}\n";
|
|
8
8
|
//# sourceMappingURL=styles.d.ts.map
|
package/dist/styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,g3MA+UxB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/permission-module-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40",
|
|
4
4
|
"description": "React component for the 1Sat permission module's prompt UX",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@1sat/permission-module": "0.0.
|
|
32
|
-
"@1sat/types": "0.0.
|
|
31
|
+
"@1sat/permission-module": "0.0.44",
|
|
32
|
+
"@1sat/types": "0.0.38"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "^18.0.0 || ^19.0.0"
|