@medialane/ui 0.259.0 → 0.261.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/components/action-button.cjs +7 -2
  2. package/dist/components/action-button.cjs.map +1 -1
  3. package/dist/components/action-button.d.cts +2 -1
  4. package/dist/components/action-button.d.ts +2 -1
  5. package/dist/components/action-button.js +7 -2
  6. package/dist/components/action-button.js.map +1 -1
  7. package/dist/components/activities-feed.cjs +5 -1
  8. package/dist/components/activities-feed.cjs.map +1 -1
  9. package/dist/components/activities-feed.js +5 -1
  10. package/dist/components/activities-feed.js.map +1 -1
  11. package/dist/components/activity-feed-shell.cjs +3 -1
  12. package/dist/components/activity-feed-shell.cjs.map +1 -1
  13. package/dist/components/activity-feed-shell.js +3 -1
  14. package/dist/components/activity-feed-shell.js.map +1 -1
  15. package/dist/components/asset-access-cards.cjs +21 -33
  16. package/dist/components/asset-access-cards.cjs.map +1 -1
  17. package/dist/components/asset-access-cards.d.cts +3 -3
  18. package/dist/components/asset-access-cards.d.ts +3 -3
  19. package/dist/components/asset-access-cards.js +20 -32
  20. package/dist/components/asset-access-cards.js.map +1 -1
  21. package/dist/components/asset-marketplace-panel.cjs +44 -41
  22. package/dist/components/asset-marketplace-panel.cjs.map +1 -1
  23. package/dist/components/asset-marketplace-panel.js +45 -42
  24. package/dist/components/asset-marketplace-panel.js.map +1 -1
  25. package/dist/components/asset-overview-content.cjs +12 -1
  26. package/dist/components/asset-overview-content.cjs.map +1 -1
  27. package/dist/components/asset-overview-content.d.cts +3 -1
  28. package/dist/components/asset-overview-content.d.ts +3 -1
  29. package/dist/components/asset-overview-content.js +13 -2
  30. package/dist/components/asset-overview-content.js.map +1 -1
  31. package/dist/components/asset-page.cjs +8 -6
  32. package/dist/components/asset-page.cjs.map +1 -1
  33. package/dist/components/asset-page.js +8 -6
  34. package/dist/components/asset-page.js.map +1 -1
  35. package/dist/components/asset-top-sections.cjs +1 -9
  36. package/dist/components/asset-top-sections.cjs.map +1 -1
  37. package/dist/components/asset-top-sections.d.cts +1 -2
  38. package/dist/components/asset-top-sections.d.ts +1 -2
  39. package/dist/components/asset-top-sections.js +1 -9
  40. package/dist/components/asset-top-sections.js.map +1 -1
  41. package/dist/components/coins-explorer.cjs +5 -1
  42. package/dist/components/coins-explorer.cjs.map +1 -1
  43. package/dist/components/coins-explorer.js +6 -2
  44. package/dist/components/coins-explorer.js.map +1 -1
  45. package/dist/components/comments-section.cjs +2 -2
  46. package/dist/components/comments-section.cjs.map +1 -1
  47. package/dist/components/comments-section.js +2 -2
  48. package/dist/components/comments-section.js.map +1 -1
  49. package/dist/components/discover-community-section.cjs +5 -1
  50. package/dist/components/discover-community-section.cjs.map +1 -1
  51. package/dist/components/discover-community-section.js +5 -1
  52. package/dist/components/discover-community-section.js.map +1 -1
  53. package/dist/components/discover-feed-section.cjs +5 -1
  54. package/dist/components/discover-feed-section.cjs.map +1 -1
  55. package/dist/components/discover-feed-section.js +5 -1
  56. package/dist/components/discover-feed-section.js.map +1 -1
  57. package/dist/components/fast-mint/success-view.cjs +2 -2
  58. package/dist/components/fast-mint/success-view.cjs.map +1 -1
  59. package/dist/components/fast-mint/success-view.js +2 -2
  60. package/dist/components/fast-mint/success-view.js.map +1 -1
  61. package/dist/components/ip-type-page.cjs +3 -2
  62. package/dist/components/ip-type-page.cjs.map +1 -1
  63. package/dist/components/ip-type-page.js +3 -2
  64. package/dist/components/ip-type-page.js.map +1 -1
  65. package/dist/components/markdown-text.cjs +53 -0
  66. package/dist/components/markdown-text.cjs.map +1 -0
  67. package/dist/components/markdown-text.d.cts +7 -0
  68. package/dist/components/markdown-text.d.ts +7 -0
  69. package/dist/components/markdown-text.js +19 -0
  70. package/dist/components/markdown-text.js.map +1 -0
  71. package/dist/components/marketplace-dialog-primitives.cjs +1 -1
  72. package/dist/components/marketplace-dialog-primitives.cjs.map +1 -1
  73. package/dist/components/marketplace-dialog-primitives.js +1 -1
  74. package/dist/components/marketplace-dialog-primitives.js.map +1 -1
  75. package/dist/components/media-wallet/media-wallet-activity.cjs +5 -1
  76. package/dist/components/media-wallet/media-wallet-activity.cjs.map +1 -1
  77. package/dist/components/media-wallet/media-wallet-activity.js +5 -1
  78. package/dist/components/media-wallet/media-wallet-activity.js.map +1 -1
  79. package/dist/components/media-wallet/media-wallet-home.cjs +3 -2
  80. package/dist/components/media-wallet/media-wallet-home.cjs.map +1 -1
  81. package/dist/components/media-wallet/media-wallet-home.js +3 -2
  82. package/dist/components/media-wallet/media-wallet-home.js.map +1 -1
  83. package/dist/components/media-wallet/media-wallet-send.cjs +5 -2
  84. package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
  85. package/dist/components/media-wallet/media-wallet-send.js +5 -2
  86. package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
  87. package/dist/components/media-wallet/success-dialog.cjs +5 -11
  88. package/dist/components/media-wallet/success-dialog.cjs.map +1 -1
  89. package/dist/components/media-wallet/success-dialog.js +5 -11
  90. package/dist/components/media-wallet/success-dialog.js.map +1 -1
  91. package/dist/components/pop-claim-button.cjs +2 -2
  92. package/dist/components/pop-claim-button.cjs.map +1 -1
  93. package/dist/components/pop-claim-button.js +2 -2
  94. package/dist/components/pop-claim-button.js.map +1 -1
  95. package/dist/components/pop-manage-page.cjs +3 -2
  96. package/dist/components/pop-manage-page.cjs.map +1 -1
  97. package/dist/components/pop-manage-page.js +3 -2
  98. package/dist/components/pop-manage-page.js.map +1 -1
  99. package/dist/components/portfolio-sponsorships.cjs +14 -7
  100. package/dist/components/portfolio-sponsorships.cjs.map +1 -1
  101. package/dist/components/portfolio-sponsorships.js +14 -7
  102. package/dist/components/portfolio-sponsorships.js.map +1 -1
  103. package/dist/components/service-collections-page.cjs +2 -2
  104. package/dist/components/service-collections-page.cjs.map +1 -1
  105. package/dist/components/service-collections-page.d.cts +2 -2
  106. package/dist/components/service-collections-page.d.ts +2 -2
  107. package/dist/components/service-collections-page.js +2 -2
  108. package/dist/components/service-collections-page.js.map +1 -1
  109. package/dist/components/sponsorship-offer-page.cjs +4 -4
  110. package/dist/components/sponsorship-offer-page.cjs.map +1 -1
  111. package/dist/components/sponsorship-offer-page.js +4 -4
  112. package/dist/components/sponsorship-offer-page.js.map +1 -1
  113. package/dist/components/transaction-success.cjs +2 -5
  114. package/dist/components/transaction-success.cjs.map +1 -1
  115. package/dist/components/transaction-success.js +3 -6
  116. package/dist/components/transaction-success.js.map +1 -1
  117. package/dist/components/transfer-collection-ownership.cjs +2 -5
  118. package/dist/components/transfer-collection-ownership.cjs.map +1 -1
  119. package/dist/components/transfer-collection-ownership.js +2 -5
  120. package/dist/components/transfer-collection-ownership.js.map +1 -1
  121. package/dist/index.cjs +3 -0
  122. package/dist/index.cjs.map +1 -1
  123. package/dist/index.d.cts +1 -0
  124. package/dist/index.d.ts +1 -0
  125. package/dist/index.js +2 -0
  126. package/dist/index.js.map +1 -1
  127. package/dist/utils/empty-messages.cjs +62 -0
  128. package/dist/utils/empty-messages.cjs.map +1 -0
  129. package/dist/utils/empty-messages.d.cts +40 -0
  130. package/dist/utils/empty-messages.d.ts +40 -0
  131. package/dist/utils/empty-messages.js +38 -0
  132. package/dist/utils/empty-messages.js.map +1 -0
  133. package/dist/utils/success-messages.cjs +52 -0
  134. package/dist/utils/success-messages.cjs.map +1 -1
  135. package/dist/utils/success-messages.d.cts +27 -0
  136. package/dist/utils/success-messages.d.ts +27 -0
  137. package/dist/utils/success-messages.js +52 -0
  138. package/dist/utils/success-messages.js.map +1 -1
  139. package/package.json +3 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/media-wallet/media-wallet-send.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Account, CallData, cairo, validateAndParseAddress, type Call, type ProviderInterface } from \"starknet\";\nimport { parseAmount, formatAmount } from \"@medialane/sdk\";\nimport { ActionButton } from \"../action-button.js\";\nimport { CurrencyIcon } from \"../currency-icon.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useErc20Balance, useTokenBalance } from \"../../utils/media-wallet/use-erc20-balance.js\";\nimport { fmt, short } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { TrustNote } from \"./action-button.js\";\nimport { ActionModal, BusyOverlay } from \"./action-modal.js\";\nimport { CurrencySheet } from \"./currency-sheet.js\";\nimport { WALLET_TOKENS, type WalletToken } from \"../../utils/media-wallet/wallet-tokens.js\";\nimport { SuccessDialog } from \"./success-dialog.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { runIntentCalls } from \"../../utils/run-intent-calls.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\n\nfunction isValidStarknetAddress(address: string): boolean {\n try {\n validateAndParseAddress(address.trim());\n return true;\n } catch {\n return false;\n }\n}\n\nasync function estimateSendFee(provider: ProviderInterface, address: string, token: string, to: string, amountRaw: bigint) {\n const account = new Account({ provider, address, signer: \"0x1\", cairoVersion: \"1\" });\n const call: Call = {\n contractAddress: token,\n entrypoint: \"transfer\",\n calldata: CallData.compile({ recipient: to, amount: cairo.uint256(amountRaw) }),\n };\n const est = await account.estimateInvokeFee(call);\n return { feeRaw: est.overall_fee, unit: est.unit };\n}\n\nexport function MediaWalletSend({\n initialToken,\n onNavigate,\n onDone,\n}: {\n initialToken?: WalletToken;\n onNavigate: (view: MediaWalletView) => void;\n onDone: () => void;\n}) {\n const { useWalletSession, useWriteAction } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const { run, status, reset, error } = useWriteAction();\n\n const [currency, setCurrency] = useState<WalletToken>(initialToken ?? WALLET_TOKENS[0]);\n const [pickerOpen, setPickerOpen] = useState(false);\n const strk = useTokenBalance(\"STRK\", address);\n const eth = useTokenBalance(\"ETH\", address);\n const usdc = useTokenBalance(\"USDC\", address);\n const wbtc = useTokenBalance(\"WBTC\", address);\n \n const pinnedBalancesBySymbol: Record<string, bigint | null> = {\n STRK: strk.rawBalance, ETH: eth.rawBalance, USDC: usdc.rawBalance, WBTC: wbtc.rawBalance,\n };\n const { rawBalance: currencyBalance } = useErc20Balance(currency.address, address);\n\n const [to, setTo] = useState(\"\");\n const [amount, setAmount] = useState(\"\");\n const [txHash, setTxHash] = useState<string | null>(null);\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [fee, setFee] = useState<{ raw: bigint; unit: string } | null>(null);\n const [feeError, setFeeError] = useState<string | null>(null);\n\n const recipientValid = isValidStarknetAddress(to);\n let amountRaw: bigint | null;\n try {\n amountRaw = amount.trim() ? BigInt(parseAmount(amount.trim(), currency.decimals)) : null;\n } catch {\n amountRaw = null;\n }\n const amountOverBalance = amountRaw != null && currencyBalance != null && amountRaw > currencyBalance;\n const composeReady = recipientValid && amountRaw != null && amountRaw > 0n && !amountOverBalance;\n\n const pasteRecipient = async () => {\n try {\n const text = await navigator.clipboard.readText();\n if (text) setTo(text.trim());\n } catch {\n\n }\n };\n\n const setMax = () => {\n if (currencyBalance == null) return;\n setAmount(formatAmount(currencyBalance.toString(), currency.decimals));\n };\n\n const openReview = () => {\n if (!address || !composeReady || amountRaw == null) return;\n setFeeError(null);\n setFee(null);\n setConfirmOpen(true);\n estimateSendFee(getClient().provider, address, currency.address, to.trim(), amountRaw)\n .then((f) => setFee({ raw: f.feeRaw, unit: f.unit }))\n .catch((e) => setFeeError(describeError(e).message));\n };\n\n const send = async () => {\n if (!composeReady || amountRaw == null) return;\n setConfirmOpen(false);\n const dest = to.trim();\n const amt = amountRaw;\n await run(async (signer) => {\n const result = await runIntentCalls(signer, () =>\n getClient().api.intents.create(\"transfer-token\", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() }),\n );\n setTxHash(result.txHash);\n return result;\n });\n };\n\n return (\n <main className=\"flex flex-col gap-6 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Send</h1>\n </div>\n\n {error && (\n <div className=\"rounded-2xl border border-destructive/40 bg-destructive/10 p-3 text-xs leading-relaxed\">\n {error}\n </div>\n )}\n\n <div className=\"flex flex-col gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n value={to}\n onChange={(e) => setTo(e.target.value)}\n placeholder=\"Recipient 0x…\"\n spellCheck={false}\n className=\"w-0 flex-1 rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 font-mono text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n {to.trim() === \"\" && (\n <button\n onClick={pasteRecipient}\n className=\"shrink-0 rounded-2xl border border-border bg-foreground/[0.05] px-3 py-3 text-xs font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Paste\n </button>\n )}\n </div>\n {to.trim() !== \"\" && !recipientValid && (\n <p className=\"mt-1.5 px-1 text-xs text-destructive\">Not a valid Starknet address.</p>\n )}\n </div>\n\n <div>\n <div className=\"relative\">\n <input\n value={amount}\n onChange={(e) => setAmount(e.target.value.replace(/[^0-9.]/g, \"\"))}\n placeholder=\"0.00\"\n inputMode=\"decimal\"\n className=\"w-full rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 pr-36 text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n <div className=\"absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1.5\">\n <button\n onClick={setMax}\n className=\"rounded-full bg-foreground/[0.06] px-2 py-1 text-2xs font-bold text-muted-foreground transition-colors hover:text-foreground\"\n >\n MAX\n </button>\n <button\n onClick={() => setPickerOpen(true)}\n className=\"flex items-center gap-1.5 rounded-full bg-foreground/[0.06] px-2.5 py-1 text-xs font-semibold\"\n >\n <CurrencyIcon symbol={currency.symbol} size={16} /> {currency.symbol}\n </button>\n </div>\n </div>\n <div className=\"mt-1.5 flex items-center justify-between px-1\">\n <span className=\"text-xs text-muted-foreground\">\n Balance: {currencyBalance != null ? fmt(currencyBalance, currency.decimals) : \"…\"}\n </span>\n {amountOverBalance && <span className=\"text-xs text-destructive\">Amount exceeds balance.</span>}\n </div>\n </div>\n\n <ActionButton\n action=\"offer\"\n big\n onClick={openReview}\n disabled={status === \"processing\" || !composeReady}\n className=\"mt-1 w-full disabled:pointer-events-none disabled:opacity-40\"\n >\n Review Transfer\n </ActionButton>\n <TrustNote>Gas paid from your balance. Transfers are permanent and recorded onchain.</TrustNote>\n </div>\n\n {pickerOpen && (\n <CurrencySheet\n title=\"Choose currency\"\n tokens={WALLET_TOKENS}\n balances={pinnedBalancesBySymbol}\n onSelect={(t) => {\n setCurrency(t);\n setPickerOpen(false);\n }}\n onClose={() => setPickerOpen(false)}\n />\n )}\n\n {confirmOpen && (\n <ActionModal title=\"Review Transfer\" onClose={() => setConfirmOpen(false)}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"grid h-10 w-10 shrink-0 place-items-center rounded-full bg-foreground/[0.06]\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\" />\n </svg>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-semibold\">Send</div>\n <div className=\"truncate font-mono text-xs text-muted-foreground\">To: {short(to.trim())}</div>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-2xl bg-foreground/[0.05] p-4\">\n <CurrencyIcon symbol={currency.symbol} size={28} />\n <div className=\"min-w-0 flex-1 font-semibold\">{currency.symbol}</div>\n <div className=\"text-right font-semibold tabular-nums\">\n −{amount.trim()} {currency.symbol}\n </div>\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Amount</span>\n <span className=\"font-medium\">{amount.trim()} {currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Recipient</span>\n <span className=\"font-mono font-medium\">{short(to.trim())}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Contract</span>\n <span className=\"font-medium\">{currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Call</span>\n <span className=\"font-medium underline\">transfer</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-2xl border border-border px-4 py-3 text-sm\">\n <span className=\"text-muted-foreground\">Estimated fee</span>\n <span className=\"font-medium\">\n {feeError ? \"Unavailable\" : fee ? `${fmt(fee.raw, 18, 6)} ${fee.unit === \"FRI\" ? \"STRK\" : \"ETH\"}` : \"Estimating…\"}\n </span>\n </div>\n {feeError && <p className=\"px-1 text-xs text-destructive\">Fee estimate failed: {feeError}</p>}\n\n <div className=\"flex gap-3\">\n <button\n onClick={() => setConfirmOpen(false)}\n className=\"flex-1 rounded-2xl border border-border py-3 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Reject\n </button>\n <ActionButton action=\"offer\" big onClick={send} className=\"flex-1\">\n Confirm\n </ActionButton>\n </div>\n </div>\n </ActionModal>\n )}\n\n {status === \"processing\" && <BusyOverlay label=\"Signing & sending…\" />}\n {status === \"success\" && txHash && (\n <SuccessDialog\n title=\"Sent\"\n message={`${amount.trim()} ${currency.symbol} is on its way.`}\n txHash={txHash}\n onClose={() => {\n reset();\n onDone();\n }}\n />\n )}\n </main>\n );\n}\n"],"mappings":"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","names":["import_action_button"]}
1
+ {"version":3,"sources":["../../../src/components/media-wallet/media-wallet-send.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Account, CallData, cairo, validateAndParseAddress, type Call, type ProviderInterface } from \"starknet\";\nimport { parseAmount, formatAmount } from \"@medialane/sdk\";\nimport { ActionButton } from \"../action-button.js\";\nimport { CurrencyIcon } from \"../currency-icon.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useErc20Balance, useTokenBalance } from \"../../utils/media-wallet/use-erc20-balance.js\";\nimport { fmt, short } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { TrustNote } from \"./action-button.js\";\nimport { ActionModal, BusyOverlay } from \"./action-modal.js\";\nimport { CurrencySheet } from \"./currency-sheet.js\";\nimport { WALLET_TOKENS, type WalletToken } from \"../../utils/media-wallet/wallet-tokens.js\";\nimport { SuccessDialog } from \"./success-dialog.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { runIntentCalls } from \"../../utils/run-intent-calls.js\";\nimport { successMessages } from \"../../utils/success-messages.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\n\nfunction isValidStarknetAddress(address: string): boolean {\n try {\n validateAndParseAddress(address.trim());\n return true;\n } catch {\n return false;\n }\n}\n\nasync function estimateSendFee(provider: ProviderInterface, address: string, token: string, to: string, amountRaw: bigint) {\n const account = new Account({ provider, address, signer: \"0x1\", cairoVersion: \"1\" });\n const call: Call = {\n contractAddress: token,\n entrypoint: \"transfer\",\n calldata: CallData.compile({ recipient: to, amount: cairo.uint256(amountRaw) }),\n };\n const est = await account.estimateInvokeFee(call);\n return { feeRaw: est.overall_fee, unit: est.unit };\n}\n\nexport function MediaWalletSend({\n initialToken,\n onNavigate,\n onDone,\n}: {\n initialToken?: WalletToken;\n onNavigate: (view: MediaWalletView) => void;\n onDone: () => void;\n}) {\n const { useWalletSession, useWriteAction } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const { run, status, reset, error } = useWriteAction();\n\n const [currency, setCurrency] = useState<WalletToken>(initialToken ?? WALLET_TOKENS[0]);\n const [pickerOpen, setPickerOpen] = useState(false);\n const strk = useTokenBalance(\"STRK\", address);\n const eth = useTokenBalance(\"ETH\", address);\n const usdc = useTokenBalance(\"USDC\", address);\n const wbtc = useTokenBalance(\"WBTC\", address);\n \n const pinnedBalancesBySymbol: Record<string, bigint | null> = {\n STRK: strk.rawBalance, ETH: eth.rawBalance, USDC: usdc.rawBalance, WBTC: wbtc.rawBalance,\n };\n const { rawBalance: currencyBalance } = useErc20Balance(currency.address, address);\n\n const [to, setTo] = useState(\"\");\n const [amount, setAmount] = useState(\"\");\n const [txHash, setTxHash] = useState<string | null>(null);\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [fee, setFee] = useState<{ raw: bigint; unit: string } | null>(null);\n const [feeError, setFeeError] = useState<string | null>(null);\n\n const recipientValid = isValidStarknetAddress(to);\n const sentMessage = successMessages.sent({ amount: amount.trim(), symbol: currency.symbol, to: shortenAddress(to.trim()) });\n let amountRaw: bigint | null;\n try {\n amountRaw = amount.trim() ? BigInt(parseAmount(amount.trim(), currency.decimals)) : null;\n } catch {\n amountRaw = null;\n }\n const amountOverBalance = amountRaw != null && currencyBalance != null && amountRaw > currencyBalance;\n const composeReady = recipientValid && amountRaw != null && amountRaw > 0n && !amountOverBalance;\n\n const pasteRecipient = async () => {\n try {\n const text = await navigator.clipboard.readText();\n if (text) setTo(text.trim());\n } catch {\n\n }\n };\n\n const setMax = () => {\n if (currencyBalance == null) return;\n setAmount(formatAmount(currencyBalance.toString(), currency.decimals));\n };\n\n const openReview = () => {\n if (!address || !composeReady || amountRaw == null) return;\n setFeeError(null);\n setFee(null);\n setConfirmOpen(true);\n estimateSendFee(getClient().provider, address, currency.address, to.trim(), amountRaw)\n .then((f) => setFee({ raw: f.feeRaw, unit: f.unit }))\n .catch((e) => setFeeError(describeError(e).message));\n };\n\n const send = async () => {\n if (!composeReady || amountRaw == null) return;\n setConfirmOpen(false);\n const dest = to.trim();\n const amt = amountRaw;\n await run(async (signer) => {\n const result = await runIntentCalls(signer, () =>\n getClient().api.intents.create(\"transfer-token\", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() }),\n );\n setTxHash(result.txHash);\n return result;\n });\n };\n\n return (\n <main className=\"flex flex-col gap-6 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Send</h1>\n </div>\n\n {error && (\n <div className=\"rounded-2xl border border-destructive/40 bg-destructive/10 p-3 text-xs leading-relaxed\">\n {error}\n </div>\n )}\n\n <div className=\"flex flex-col gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n value={to}\n onChange={(e) => setTo(e.target.value)}\n placeholder=\"Recipient 0x…\"\n spellCheck={false}\n className=\"w-0 flex-1 rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 font-mono text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n {to.trim() === \"\" && (\n <button\n onClick={pasteRecipient}\n className=\"shrink-0 rounded-2xl border border-border bg-foreground/[0.05] px-3 py-3 text-xs font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Paste\n </button>\n )}\n </div>\n {to.trim() !== \"\" && !recipientValid && (\n <p className=\"mt-1.5 px-1 text-xs text-destructive\">Not a valid Starknet address.</p>\n )}\n </div>\n\n <div>\n <div className=\"relative\">\n <input\n value={amount}\n onChange={(e) => setAmount(e.target.value.replace(/[^0-9.]/g, \"\"))}\n placeholder=\"0.00\"\n inputMode=\"decimal\"\n className=\"w-full rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 pr-36 text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n <div className=\"absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1.5\">\n <button\n onClick={setMax}\n className=\"rounded-full bg-foreground/[0.06] px-2 py-1 text-2xs font-bold text-muted-foreground transition-colors hover:text-foreground\"\n >\n MAX\n </button>\n <button\n onClick={() => setPickerOpen(true)}\n className=\"flex items-center gap-1.5 rounded-full bg-foreground/[0.06] px-2.5 py-1 text-xs font-semibold\"\n >\n <CurrencyIcon symbol={currency.symbol} size={16} /> {currency.symbol}\n </button>\n </div>\n </div>\n <div className=\"mt-1.5 flex items-center justify-between px-1\">\n <span className=\"text-xs text-muted-foreground\">\n Balance: {currencyBalance != null ? fmt(currencyBalance, currency.decimals) : \"…\"}\n </span>\n {amountOverBalance && <span className=\"text-xs text-destructive\">Amount exceeds balance.</span>}\n </div>\n </div>\n\n <ActionButton\n action=\"offer\"\n big\n onClick={openReview}\n disabled={status === \"processing\" || !composeReady}\n className=\"mt-1 w-full disabled:pointer-events-none disabled:opacity-40\"\n >\n Review Transfer\n </ActionButton>\n <TrustNote>Gas paid from your balance. Transfers are permanent and recorded onchain.</TrustNote>\n </div>\n\n {pickerOpen && (\n <CurrencySheet\n title=\"Choose currency\"\n tokens={WALLET_TOKENS}\n balances={pinnedBalancesBySymbol}\n onSelect={(t) => {\n setCurrency(t);\n setPickerOpen(false);\n }}\n onClose={() => setPickerOpen(false)}\n />\n )}\n\n {confirmOpen && (\n <ActionModal title=\"Review Transfer\" onClose={() => setConfirmOpen(false)}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"grid h-10 w-10 shrink-0 place-items-center rounded-full bg-foreground/[0.06]\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\" />\n </svg>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-semibold\">Send</div>\n <div className=\"truncate font-mono text-xs text-muted-foreground\">To: {short(to.trim())}</div>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-2xl bg-foreground/[0.05] p-4\">\n <CurrencyIcon symbol={currency.symbol} size={28} />\n <div className=\"min-w-0 flex-1 font-semibold\">{currency.symbol}</div>\n <div className=\"text-right font-semibold tabular-nums\">\n −{amount.trim()} {currency.symbol}\n </div>\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Amount</span>\n <span className=\"font-medium\">{amount.trim()} {currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Recipient</span>\n <span className=\"font-mono font-medium\">{short(to.trim())}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Contract</span>\n <span className=\"font-medium\">{currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Call</span>\n <span className=\"font-medium underline\">transfer</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-2xl border border-border px-4 py-3 text-sm\">\n <span className=\"text-muted-foreground\">Estimated fee</span>\n <span className=\"font-medium\">\n {feeError ? \"Unavailable\" : fee ? `${fmt(fee.raw, 18, 6)} ${fee.unit === \"FRI\" ? \"STRK\" : \"ETH\"}` : \"Estimating…\"}\n </span>\n </div>\n {feeError && <p className=\"px-1 text-xs text-destructive\">Fee estimate failed: {feeError}</p>}\n\n <div className=\"flex gap-3\">\n <button\n onClick={() => setConfirmOpen(false)}\n className=\"flex-1 rounded-2xl border border-border py-3 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Reject\n </button>\n <ActionButton action=\"offer\" big onClick={send} className=\"flex-1\">\n Confirm\n </ActionButton>\n </div>\n </div>\n </ActionModal>\n )}\n\n {status === \"processing\" && <BusyOverlay label=\"Signing & sending…\" />}\n {status === \"success\" && txHash && (\n <SuccessDialog\n title={sentMessage.title}\n message={sentMessage.description}\n txHash={txHash}\n onClose={() => {\n reset();\n onDone();\n }}\n />\n )}\n </main>\n );\n}\n"],"mappings":"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","names":["import_action_button"]}
@@ -15,7 +15,9 @@ import { CurrencySheet } from "./currency-sheet.js";
15
15
  import { WALLET_TOKENS } from "../../utils/media-wallet/wallet-tokens.js";
16
16
  import { SuccessDialog } from "./success-dialog.js";
17
17
  import { useMediaWalletApp } from "./types.js";
18
+ import { shortenAddress } from "../../utils/address.js";
18
19
  import { runIntentCalls } from "../../utils/run-intent-calls.js";
20
+ import { successMessages } from "../../utils/success-messages.js";
19
21
  import { useMedialaneApp } from "../medialane-app.js";
20
22
  function isValidStarknetAddress(address) {
21
23
  try {
@@ -64,6 +66,7 @@ function MediaWalletSend({
64
66
  const [fee, setFee] = useState(null);
65
67
  const [feeError, setFeeError] = useState(null);
66
68
  const recipientValid = isValidStarknetAddress(to);
69
+ const sentMessage = successMessages.sent({ amount: amount.trim(), symbol: currency.symbol, to: shortenAddress(to.trim()) });
67
70
  let amountRaw;
68
71
  try {
69
72
  amountRaw = amount.trim() ? BigInt(parseAmount(amount.trim(), currency.decimals)) : null;
@@ -270,8 +273,8 @@ function MediaWalletSend({
270
273
  status === "success" && txHash && /* @__PURE__ */ jsx(
271
274
  SuccessDialog,
272
275
  {
273
- title: "Sent",
274
- message: `${amount.trim()} ${currency.symbol} is on its way.`,
276
+ title: sentMessage.title,
277
+ message: sentMessage.description,
275
278
  txHash,
276
279
  onClose: () => {
277
280
  reset();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/media-wallet/media-wallet-send.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Account, CallData, cairo, validateAndParseAddress, type Call, type ProviderInterface } from \"starknet\";\nimport { parseAmount, formatAmount } from \"@medialane/sdk\";\nimport { ActionButton } from \"../action-button.js\";\nimport { CurrencyIcon } from \"../currency-icon.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useErc20Balance, useTokenBalance } from \"../../utils/media-wallet/use-erc20-balance.js\";\nimport { fmt, short } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { TrustNote } from \"./action-button.js\";\nimport { ActionModal, BusyOverlay } from \"./action-modal.js\";\nimport { CurrencySheet } from \"./currency-sheet.js\";\nimport { WALLET_TOKENS, type WalletToken } from \"../../utils/media-wallet/wallet-tokens.js\";\nimport { SuccessDialog } from \"./success-dialog.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { runIntentCalls } from \"../../utils/run-intent-calls.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\n\nfunction isValidStarknetAddress(address: string): boolean {\n try {\n validateAndParseAddress(address.trim());\n return true;\n } catch {\n return false;\n }\n}\n\nasync function estimateSendFee(provider: ProviderInterface, address: string, token: string, to: string, amountRaw: bigint) {\n const account = new Account({ provider, address, signer: \"0x1\", cairoVersion: \"1\" });\n const call: Call = {\n contractAddress: token,\n entrypoint: \"transfer\",\n calldata: CallData.compile({ recipient: to, amount: cairo.uint256(amountRaw) }),\n };\n const est = await account.estimateInvokeFee(call);\n return { feeRaw: est.overall_fee, unit: est.unit };\n}\n\nexport function MediaWalletSend({\n initialToken,\n onNavigate,\n onDone,\n}: {\n initialToken?: WalletToken;\n onNavigate: (view: MediaWalletView) => void;\n onDone: () => void;\n}) {\n const { useWalletSession, useWriteAction } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const { run, status, reset, error } = useWriteAction();\n\n const [currency, setCurrency] = useState<WalletToken>(initialToken ?? WALLET_TOKENS[0]);\n const [pickerOpen, setPickerOpen] = useState(false);\n const strk = useTokenBalance(\"STRK\", address);\n const eth = useTokenBalance(\"ETH\", address);\n const usdc = useTokenBalance(\"USDC\", address);\n const wbtc = useTokenBalance(\"WBTC\", address);\n \n const pinnedBalancesBySymbol: Record<string, bigint | null> = {\n STRK: strk.rawBalance, ETH: eth.rawBalance, USDC: usdc.rawBalance, WBTC: wbtc.rawBalance,\n };\n const { rawBalance: currencyBalance } = useErc20Balance(currency.address, address);\n\n const [to, setTo] = useState(\"\");\n const [amount, setAmount] = useState(\"\");\n const [txHash, setTxHash] = useState<string | null>(null);\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [fee, setFee] = useState<{ raw: bigint; unit: string } | null>(null);\n const [feeError, setFeeError] = useState<string | null>(null);\n\n const recipientValid = isValidStarknetAddress(to);\n let amountRaw: bigint | null;\n try {\n amountRaw = amount.trim() ? BigInt(parseAmount(amount.trim(), currency.decimals)) : null;\n } catch {\n amountRaw = null;\n }\n const amountOverBalance = amountRaw != null && currencyBalance != null && amountRaw > currencyBalance;\n const composeReady = recipientValid && amountRaw != null && amountRaw > 0n && !amountOverBalance;\n\n const pasteRecipient = async () => {\n try {\n const text = await navigator.clipboard.readText();\n if (text) setTo(text.trim());\n } catch {\n\n }\n };\n\n const setMax = () => {\n if (currencyBalance == null) return;\n setAmount(formatAmount(currencyBalance.toString(), currency.decimals));\n };\n\n const openReview = () => {\n if (!address || !composeReady || amountRaw == null) return;\n setFeeError(null);\n setFee(null);\n setConfirmOpen(true);\n estimateSendFee(getClient().provider, address, currency.address, to.trim(), amountRaw)\n .then((f) => setFee({ raw: f.feeRaw, unit: f.unit }))\n .catch((e) => setFeeError(describeError(e).message));\n };\n\n const send = async () => {\n if (!composeReady || amountRaw == null) return;\n setConfirmOpen(false);\n const dest = to.trim();\n const amt = amountRaw;\n await run(async (signer) => {\n const result = await runIntentCalls(signer, () =>\n getClient().api.intents.create(\"transfer-token\", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() }),\n );\n setTxHash(result.txHash);\n return result;\n });\n };\n\n return (\n <main className=\"flex flex-col gap-6 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Send</h1>\n </div>\n\n {error && (\n <div className=\"rounded-2xl border border-destructive/40 bg-destructive/10 p-3 text-xs leading-relaxed\">\n {error}\n </div>\n )}\n\n <div className=\"flex flex-col gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n value={to}\n onChange={(e) => setTo(e.target.value)}\n placeholder=\"Recipient 0x…\"\n spellCheck={false}\n className=\"w-0 flex-1 rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 font-mono text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n {to.trim() === \"\" && (\n <button\n onClick={pasteRecipient}\n className=\"shrink-0 rounded-2xl border border-border bg-foreground/[0.05] px-3 py-3 text-xs font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Paste\n </button>\n )}\n </div>\n {to.trim() !== \"\" && !recipientValid && (\n <p className=\"mt-1.5 px-1 text-xs text-destructive\">Not a valid Starknet address.</p>\n )}\n </div>\n\n <div>\n <div className=\"relative\">\n <input\n value={amount}\n onChange={(e) => setAmount(e.target.value.replace(/[^0-9.]/g, \"\"))}\n placeholder=\"0.00\"\n inputMode=\"decimal\"\n className=\"w-full rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 pr-36 text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n <div className=\"absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1.5\">\n <button\n onClick={setMax}\n className=\"rounded-full bg-foreground/[0.06] px-2 py-1 text-2xs font-bold text-muted-foreground transition-colors hover:text-foreground\"\n >\n MAX\n </button>\n <button\n onClick={() => setPickerOpen(true)}\n className=\"flex items-center gap-1.5 rounded-full bg-foreground/[0.06] px-2.5 py-1 text-xs font-semibold\"\n >\n <CurrencyIcon symbol={currency.symbol} size={16} /> {currency.symbol}\n </button>\n </div>\n </div>\n <div className=\"mt-1.5 flex items-center justify-between px-1\">\n <span className=\"text-xs text-muted-foreground\">\n Balance: {currencyBalance != null ? fmt(currencyBalance, currency.decimals) : \"…\"}\n </span>\n {amountOverBalance && <span className=\"text-xs text-destructive\">Amount exceeds balance.</span>}\n </div>\n </div>\n\n <ActionButton\n action=\"offer\"\n big\n onClick={openReview}\n disabled={status === \"processing\" || !composeReady}\n className=\"mt-1 w-full disabled:pointer-events-none disabled:opacity-40\"\n >\n Review Transfer\n </ActionButton>\n <TrustNote>Gas paid from your balance. Transfers are permanent and recorded onchain.</TrustNote>\n </div>\n\n {pickerOpen && (\n <CurrencySheet\n title=\"Choose currency\"\n tokens={WALLET_TOKENS}\n balances={pinnedBalancesBySymbol}\n onSelect={(t) => {\n setCurrency(t);\n setPickerOpen(false);\n }}\n onClose={() => setPickerOpen(false)}\n />\n )}\n\n {confirmOpen && (\n <ActionModal title=\"Review Transfer\" onClose={() => setConfirmOpen(false)}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"grid h-10 w-10 shrink-0 place-items-center rounded-full bg-foreground/[0.06]\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\" />\n </svg>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-semibold\">Send</div>\n <div className=\"truncate font-mono text-xs text-muted-foreground\">To: {short(to.trim())}</div>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-2xl bg-foreground/[0.05] p-4\">\n <CurrencyIcon symbol={currency.symbol} size={28} />\n <div className=\"min-w-0 flex-1 font-semibold\">{currency.symbol}</div>\n <div className=\"text-right font-semibold tabular-nums\">\n −{amount.trim()} {currency.symbol}\n </div>\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Amount</span>\n <span className=\"font-medium\">{amount.trim()} {currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Recipient</span>\n <span className=\"font-mono font-medium\">{short(to.trim())}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Contract</span>\n <span className=\"font-medium\">{currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Call</span>\n <span className=\"font-medium underline\">transfer</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-2xl border border-border px-4 py-3 text-sm\">\n <span className=\"text-muted-foreground\">Estimated fee</span>\n <span className=\"font-medium\">\n {feeError ? \"Unavailable\" : fee ? `${fmt(fee.raw, 18, 6)} ${fee.unit === \"FRI\" ? \"STRK\" : \"ETH\"}` : \"Estimating…\"}\n </span>\n </div>\n {feeError && <p className=\"px-1 text-xs text-destructive\">Fee estimate failed: {feeError}</p>}\n\n <div className=\"flex gap-3\">\n <button\n onClick={() => setConfirmOpen(false)}\n className=\"flex-1 rounded-2xl border border-border py-3 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Reject\n </button>\n <ActionButton action=\"offer\" big onClick={send} className=\"flex-1\">\n Confirm\n </ActionButton>\n </div>\n </div>\n </ActionModal>\n )}\n\n {status === \"processing\" && <BusyOverlay label=\"Signing & sending…\" />}\n {status === \"success\" && txHash && (\n <SuccessDialog\n title=\"Sent\"\n message={`${amount.trim()} ${currency.symbol} is on its way.`}\n txHash={txHash}\n onClose={() => {\n reset();\n onDone();\n }}\n />\n )}\n </main>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/media-wallet/media-wallet-send.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Account, CallData, cairo, validateAndParseAddress, type Call, type ProviderInterface } from \"starknet\";\nimport { parseAmount, formatAmount } from \"@medialane/sdk\";\nimport { ActionButton } from \"../action-button.js\";\nimport { CurrencyIcon } from \"../currency-icon.js\";\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useErc20Balance, useTokenBalance } from \"../../utils/media-wallet/use-erc20-balance.js\";\nimport { fmt, short } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { TrustNote } from \"./action-button.js\";\nimport { ActionModal, BusyOverlay } from \"./action-modal.js\";\nimport { CurrencySheet } from \"./currency-sheet.js\";\nimport { WALLET_TOKENS, type WalletToken } from \"../../utils/media-wallet/wallet-tokens.js\";\nimport { SuccessDialog } from \"./success-dialog.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { runIntentCalls } from \"../../utils/run-intent-calls.js\";\nimport { successMessages } from \"../../utils/success-messages.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\n\nfunction isValidStarknetAddress(address: string): boolean {\n try {\n validateAndParseAddress(address.trim());\n return true;\n } catch {\n return false;\n }\n}\n\nasync function estimateSendFee(provider: ProviderInterface, address: string, token: string, to: string, amountRaw: bigint) {\n const account = new Account({ provider, address, signer: \"0x1\", cairoVersion: \"1\" });\n const call: Call = {\n contractAddress: token,\n entrypoint: \"transfer\",\n calldata: CallData.compile({ recipient: to, amount: cairo.uint256(amountRaw) }),\n };\n const est = await account.estimateInvokeFee(call);\n return { feeRaw: est.overall_fee, unit: est.unit };\n}\n\nexport function MediaWalletSend({\n initialToken,\n onNavigate,\n onDone,\n}: {\n initialToken?: WalletToken;\n onNavigate: (view: MediaWalletView) => void;\n onDone: () => void;\n}) {\n const { useWalletSession, useWriteAction } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const { run, status, reset, error } = useWriteAction();\n\n const [currency, setCurrency] = useState<WalletToken>(initialToken ?? WALLET_TOKENS[0]);\n const [pickerOpen, setPickerOpen] = useState(false);\n const strk = useTokenBalance(\"STRK\", address);\n const eth = useTokenBalance(\"ETH\", address);\n const usdc = useTokenBalance(\"USDC\", address);\n const wbtc = useTokenBalance(\"WBTC\", address);\n \n const pinnedBalancesBySymbol: Record<string, bigint | null> = {\n STRK: strk.rawBalance, ETH: eth.rawBalance, USDC: usdc.rawBalance, WBTC: wbtc.rawBalance,\n };\n const { rawBalance: currencyBalance } = useErc20Balance(currency.address, address);\n\n const [to, setTo] = useState(\"\");\n const [amount, setAmount] = useState(\"\");\n const [txHash, setTxHash] = useState<string | null>(null);\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n const [fee, setFee] = useState<{ raw: bigint; unit: string } | null>(null);\n const [feeError, setFeeError] = useState<string | null>(null);\n\n const recipientValid = isValidStarknetAddress(to);\n const sentMessage = successMessages.sent({ amount: amount.trim(), symbol: currency.symbol, to: shortenAddress(to.trim()) });\n let amountRaw: bigint | null;\n try {\n amountRaw = amount.trim() ? BigInt(parseAmount(amount.trim(), currency.decimals)) : null;\n } catch {\n amountRaw = null;\n }\n const amountOverBalance = amountRaw != null && currencyBalance != null && amountRaw > currencyBalance;\n const composeReady = recipientValid && amountRaw != null && amountRaw > 0n && !amountOverBalance;\n\n const pasteRecipient = async () => {\n try {\n const text = await navigator.clipboard.readText();\n if (text) setTo(text.trim());\n } catch {\n\n }\n };\n\n const setMax = () => {\n if (currencyBalance == null) return;\n setAmount(formatAmount(currencyBalance.toString(), currency.decimals));\n };\n\n const openReview = () => {\n if (!address || !composeReady || amountRaw == null) return;\n setFeeError(null);\n setFee(null);\n setConfirmOpen(true);\n estimateSendFee(getClient().provider, address, currency.address, to.trim(), amountRaw)\n .then((f) => setFee({ raw: f.feeRaw, unit: f.unit }))\n .catch((e) => setFeeError(describeError(e).message));\n };\n\n const send = async () => {\n if (!composeReady || amountRaw == null) return;\n setConfirmOpen(false);\n const dest = to.trim();\n const amt = amountRaw;\n await run(async (signer) => {\n const result = await runIntentCalls(signer, () =>\n getClient().api.intents.create(\"transfer-token\", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() }),\n );\n setTxHash(result.txHash);\n return result;\n });\n };\n\n return (\n <main className=\"flex flex-col gap-6 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Send</h1>\n </div>\n\n {error && (\n <div className=\"rounded-2xl border border-destructive/40 bg-destructive/10 p-3 text-xs leading-relaxed\">\n {error}\n </div>\n )}\n\n <div className=\"flex flex-col gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n value={to}\n onChange={(e) => setTo(e.target.value)}\n placeholder=\"Recipient 0x…\"\n spellCheck={false}\n className=\"w-0 flex-1 rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 font-mono text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n {to.trim() === \"\" && (\n <button\n onClick={pasteRecipient}\n className=\"shrink-0 rounded-2xl border border-border bg-foreground/[0.05] px-3 py-3 text-xs font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Paste\n </button>\n )}\n </div>\n {to.trim() !== \"\" && !recipientValid && (\n <p className=\"mt-1.5 px-1 text-xs text-destructive\">Not a valid Starknet address.</p>\n )}\n </div>\n\n <div>\n <div className=\"relative\">\n <input\n value={amount}\n onChange={(e) => setAmount(e.target.value.replace(/[^0-9.]/g, \"\"))}\n placeholder=\"0.00\"\n inputMode=\"decimal\"\n className=\"w-full rounded-2xl border border-border bg-foreground/[0.05] px-4 py-3 pr-36 text-sm outline-none transition-colors focus:border-brand-purple\"\n />\n <div className=\"absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1.5\">\n <button\n onClick={setMax}\n className=\"rounded-full bg-foreground/[0.06] px-2 py-1 text-2xs font-bold text-muted-foreground transition-colors hover:text-foreground\"\n >\n MAX\n </button>\n <button\n onClick={() => setPickerOpen(true)}\n className=\"flex items-center gap-1.5 rounded-full bg-foreground/[0.06] px-2.5 py-1 text-xs font-semibold\"\n >\n <CurrencyIcon symbol={currency.symbol} size={16} /> {currency.symbol}\n </button>\n </div>\n </div>\n <div className=\"mt-1.5 flex items-center justify-between px-1\">\n <span className=\"text-xs text-muted-foreground\">\n Balance: {currencyBalance != null ? fmt(currencyBalance, currency.decimals) : \"…\"}\n </span>\n {amountOverBalance && <span className=\"text-xs text-destructive\">Amount exceeds balance.</span>}\n </div>\n </div>\n\n <ActionButton\n action=\"offer\"\n big\n onClick={openReview}\n disabled={status === \"processing\" || !composeReady}\n className=\"mt-1 w-full disabled:pointer-events-none disabled:opacity-40\"\n >\n Review Transfer\n </ActionButton>\n <TrustNote>Gas paid from your balance. Transfers are permanent and recorded onchain.</TrustNote>\n </div>\n\n {pickerOpen && (\n <CurrencySheet\n title=\"Choose currency\"\n tokens={WALLET_TOKENS}\n balances={pinnedBalancesBySymbol}\n onSelect={(t) => {\n setCurrency(t);\n setPickerOpen(false);\n }}\n onClose={() => setPickerOpen(false)}\n />\n )}\n\n {confirmOpen && (\n <ActionModal title=\"Review Transfer\" onClose={() => setConfirmOpen(false)}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"grid h-10 w-10 shrink-0 place-items-center rounded-full bg-foreground/[0.06]\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\" />\n </svg>\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-semibold\">Send</div>\n <div className=\"truncate font-mono text-xs text-muted-foreground\">To: {short(to.trim())}</div>\n </div>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-2xl bg-foreground/[0.05] p-4\">\n <CurrencyIcon symbol={currency.symbol} size={28} />\n <div className=\"min-w-0 flex-1 font-semibold\">{currency.symbol}</div>\n <div className=\"text-right font-semibold tabular-nums\">\n −{amount.trim()} {currency.symbol}\n </div>\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Amount</span>\n <span className=\"font-medium\">{amount.trim()} {currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Recipient</span>\n <span className=\"font-mono font-medium\">{short(to.trim())}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Contract</span>\n <span className=\"font-medium\">{currency.symbol}</span>\n </div>\n <div className=\"flex items-center justify-between py-3 text-sm\">\n <span className=\"text-muted-foreground\">Call</span>\n <span className=\"font-medium underline\">transfer</span>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between rounded-2xl border border-border px-4 py-3 text-sm\">\n <span className=\"text-muted-foreground\">Estimated fee</span>\n <span className=\"font-medium\">\n {feeError ? \"Unavailable\" : fee ? `${fmt(fee.raw, 18, 6)} ${fee.unit === \"FRI\" ? \"STRK\" : \"ETH\"}` : \"Estimating…\"}\n </span>\n </div>\n {feeError && <p className=\"px-1 text-xs text-destructive\">Fee estimate failed: {feeError}</p>}\n\n <div className=\"flex gap-3\">\n <button\n onClick={() => setConfirmOpen(false)}\n className=\"flex-1 rounded-2xl border border-border py-3 text-sm font-semibold text-muted-foreground transition-colors hover:text-foreground\"\n >\n Reject\n </button>\n <ActionButton action=\"offer\" big onClick={send} className=\"flex-1\">\n Confirm\n </ActionButton>\n </div>\n </div>\n </ActionModal>\n )}\n\n {status === \"processing\" && <BusyOverlay label=\"Signing & sending…\" />}\n {status === \"success\" && txHash && (\n <SuccessDialog\n title={sentMessage.title}\n message={sentMessage.description}\n txHash={txHash}\n onClose={() => {\n reset();\n onDone();\n }}\n />\n )}\n </main>\n );\n}\n"],"mappings":"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","names":[]}
@@ -44,16 +44,10 @@ function SuccessDialog({
44
44
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_modal.CanvasPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute inset-0 z-[70] grid place-items-center p-6", onClick: onClose, children: [
45
45
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_modal.ActionBackdrop, {}),
46
46
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-base relative z-10 w-full max-w-[320px] p-6 text-center", onClick: (e) => e.stopPropagation(), children: [
47
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
48
- "div",
49
- {
50
- className: "mx-auto grid h-16 w-16 place-items-center rounded-full text-white",
51
- style: { background: BRAND_GRADIENT },
52
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "30", height: "30", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 6L9 17l-5-5" }) })
53
- }
54
- ),
55
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "mt-4 font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight", children: title }),
56
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: message }),
47
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "status", children: [
48
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight", children: title }),
49
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: message })
50
+ ] }),
57
51
  txHash && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
58
52
  "a",
59
53
  {
@@ -61,7 +55,7 @@ function SuccessDialog({
61
55
  target: "_blank",
62
56
  rel: "noopener noreferrer",
63
57
  className: "mt-3 inline-block text-xs text-brand-blue hover:underline",
64
- children: "View on Voyager \u2197"
58
+ children: "View transaction \u2197"
65
59
  }
66
60
  ),
67
61
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_button.ActionButton, { big: true, onClick: onClose, className: "mt-5 w-full", style: { "--ml-grad": BRAND_GRADIENT }, children: actionLabel })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/media-wallet/success-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { ActionButton } from \"../action-button.js\";\nimport { ActionBackdrop, CanvasPortal } from \"./action-modal.js\";\nimport { fireConfetti } from \"../../utils/media-wallet/confetti.js\";\nimport { explorerTxUrl } from \"../../utils/media-wallet/wallet-format.js\";\nimport { useMediaWalletApp } from \"./types.js\";\n\nconst BRAND_GRADIENT = \"linear-gradient(115deg, #3b7bff, #8a5cf6, #f6608f, #fb8b46, #3b7bff)\";\n\nexport function SuccessDialog({\n title,\n message,\n actionLabel = \"Done\",\n txHash,\n onClose,\n}: {\n title: string;\n message: string;\n actionLabel?: string;\n txHash?: string;\n onClose: () => void;\n}) {\n const { explorerUrl } = useMediaWalletApp();\n useEffect(() => {\n fireConfetti();\n }, []);\n return (\n <CanvasPortal>\n <div className=\"absolute inset-0 z-[70] grid place-items-center p-6\" onClick={onClose}>\n <ActionBackdrop />\n <div className=\"card-base relative z-10 w-full max-w-[320px] p-6 text-center\" onClick={(e) => e.stopPropagation()}>\n <div\n className=\"mx-auto grid h-16 w-16 place-items-center rounded-full text-white\"\n style={{ background: BRAND_GRADIENT }}\n >\n <svg width=\"30\" height=\"30\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n </div>\n <h2 className=\"mt-4 font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight\">{title}</h2>\n <p className=\"mt-1.5 text-sm leading-relaxed text-muted-foreground\">{message}</p>\n {txHash && (\n <a\n href={explorerTxUrl(explorerUrl, txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-3 inline-block text-xs text-brand-blue hover:underline\"\n >\n View on Voyager ↗\n </a>\n )}\n <ActionButton big onClick={onClose} className=\"mt-5 w-full\" style={{ \"--ml-grad\": BRAND_GRADIENT } as React.CSSProperties}>\n {actionLabel}\n </ActionButton>\n </div>\n </div>\n </CanvasPortal>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BQ;AA7BR,mBAA0B;AAC1B,2BAA6B;AAC7B,0BAA6C;AAC7C,sBAA6B;AAC7B,2BAA8B;AAC9B,mBAAkC;AAElC,MAAM,iBAAiB;AAEhB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAMG;AACD,QAAM,EAAE,YAAY,QAAI,gCAAkB;AAC1C,8BAAU,MAAM;AACd,sCAAa;AAAA,EACf,GAAG,CAAC,CAAC;AACL,SACE,4CAAC,oCACC,uDAAC,SAAI,WAAU,uDAAsD,SAAS,SAC5E;AAAA,gDAAC,sCAAe;AAAA,IAChB,6CAAC,SAAI,WAAU,gEAA+D,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAC9G;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,YAAY,eAAe;AAAA,UAEpC,sDAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SACvI,sDAAC,UAAK,GAAE,mBAAkB,GAC5B;AAAA;AAAA,MACF;AAAA,MACA,4CAAC,QAAG,WAAU,qFAAqF,iBAAM;AAAA,MACzG,4CAAC,OAAE,WAAU,wDAAwD,mBAAQ;AAAA,MAC5E,UACC;AAAA,QAAC;AAAA;AAAA,UACC,UAAM,oCAAc,aAAa,MAAM;AAAA,UACvC,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MAEF,4CAAC,qCAAa,KAAG,MAAC,SAAS,SAAS,WAAU,eAAc,OAAO,EAAE,aAAa,eAAe,GAC9F,uBACH;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/media-wallet/success-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { ActionButton } from \"../action-button.js\";\nimport { ActionBackdrop, CanvasPortal } from \"./action-modal.js\";\nimport { fireConfetti } from \"../../utils/media-wallet/confetti.js\";\nimport { explorerTxUrl } from \"../../utils/media-wallet/wallet-format.js\";\nimport { useMediaWalletApp } from \"./types.js\";\n\nconst BRAND_GRADIENT = \"linear-gradient(115deg, #3b7bff, #8a5cf6, #f6608f, #fb8b46, #3b7bff)\";\n\nexport function SuccessDialog({\n title,\n message,\n actionLabel = \"Done\",\n txHash,\n onClose,\n}: {\n title: string;\n message: string;\n actionLabel?: string;\n txHash?: string;\n onClose: () => void;\n}) {\n const { explorerUrl } = useMediaWalletApp();\n useEffect(() => {\n fireConfetti();\n }, []);\n return (\n <CanvasPortal>\n <div className=\"absolute inset-0 z-[70] grid place-items-center p-6\" onClick={onClose}>\n <ActionBackdrop />\n <div className=\"card-base relative z-10 w-full max-w-[320px] p-6 text-center\" onClick={(e) => e.stopPropagation()}>\n <div role=\"status\">\n <h2 className=\"font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight\">{title}</h2>\n <p className=\"mt-1.5 text-sm leading-relaxed text-muted-foreground\">{message}</p>\n </div>\n {txHash && (\n <a\n href={explorerTxUrl(explorerUrl, txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-3 inline-block text-xs text-brand-blue hover:underline\"\n >\n View transaction ↗\n </a>\n )}\n <ActionButton big onClick={onClose} className=\"mt-5 w-full\" style={{ \"--ml-grad\": BRAND_GRADIENT } as React.CSSProperties}>\n {actionLabel}\n </ActionButton>\n </div>\n </div>\n </CanvasPortal>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BQ;AA7BR,mBAA0B;AAC1B,2BAA6B;AAC7B,0BAA6C;AAC7C,sBAA6B;AAC7B,2BAA8B;AAC9B,mBAAkC;AAElC,MAAM,iBAAiB;AAEhB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAMG;AACD,QAAM,EAAE,YAAY,QAAI,gCAAkB;AAC1C,8BAAU,MAAM;AACd,sCAAa;AAAA,EACf,GAAG,CAAC,CAAC;AACL,SACE,4CAAC,oCACC,uDAAC,SAAI,WAAU,uDAAsD,SAAS,SAC5E;AAAA,gDAAC,sCAAe;AAAA,IAChB,6CAAC,SAAI,WAAU,gEAA+D,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAC9G;AAAA,mDAAC,SAAI,MAAK,UACR;AAAA,oDAAC,QAAG,WAAU,gFAAgF,iBAAM;AAAA,QACpG,4CAAC,OAAE,WAAU,wDAAwD,mBAAQ;AAAA,SAC/E;AAAA,MACC,UACC;AAAA,QAAC;AAAA;AAAA,UACC,UAAM,oCAAc,aAAa,MAAM;AAAA,UACvC,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MAEF,4CAAC,qCAAa,KAAG,MAAC,SAAS,SAAS,WAAU,eAAc,OAAO,EAAE,aAAa,eAAe,GAC9F,uBACH;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -21,16 +21,10 @@ function SuccessDialog({
21
21
  return /* @__PURE__ */ jsx(CanvasPortal, { children: /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-[70] grid place-items-center p-6", onClick: onClose, children: [
22
22
  /* @__PURE__ */ jsx(ActionBackdrop, {}),
23
23
  /* @__PURE__ */ jsxs("div", { className: "card-base relative z-10 w-full max-w-[320px] p-6 text-center", onClick: (e) => e.stopPropagation(), children: [
24
- /* @__PURE__ */ jsx(
25
- "div",
26
- {
27
- className: "mx-auto grid h-16 w-16 place-items-center rounded-full text-white",
28
- style: { background: BRAND_GRADIENT },
29
- children: /* @__PURE__ */ jsx("svg", { width: "30", height: "30", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" }) })
30
- }
31
- ),
32
- /* @__PURE__ */ jsx("h2", { className: "mt-4 font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight", children: title }),
33
- /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: message }),
24
+ /* @__PURE__ */ jsxs("div", { role: "status", children: [
25
+ /* @__PURE__ */ jsx("h2", { className: "font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight", children: title }),
26
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: message })
27
+ ] }),
34
28
  txHash && /* @__PURE__ */ jsx(
35
29
  "a",
36
30
  {
@@ -38,7 +32,7 @@ function SuccessDialog({
38
32
  target: "_blank",
39
33
  rel: "noopener noreferrer",
40
34
  className: "mt-3 inline-block text-xs text-brand-blue hover:underline",
41
- children: "View on Voyager \u2197"
35
+ children: "View transaction \u2197"
42
36
  }
43
37
  ),
44
38
  /* @__PURE__ */ jsx(ActionButton, { big: true, onClick: onClose, className: "mt-5 w-full", style: { "--ml-grad": BRAND_GRADIENT }, children: actionLabel })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/media-wallet/success-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { ActionButton } from \"../action-button.js\";\nimport { ActionBackdrop, CanvasPortal } from \"./action-modal.js\";\nimport { fireConfetti } from \"../../utils/media-wallet/confetti.js\";\nimport { explorerTxUrl } from \"../../utils/media-wallet/wallet-format.js\";\nimport { useMediaWalletApp } from \"./types.js\";\n\nconst BRAND_GRADIENT = \"linear-gradient(115deg, #3b7bff, #8a5cf6, #f6608f, #fb8b46, #3b7bff)\";\n\nexport function SuccessDialog({\n title,\n message,\n actionLabel = \"Done\",\n txHash,\n onClose,\n}: {\n title: string;\n message: string;\n actionLabel?: string;\n txHash?: string;\n onClose: () => void;\n}) {\n const { explorerUrl } = useMediaWalletApp();\n useEffect(() => {\n fireConfetti();\n }, []);\n return (\n <CanvasPortal>\n <div className=\"absolute inset-0 z-[70] grid place-items-center p-6\" onClick={onClose}>\n <ActionBackdrop />\n <div className=\"card-base relative z-10 w-full max-w-[320px] p-6 text-center\" onClick={(e) => e.stopPropagation()}>\n <div\n className=\"mx-auto grid h-16 w-16 place-items-center rounded-full text-white\"\n style={{ background: BRAND_GRADIENT }}\n >\n <svg width=\"30\" height=\"30\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n </div>\n <h2 className=\"mt-4 font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight\">{title}</h2>\n <p className=\"mt-1.5 text-sm leading-relaxed text-muted-foreground\">{message}</p>\n {txHash && (\n <a\n href={explorerTxUrl(explorerUrl, txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-3 inline-block text-xs text-brand-blue hover:underline\"\n >\n View on Voyager ↗\n </a>\n )}\n <ActionButton big onClick={onClose} className=\"mt-5 w-full\" style={{ \"--ml-grad\": BRAND_GRADIENT } as React.CSSProperties}>\n {actionLabel}\n </ActionButton>\n </div>\n </div>\n </CanvasPortal>\n );\n}\n"],"mappings":";AA+BQ,cACA,YADA;AA7BR,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB;AAElC,MAAM,iBAAiB;AAEhB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAMG;AACD,QAAM,EAAE,YAAY,IAAI,kBAAkB;AAC1C,YAAU,MAAM;AACd,iBAAa;AAAA,EACf,GAAG,CAAC,CAAC;AACL,SACE,oBAAC,gBACC,+BAAC,SAAI,WAAU,uDAAsD,SAAS,SAC5E;AAAA,wBAAC,kBAAe;AAAA,IAChB,qBAAC,SAAI,WAAU,gEAA+D,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAC9G;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,YAAY,eAAe;AAAA,UAEpC,8BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SACvI,8BAAC,UAAK,GAAE,mBAAkB,GAC5B;AAAA;AAAA,MACF;AAAA,MACA,oBAAC,QAAG,WAAU,qFAAqF,iBAAM;AAAA,MACzG,oBAAC,OAAE,WAAU,wDAAwD,mBAAQ;AAAA,MAC5E,UACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,cAAc,aAAa,MAAM;AAAA,UACvC,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MAEF,oBAAC,gBAAa,KAAG,MAAC,SAAS,SAAS,WAAU,eAAc,OAAO,EAAE,aAAa,eAAe,GAC9F,uBACH;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/media-wallet/success-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { ActionButton } from \"../action-button.js\";\nimport { ActionBackdrop, CanvasPortal } from \"./action-modal.js\";\nimport { fireConfetti } from \"../../utils/media-wallet/confetti.js\";\nimport { explorerTxUrl } from \"../../utils/media-wallet/wallet-format.js\";\nimport { useMediaWalletApp } from \"./types.js\";\n\nconst BRAND_GRADIENT = \"linear-gradient(115deg, #3b7bff, #8a5cf6, #f6608f, #fb8b46, #3b7bff)\";\n\nexport function SuccessDialog({\n title,\n message,\n actionLabel = \"Done\",\n txHash,\n onClose,\n}: {\n title: string;\n message: string;\n actionLabel?: string;\n txHash?: string;\n onClose: () => void;\n}) {\n const { explorerUrl } = useMediaWalletApp();\n useEffect(() => {\n fireConfetti();\n }, []);\n return (\n <CanvasPortal>\n <div className=\"absolute inset-0 z-[70] grid place-items-center p-6\" onClick={onClose}>\n <ActionBackdrop />\n <div className=\"card-base relative z-10 w-full max-w-[320px] p-6 text-center\" onClick={(e) => e.stopPropagation()}>\n <div role=\"status\">\n <h2 className=\"font-[family-name:var(--font-display)] text-xl font-extrabold tracking-tight\">{title}</h2>\n <p className=\"mt-1.5 text-sm leading-relaxed text-muted-foreground\">{message}</p>\n </div>\n {txHash && (\n <a\n href={explorerTxUrl(explorerUrl, txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-3 inline-block text-xs text-brand-blue hover:underline\"\n >\n View transaction ↗\n </a>\n )}\n <ActionButton big onClick={onClose} className=\"mt-5 w-full\" style={{ \"--ml-grad\": BRAND_GRADIENT } as React.CSSProperties}>\n {actionLabel}\n </ActionButton>\n </div>\n </div>\n </CanvasPortal>\n );\n}\n"],"mappings":";AA+BQ,cAEE,YAFF;AA7BR,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB;AAElC,MAAM,iBAAiB;AAEhB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAMG;AACD,QAAM,EAAE,YAAY,IAAI,kBAAkB;AAC1C,YAAU,MAAM;AACd,iBAAa;AAAA,EACf,GAAG,CAAC,CAAC;AACL,SACE,oBAAC,gBACC,+BAAC,SAAI,WAAU,uDAAsD,SAAS,SAC5E;AAAA,wBAAC,kBAAe;AAAA,IAChB,qBAAC,SAAI,WAAU,gEAA+D,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAC9G;AAAA,2BAAC,SAAI,MAAK,UACR;AAAA,4BAAC,QAAG,WAAU,gFAAgF,iBAAM;AAAA,QACpG,oBAAC,OAAE,WAAU,wDAAwD,mBAAQ;AAAA,SAC/E;AAAA,MACC,UACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,cAAc,aAAa,MAAM;AAAA,UACvC,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MAEF,oBAAC,gBAAa,KAAG,MAAC,SAAS,SAAS,WAAU,eAAc,OAAO,EAAE,aAAa,eAAe,GAC9F,uBACH;AAAA,OACF;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -34,6 +34,7 @@ var import_medialane_app = require("./medialane-app.js");
34
34
  var import_claim_proof = require("../utils/drop/claim-proof.js");
35
35
  var import_run_intent_calls = require("../utils/run-intent-calls.js");
36
36
  var import_use_pop = require("../utils/use-pop.js");
37
+ var import_success_messages = require("../utils/success-messages.js");
37
38
  var import_use_transaction = require("../utils/use-transaction.js");
38
39
  function PopClaimButton({ collectionAddress }) {
39
40
  const app = (0, import_medialane_app.useMedialaneApp)();
@@ -77,8 +78,7 @@ function PopClaimButton({ collectionAddress }) {
77
78
  import_transaction_success.TransactionSuccess,
78
79
  {
79
80
  name: "Credential",
80
- title: "Credential claimed!",
81
- description: "Your proof of participation is now on-chain.",
81
+ ...import_success_messages.successMessages.claimed(),
82
82
  txHash: tx.txHash,
83
83
  actions: [{ label: "Done", onClick: tx.reset }],
84
84
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_reward_earned.RewardEarned, { actionType: "claim_pop" })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/pop-claim-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Award, Loader2 } from \"lucide-react\";\nimport { popClaimState, type PopClaimInfo } from \"@medialane/sdk/starknet\";\nimport { Button } from \"./button.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { claimProofFor } from \"../utils/drop/claim-proof.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { usePopClaimStatus } from \"../utils/use-pop.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport function PopClaimButton({ collectionAddress }: { collectionAddress: string }) {\n const app = useMedialaneApp();\n const { walletAddress } = app;\n const { hasClaimed, mutate } = usePopClaimStatus(collectionAddress, walletAddress);\n const [proof, setProof] = useState<string[] | null>(null);\n const [info, setInfo] = useState<PopClaimInfo | null>(null);\n const tx = useTransaction();\n const busy = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n useEffect(() => {\n let storage: Storage | null = null;\n try {\n storage = window.sessionStorage;\n } catch {\n storage = null;\n }\n setProof(claimProofFor(storage, collectionAddress, window.location.hash));\n app.getClient().api.chainReads.popClaimInfo(collectionAddress)\n .then(setInfo)\n .catch(() => setInfo(null));\n }, [app, collectionAddress]);\n\n useEffect(() => {\n if (tx.phase === \"success\") void mutate();\n }, [tx.phase, mutate]);\n\n const state = popClaimState({\n hasClaimed,\n proof,\n wallet: walletAddress,\n info: info && { ...info, now: Math.floor(Date.now() / 1000) },\n });\n\n const claim = () => {\n if (!proof) return;\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-claim\", { claimer: signer.address, collection: collectionAddress, proof }));\n });\n };\n\n return (\n <>\n {(state === \"ready\" || busy) && (\n <Button size=\"sm\" className=\"w-full gap-1.5\" onClick={claim} disabled={busy}>\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <Award className=\"h-3.5 w-3.5\" />}\n {busy ? \"Claiming…\" : \"Claim credential\"}\n </Button>\n )}\n <TransactionDialog tx={tx} title=\"Claim credential\" workingLabel=\"Claiming your credential…\" firstStepLabel=\"Prepare claim\">\n <TransactionSuccess\n name=\"Credential\"\n title=\"Credential claimed!\"\n description=\"Your proof of participation is now on-chain.\"\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"claim_pop\" />\n </TransactionSuccess>\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDI;AAtDJ,mBAAoC;AACpC,0BAA+B;AAC/B,sBAAiD;AACjD,oBAAuB;AACvB,gCAAkC;AAClC,iCAAmC;AACnC,2BAA6B;AAC7B,2BAAgC;AAChC,yBAA8B;AAC9B,8BAA+B;AAC/B,qBAAkC;AAClC,6BAA+B;AAExB,SAAS,eAAe,EAAE,kBAAkB,GAAkC;AACnF,QAAM,UAAM,sCAAgB;AAC5B,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,EAAE,YAAY,OAAO,QAAI,kCAAkB,mBAAmB,aAAa;AACjF,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAA0B,IAAI;AACxD,QAAM,CAAC,MAAM,OAAO,QAAI,uBAA8B,IAAI;AAC1D,QAAM,SAAK,uCAAe;AAC1B,QAAM,OAAO,GAAG,UAAU,eAAe,GAAG,UAAU,gBAAgB,GAAG,UAAU;AAEnF,8BAAU,MAAM;AACd,QAAI,UAA0B;AAC9B,QAAI;AACF,gBAAU,OAAO;AAAA,IACnB,QAAQ;AACN,gBAAU;AAAA,IACZ;AACA,iBAAS,kCAAc,SAAS,mBAAmB,OAAO,SAAS,IAAI,CAAC;AACxE,QAAI,UAAU,EAAE,IAAI,WAAW,aAAa,iBAAiB,EAC1D,KAAK,OAAO,EACZ,MAAM,MAAM,QAAQ,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,KAAK,iBAAiB,CAAC;AAE3B,8BAAU,MAAM;AACd,QAAI,GAAG,UAAU,UAAW,MAAK,OAAO;AAAA,EAC1C,GAAG,CAAC,GAAG,OAAO,MAAM,CAAC;AAErB,QAAM,YAAQ,+BAAc;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,QAAQ,EAAE,GAAG,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE;AAAA,EAC9D,CAAC;AAED,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,MAAO;AACZ,SAAK,GAAG,IAAI,OAAO,WAAW;AAC5B,gBAAM,wCAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,aAAa,EAAE,SAAS,OAAO,SAAS,YAAY,mBAAmB,MAAM,CAAC,CAAC;AAAA,IACvJ,CAAC;AAAA,EACH;AAEA,SACE,4EACI;AAAA,eAAU,WAAW,SACrB,6CAAC,wBAAO,MAAK,MAAK,WAAU,kBAAiB,SAAS,OAAO,UAAU,MACpE;AAAA,aAAO,4CAAC,+BAAQ,WAAU,4BAA2B,IAAK,4CAAC,6BAAM,WAAU,eAAc;AAAA,MACzF,OAAO,mBAAc;AAAA,OACxB;AAAA,IAEF,4CAAC,+CAAkB,IAAQ,OAAM,oBAAmB,cAAa,kCAA4B,gBAAe,iBAC1G;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,QAAQ,GAAG;AAAA,QACX,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,GAAG,MAAM,CAAC;AAAA,QAE9C,sDAAC,qCAAa,YAAW,aAAY;AAAA;AAAA,IACvC,GACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/pop-claim-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Award, Loader2 } from \"lucide-react\";\nimport { popClaimState, type PopClaimInfo } from \"@medialane/sdk/starknet\";\nimport { Button } from \"./button.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { claimProofFor } from \"../utils/drop/claim-proof.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { usePopClaimStatus } from \"../utils/use-pop.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport function PopClaimButton({ collectionAddress }: { collectionAddress: string }) {\n const app = useMedialaneApp();\n const { walletAddress } = app;\n const { hasClaimed, mutate } = usePopClaimStatus(collectionAddress, walletAddress);\n const [proof, setProof] = useState<string[] | null>(null);\n const [info, setInfo] = useState<PopClaimInfo | null>(null);\n const tx = useTransaction();\n const busy = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n useEffect(() => {\n let storage: Storage | null = null;\n try {\n storage = window.sessionStorage;\n } catch {\n storage = null;\n }\n setProof(claimProofFor(storage, collectionAddress, window.location.hash));\n app.getClient().api.chainReads.popClaimInfo(collectionAddress)\n .then(setInfo)\n .catch(() => setInfo(null));\n }, [app, collectionAddress]);\n\n useEffect(() => {\n if (tx.phase === \"success\") void mutate();\n }, [tx.phase, mutate]);\n\n const state = popClaimState({\n hasClaimed,\n proof,\n wallet: walletAddress,\n info: info && { ...info, now: Math.floor(Date.now() / 1000) },\n });\n\n const claim = () => {\n if (!proof) return;\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-claim\", { claimer: signer.address, collection: collectionAddress, proof }));\n });\n };\n\n return (\n <>\n {(state === \"ready\" || busy) && (\n <Button size=\"sm\" className=\"w-full gap-1.5\" onClick={claim} disabled={busy}>\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <Award className=\"h-3.5 w-3.5\" />}\n {busy ? \"Claiming…\" : \"Claim credential\"}\n </Button>\n )}\n <TransactionDialog tx={tx} title=\"Claim credential\" workingLabel=\"Claiming your credential…\" firstStepLabel=\"Prepare claim\">\n <TransactionSuccess\n name=\"Credential\"\n {...successMessages.claimed()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"claim_pop\" />\n </TransactionSuccess>\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDI;AAvDJ,mBAAoC;AACpC,0BAA+B;AAC/B,sBAAiD;AACjD,oBAAuB;AACvB,gCAAkC;AAClC,iCAAmC;AACnC,2BAA6B;AAC7B,2BAAgC;AAChC,yBAA8B;AAC9B,8BAA+B;AAC/B,qBAAkC;AAClC,8BAAgC;AAChC,6BAA+B;AAExB,SAAS,eAAe,EAAE,kBAAkB,GAAkC;AACnF,QAAM,UAAM,sCAAgB;AAC5B,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,EAAE,YAAY,OAAO,QAAI,kCAAkB,mBAAmB,aAAa;AACjF,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAA0B,IAAI;AACxD,QAAM,CAAC,MAAM,OAAO,QAAI,uBAA8B,IAAI;AAC1D,QAAM,SAAK,uCAAe;AAC1B,QAAM,OAAO,GAAG,UAAU,eAAe,GAAG,UAAU,gBAAgB,GAAG,UAAU;AAEnF,8BAAU,MAAM;AACd,QAAI,UAA0B;AAC9B,QAAI;AACF,gBAAU,OAAO;AAAA,IACnB,QAAQ;AACN,gBAAU;AAAA,IACZ;AACA,iBAAS,kCAAc,SAAS,mBAAmB,OAAO,SAAS,IAAI,CAAC;AACxE,QAAI,UAAU,EAAE,IAAI,WAAW,aAAa,iBAAiB,EAC1D,KAAK,OAAO,EACZ,MAAM,MAAM,QAAQ,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,KAAK,iBAAiB,CAAC;AAE3B,8BAAU,MAAM;AACd,QAAI,GAAG,UAAU,UAAW,MAAK,OAAO;AAAA,EAC1C,GAAG,CAAC,GAAG,OAAO,MAAM,CAAC;AAErB,QAAM,YAAQ,+BAAc;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,QAAQ,EAAE,GAAG,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE;AAAA,EAC9D,CAAC;AAED,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,MAAO;AACZ,SAAK,GAAG,IAAI,OAAO,WAAW;AAC5B,gBAAM,wCAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,aAAa,EAAE,SAAS,OAAO,SAAS,YAAY,mBAAmB,MAAM,CAAC,CAAC;AAAA,IACvJ,CAAC;AAAA,EACH;AAEA,SACE,4EACI;AAAA,eAAU,WAAW,SACrB,6CAAC,wBAAO,MAAK,MAAK,WAAU,kBAAiB,SAAS,OAAO,UAAU,MACpE;AAAA,aAAO,4CAAC,+BAAQ,WAAU,4BAA2B,IAAK,4CAAC,6BAAM,WAAU,eAAc;AAAA,MACzF,OAAO,mBAAc;AAAA,OACxB;AAAA,IAEF,4CAAC,+CAAkB,IAAQ,OAAM,oBAAmB,cAAa,kCAA4B,gBAAe,iBAC1G;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACJ,GAAG,wCAAgB,QAAQ;AAAA,QAC5B,QAAQ,GAAG;AAAA,QACX,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,GAAG,MAAM,CAAC;AAAA,QAE9C,sDAAC,qCAAa,YAAW,aAAY;AAAA;AAAA,IACvC,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -11,6 +11,7 @@ import { useMedialaneApp } from "./medialane-app.js";
11
11
  import { claimProofFor } from "../utils/drop/claim-proof.js";
12
12
  import { runIntentCalls } from "../utils/run-intent-calls.js";
13
13
  import { usePopClaimStatus } from "../utils/use-pop.js";
14
+ import { successMessages } from "../utils/success-messages.js";
14
15
  import { useTransaction } from "../utils/use-transaction.js";
15
16
  function PopClaimButton({ collectionAddress }) {
16
17
  const app = useMedialaneApp();
@@ -54,8 +55,7 @@ function PopClaimButton({ collectionAddress }) {
54
55
  TransactionSuccess,
55
56
  {
56
57
  name: "Credential",
57
- title: "Credential claimed!",
58
- description: "Your proof of participation is now on-chain.",
58
+ ...successMessages.claimed(),
59
59
  txHash: tx.txHash,
60
60
  actions: [{ label: "Done", onClick: tx.reset }],
61
61
  children: /* @__PURE__ */ jsx(RewardEarned, { actionType: "claim_pop" })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/pop-claim-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Award, Loader2 } from \"lucide-react\";\nimport { popClaimState, type PopClaimInfo } from \"@medialane/sdk/starknet\";\nimport { Button } from \"./button.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { claimProofFor } from \"../utils/drop/claim-proof.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { usePopClaimStatus } from \"../utils/use-pop.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport function PopClaimButton({ collectionAddress }: { collectionAddress: string }) {\n const app = useMedialaneApp();\n const { walletAddress } = app;\n const { hasClaimed, mutate } = usePopClaimStatus(collectionAddress, walletAddress);\n const [proof, setProof] = useState<string[] | null>(null);\n const [info, setInfo] = useState<PopClaimInfo | null>(null);\n const tx = useTransaction();\n const busy = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n useEffect(() => {\n let storage: Storage | null = null;\n try {\n storage = window.sessionStorage;\n } catch {\n storage = null;\n }\n setProof(claimProofFor(storage, collectionAddress, window.location.hash));\n app.getClient().api.chainReads.popClaimInfo(collectionAddress)\n .then(setInfo)\n .catch(() => setInfo(null));\n }, [app, collectionAddress]);\n\n useEffect(() => {\n if (tx.phase === \"success\") void mutate();\n }, [tx.phase, mutate]);\n\n const state = popClaimState({\n hasClaimed,\n proof,\n wallet: walletAddress,\n info: info && { ...info, now: Math.floor(Date.now() / 1000) },\n });\n\n const claim = () => {\n if (!proof) return;\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-claim\", { claimer: signer.address, collection: collectionAddress, proof }));\n });\n };\n\n return (\n <>\n {(state === \"ready\" || busy) && (\n <Button size=\"sm\" className=\"w-full gap-1.5\" onClick={claim} disabled={busy}>\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <Award className=\"h-3.5 w-3.5\" />}\n {busy ? \"Claiming…\" : \"Claim credential\"}\n </Button>\n )}\n <TransactionDialog tx={tx} title=\"Claim credential\" workingLabel=\"Claiming your credential…\" firstStepLabel=\"Prepare claim\">\n <TransactionSuccess\n name=\"Credential\"\n title=\"Credential claimed!\"\n description=\"Your proof of participation is now on-chain.\"\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"claim_pop\" />\n </TransactionSuccess>\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":";AAwDI,mBAGc,KADV,YAFJ;AAtDJ,SAAS,WAAW,gBAAgB;AACpC,SAAS,OAAO,eAAe;AAC/B,SAAS,qBAAwC;AACjD,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAClC,SAAS,sBAAsB;AAExB,SAAS,eAAe,EAAE,kBAAkB,GAAkC;AACnF,QAAM,MAAM,gBAAgB;AAC5B,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,EAAE,YAAY,OAAO,IAAI,kBAAkB,mBAAmB,aAAa;AACjF,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA0B,IAAI;AACxD,QAAM,CAAC,MAAM,OAAO,IAAI,SAA8B,IAAI;AAC1D,QAAM,KAAK,eAAe;AAC1B,QAAM,OAAO,GAAG,UAAU,eAAe,GAAG,UAAU,gBAAgB,GAAG,UAAU;AAEnF,YAAU,MAAM;AACd,QAAI,UAA0B;AAC9B,QAAI;AACF,gBAAU,OAAO;AAAA,IACnB,QAAQ;AACN,gBAAU;AAAA,IACZ;AACA,aAAS,cAAc,SAAS,mBAAmB,OAAO,SAAS,IAAI,CAAC;AACxE,QAAI,UAAU,EAAE,IAAI,WAAW,aAAa,iBAAiB,EAC1D,KAAK,OAAO,EACZ,MAAM,MAAM,QAAQ,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,KAAK,iBAAiB,CAAC;AAE3B,YAAU,MAAM;AACd,QAAI,GAAG,UAAU,UAAW,MAAK,OAAO;AAAA,EAC1C,GAAG,CAAC,GAAG,OAAO,MAAM,CAAC;AAErB,QAAM,QAAQ,cAAc;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,QAAQ,EAAE,GAAG,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE;AAAA,EAC9D,CAAC;AAED,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,MAAO;AACZ,SAAK,GAAG,IAAI,OAAO,WAAW;AAC5B,YAAM,eAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,aAAa,EAAE,SAAS,OAAO,SAAS,YAAY,mBAAmB,MAAM,CAAC,CAAC;AAAA,IACvJ,CAAC;AAAA,EACH;AAEA,SACE,iCACI;AAAA,eAAU,WAAW,SACrB,qBAAC,UAAO,MAAK,MAAK,WAAU,kBAAiB,SAAS,OAAO,UAAU,MACpE;AAAA,aAAO,oBAAC,WAAQ,WAAU,4BAA2B,IAAK,oBAAC,SAAM,WAAU,eAAc;AAAA,MACzF,OAAO,mBAAc;AAAA,OACxB;AAAA,IAEF,oBAAC,qBAAkB,IAAQ,OAAM,oBAAmB,cAAa,kCAA4B,gBAAe,iBAC1G;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAM;AAAA,QACN,aAAY;AAAA,QACZ,QAAQ,GAAG;AAAA,QACX,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,GAAG,MAAM,CAAC;AAAA,QAE9C,8BAAC,gBAAa,YAAW,aAAY;AAAA;AAAA,IACvC,GACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/pop-claim-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Award, Loader2 } from \"lucide-react\";\nimport { popClaimState, type PopClaimInfo } from \"@medialane/sdk/starknet\";\nimport { Button } from \"./button.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { claimProofFor } from \"../utils/drop/claim-proof.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { usePopClaimStatus } from \"../utils/use-pop.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport function PopClaimButton({ collectionAddress }: { collectionAddress: string }) {\n const app = useMedialaneApp();\n const { walletAddress } = app;\n const { hasClaimed, mutate } = usePopClaimStatus(collectionAddress, walletAddress);\n const [proof, setProof] = useState<string[] | null>(null);\n const [info, setInfo] = useState<PopClaimInfo | null>(null);\n const tx = useTransaction();\n const busy = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n useEffect(() => {\n let storage: Storage | null = null;\n try {\n storage = window.sessionStorage;\n } catch {\n storage = null;\n }\n setProof(claimProofFor(storage, collectionAddress, window.location.hash));\n app.getClient().api.chainReads.popClaimInfo(collectionAddress)\n .then(setInfo)\n .catch(() => setInfo(null));\n }, [app, collectionAddress]);\n\n useEffect(() => {\n if (tx.phase === \"success\") void mutate();\n }, [tx.phase, mutate]);\n\n const state = popClaimState({\n hasClaimed,\n proof,\n wallet: walletAddress,\n info: info && { ...info, now: Math.floor(Date.now() / 1000) },\n });\n\n const claim = () => {\n if (!proof) return;\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-claim\", { claimer: signer.address, collection: collectionAddress, proof }));\n });\n };\n\n return (\n <>\n {(state === \"ready\" || busy) && (\n <Button size=\"sm\" className=\"w-full gap-1.5\" onClick={claim} disabled={busy}>\n {busy ? <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> : <Award className=\"h-3.5 w-3.5\" />}\n {busy ? \"Claiming…\" : \"Claim credential\"}\n </Button>\n )}\n <TransactionDialog tx={tx} title=\"Claim credential\" workingLabel=\"Claiming your credential…\" firstStepLabel=\"Prepare claim\">\n <TransactionSuccess\n name=\"Credential\"\n {...successMessages.claimed()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"claim_pop\" />\n </TransactionSuccess>\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":";AAyDI,mBAGc,KADV,YAFJ;AAvDJ,SAAS,WAAW,gBAAgB;AACpC,SAAS,OAAO,eAAe;AAC/B,SAAS,qBAAwC;AACjD,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAExB,SAAS,eAAe,EAAE,kBAAkB,GAAkC;AACnF,QAAM,MAAM,gBAAgB;AAC5B,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,EAAE,YAAY,OAAO,IAAI,kBAAkB,mBAAmB,aAAa;AACjF,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA0B,IAAI;AACxD,QAAM,CAAC,MAAM,OAAO,IAAI,SAA8B,IAAI;AAC1D,QAAM,KAAK,eAAe;AAC1B,QAAM,OAAO,GAAG,UAAU,eAAe,GAAG,UAAU,gBAAgB,GAAG,UAAU;AAEnF,YAAU,MAAM;AACd,QAAI,UAA0B;AAC9B,QAAI;AACF,gBAAU,OAAO;AAAA,IACnB,QAAQ;AACN,gBAAU;AAAA,IACZ;AACA,aAAS,cAAc,SAAS,mBAAmB,OAAO,SAAS,IAAI,CAAC;AACxE,QAAI,UAAU,EAAE,IAAI,WAAW,aAAa,iBAAiB,EAC1D,KAAK,OAAO,EACZ,MAAM,MAAM,QAAQ,IAAI,CAAC;AAAA,EAC9B,GAAG,CAAC,KAAK,iBAAiB,CAAC;AAE3B,YAAU,MAAM;AACd,QAAI,GAAG,UAAU,UAAW,MAAK,OAAO;AAAA,EAC1C,GAAG,CAAC,GAAG,OAAO,MAAM,CAAC;AAErB,QAAM,QAAQ,cAAc;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,QAAQ,EAAE,GAAG,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,EAAE;AAAA,EAC9D,CAAC;AAED,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,MAAO;AACZ,SAAK,GAAG,IAAI,OAAO,WAAW;AAC5B,YAAM,eAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,aAAa,EAAE,SAAS,OAAO,SAAS,YAAY,mBAAmB,MAAM,CAAC,CAAC;AAAA,IACvJ,CAAC;AAAA,EACH;AAEA,SACE,iCACI;AAAA,eAAU,WAAW,SACrB,qBAAC,UAAO,MAAK,MAAK,WAAU,kBAAiB,SAAS,OAAO,UAAU,MACpE;AAAA,aAAO,oBAAC,WAAQ,WAAU,4BAA2B,IAAK,oBAAC,SAAM,WAAU,eAAc;AAAA,MACzF,OAAO,mBAAc;AAAA,OACxB;AAAA,IAEF,oBAAC,qBAAkB,IAAQ,OAAM,oBAAmB,cAAa,kCAA4B,gBAAe,iBAC1G;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACJ,GAAG,gBAAgB,QAAQ;AAAA,QAC5B,QAAQ,GAAG;AAAA,QACX,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,GAAG,MAAM,CAAC;AAAA,QAE9C,8BAAC,gBAAa,YAAW,aAAY;AAAA;AAAA,IACvC,GACF;AAAA,KACF;AAEJ;","names":[]}
@@ -47,6 +47,7 @@ var import_transaction_dialog = require("./transaction-dialog.js");
47
47
  var import_transaction_success = require("./transaction-success.js");
48
48
  var import_wallet_required = require("./wallet-required.js");
49
49
  var import_run_intent_calls = require("../utils/run-intent-calls.js");
50
+ var import_success_messages = require("../utils/success-messages.js");
50
51
  var import_use_collections = require("../utils/use-collections.js");
51
52
  var import_use_transaction = require("../utils/use-transaction.js");
52
53
  function parseAddresses(raw) {
@@ -164,7 +165,7 @@ function PopManagePage({ contract }) {
164
165
  const isSubmitting = tx.phase === "preparing" || tx.phase === "submitting" || tx.phase === "confirming";
165
166
  const isOwner = walletAddress && collection?.owner && (0, import_sdk.normalizeAddress)("STARKNET", walletAddress) === (0, import_sdk.normalizeAddress)("STARKNET", collection.owner);
166
167
  const issue = (recipient) => {
167
- setDone({ title: "Credential issued", description: "The credential is now in their wallet." });
168
+ setDone(import_success_messages.successMessages.credentialIssued());
168
169
  void tx.run(async (signer) => {
169
170
  await (0, import_run_intent_calls.runIntentCalls)(signer, () => app.getClient().api.intents.create("pop-manage", { owner: signer.address, collection: contract, action: "issue", recipient }));
170
171
  });
@@ -172,7 +173,7 @@ function PopManagePage({ contract }) {
172
173
  const publish = (addresses) => {
173
174
  const list = (0, import_starknet.buildPopAllowlist)(addresses);
174
175
  const count = Object.keys(list.proofs).length;
175
- setDone({ title: "Participants published", description: `Published ${count} participant${count !== 1 ? "s" : ""}.` });
176
+ setDone(import_success_messages.successMessages.participantsPublished({ count }));
176
177
  void tx.run(async (signer) => {
177
178
  await (0, import_run_intent_calls.runIntentCalls)(signer, () => app.getClient().api.intents.create("pop-manage", { owner: signer.address, collection: contract, action: "set_allowlist_root", root: list.root }));
178
179
  }).then((ok) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/pop-manage-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { buildPopAllowlist, popClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ArrowLeft, Award, AlertCircle, CheckCircle2, Download, Loader2, Send, Users } from \"lucide-react\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { WalletRequired } from \"./wallet-required.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { useCollection } from \"../utils/use-collections.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nfunction parseAddresses(raw: string): string[] {\n return raw\n .split(/[\\n,\\s]+/)\n .map((a) => a.trim())\n .filter((a) => /^0x[0-9a-fA-F]+$/.test(a));\n}\n\nfunction downloadCsv(links: PopClaimLink[]) {\n const href = URL.createObjectURL(new Blob([popClaimLinksCsv(links)], { type: \"text/csv\" }));\n const anchor = Object.assign(document.createElement(\"a\"), { href, download: \"claim-links.csv\" });\n anchor.click();\n URL.revokeObjectURL(href);\n}\n\nfunction IssueSection({\n onIssue,\n isSubmitting,\n}: {\n onIssue: (address: string) => void;\n isSubmitting: boolean;\n}) {\n const [raw, setRaw] = useState(\"\");\n const address = raw.trim();\n const valid = /^0x[0-9a-fA-F]{1,64}$/.test(address);\n\n return (\n <div className=\"bento-cell p-5 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Award className=\"h-4 w-4 text-green-500\" />\n <span className=\"font-semibold text-sm\">Issue directly</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Send the credential straight to one wallet — for a late participant, without republishing the list or\n changing anyone&apos;s claim link.\n </p>\n <input\n type=\"text\"\n placeholder=\"0x...\"\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm tabular-nums placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring\"\n />\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n disabled={!valid || isSubmitting}\n onClick={() => {\n onIssue(address);\n setRaw(\"\");\n }}\n >\n <Send className=\"h-3.5 w-3.5 mr-1.5\" />\n Issue credential\n </Button>\n </div>\n );\n}\n\nfunction AllowlistSection({\n onPublish,\n isSubmitting,\n links,\n}: {\n onPublish: (addresses: string[]) => void;\n isSubmitting: boolean;\n links: PopClaimLink[] | null;\n}) {\n const [raw, setRaw] = useState(\"\");\n const parsed = parseAddresses(raw);\n\n return (\n <div className=\"bento-cell p-5 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4 text-green-500\" />\n <span className=\"font-semibold text-sm\">Participants</span>\n {parsed.length > 0 && (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {parsed.length} address{parsed.length !== 1 ? \"es\" : \"\"}\n </span>\n )}\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Paste every participant&apos;s wallet address. Publishing replaces the previous list and every link\n sent before it — send the new links to everyone who hasn&apos;t claimed yet. The list stays in this\n browser: download the claim links and send each participant theirs.\n </p>\n <Textarea\n placeholder={\"Paste Starknet addresses, one per line:\\n0x04a...\\n0x06b...\"}\n rows={8}\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n className=\"tabular-nums text-xs resize-none\"\n />\n <Button\n size=\"sm\"\n className=\"w-full bg-green-600 hover:bg-green-700 text-white\"\n disabled={parsed.length === 0 || isSubmitting}\n onClick={() => onPublish(parsed)}\n >\n {isSubmitting ? (\n <>\n <Loader2 className=\"h-3.5 w-3.5 animate-spin mr-1.5\" />\n Publishing…\n </>\n ) : (\n <>\n <CheckCircle2 className=\"h-3.5 w-3.5 mr-1.5\" />\n Publish {parsed.length > 0 ? `${parsed.length} participant${parsed.length !== 1 ? \"s\" : \"\"}` : \"participants\"}\n </>\n )}\n </Button>\n {links && (\n <div className=\"space-y-2 pt-2\">\n <Button variant=\"outline\" size=\"sm\" className=\"w-full\" onClick={() => downloadCsv(links)}>\n <Download className=\"h-3.5 w-3.5 mr-1.5\" />\n Download claim links (CSV)\n </Button>\n <ul className=\"max-h-48 overflow-auto text-xs tabular-nums space-y-1 text-muted-foreground\">\n {links.map((link) => (\n <li key={link.address} className=\"truncate\">{link.address}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n\nexport function PopManagePage({ contract }: { contract: string }) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const { collection, isLoading } = useCollection(contract);\n const tx = useTransaction();\n const [done, setDone] = useState({ title: \"\", description: \"\" });\n const [links, setLinks] = useState<PopClaimLink[] | null>(null);\n const isSubmitting = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwner =\n walletAddress &&\n collection?.owner &&\n normalizeAddress(\"STARKNET\", walletAddress) === normalizeAddress(\"STARKNET\", collection.owner);\n\n const issue = (recipient: string) => {\n setDone({ title: \"Credential issued\", description: \"The credential is now in their wallet.\" });\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-manage\", { owner: signer.address, collection: contract, action: \"issue\", recipient }));\n });\n };\n\n const publish = (addresses: string[]) => {\n const list = buildPopAllowlist(addresses);\n const count = Object.keys(list.proofs).length;\n setDone({ title: \"Participants published\", description: `Published ${count} participant${count !== 1 ? \"s\" : \"\"}.` });\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-manage\", { owner: signer.address, collection: contract, action: \"set_allowlist_root\", root: list.root }));\n })\n .then((ok) => {\n if (ok) setLinks(popClaimLinks(window.location.origin, contract, list));\n });\n };\n\n return (\n <WalletRequired icon={Award} title=\"Connect your wallet\" description=\"Connect to manage your event.\">\n {isLoading ? (\n <div className=\"max-w-xl mx-auto px-4 pt-10 pb-16 space-y-4\">\n <Skeleton className=\"h-6 w-24\" />\n <Skeleton className=\"h-32 w-full rounded-2xl\" />\n <Skeleton className=\"h-64 w-full rounded-2xl\" />\n </div>\n ) : !collection ? (\n <div className=\"max-w-xl mx-auto px-4 pt-24 pb-8 text-center space-y-4\">\n <AlertCircle className=\"h-10 w-10 text-muted-foreground/20 mx-auto\" />\n <p className=\"text-muted-foreground\">Collection not found.</p>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/launchpad/pop\">← Back</Link>\n </Button>\n </div>\n ) : !isOwner ? (\n <div className=\"max-w-xl mx-auto px-4 pt-24 pb-8 text-center space-y-4\">\n <Award className=\"h-10 w-10 text-muted-foreground/20 mx-auto\" />\n <p className=\"text-muted-foreground\">You are not the organizer of this event.</p>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/launchpad/pop\">← Back to events</Link>\n </Button>\n </div>\n ) : (\n <div className=\"max-w-xl mx-auto px-4 pt-10 pb-16 space-y-6\">\n <TransactionDialog tx={tx} title=\"Manage event\" workingLabel=\"Updating your event…\" firstStepLabel=\"Prepare\">\n <TransactionSuccess name={collection.name ?? \"Event\"} title={done.title} description={done.description} txHash={tx.txHash} actions={[{ label: \"Done\", onClick: tx.reset }]} />\n </TransactionDialog>\n\n <FadeIn>\n <Button asChild variant=\"ghost\" size=\"sm\" className=\"-ml-2\">\n <Link href=\"/launchpad/pop\">\n <ArrowLeft className=\"h-3.5 w-3.5 mr-1.5\" />\n All events\n </Link>\n </Button>\n </FadeIn>\n\n <FadeIn delay={0.04}>\n <div>\n <span className=\"pill-badge inline-flex gap-1.5 mb-2\">\n <Award className=\"h-3 w-3\" />\n Organizer\n </span>\n <h1 className=\"text-2xl font-bold mt-1\">Manage Event</h1>\n <p className=\"text-sm text-muted-foreground\">{collection.name ?? contract}</p>\n </div>\n </FadeIn>\n\n <FadeIn delay={0.08}>\n <div className=\"bento-cell p-4 flex items-center gap-3\">\n <Award className=\"h-4 w-4 text-green-500 shrink-0\" />\n <p className=\"text-xs text-muted-foreground\">\n Only participants on your <strong className=\"text-foreground\">published list</strong> can claim,\n with the link you send them.\n </p>\n </div>\n </FadeIn>\n\n <FadeIn delay={0.12}>\n <AllowlistSection onPublish={publish} isSubmitting={isSubmitting} links={links} />\n </FadeIn>\n\n <FadeIn delay={0.16}>\n <IssueSection onIssue={issue} isSubmitting={isSubmitting} />\n </FadeIn>\n </div>\n )}\n </WalletRequired>\n );\n}\n"],"mappings":"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","names":["Link"]}
1
+ {"version":3,"sources":["../../src/components/pop-manage-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { buildPopAllowlist, popClaimLinks, popClaimLinksCsv, type PopClaimLink } from \"@medialane/sdk/starknet\";\nimport { ArrowLeft, Award, AlertCircle, CheckCircle2, Download, Loader2, Send, Users } from \"lucide-react\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { FadeIn } from \"./motion-primitives.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { WalletRequired } from \"./wallet-required.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useCollection } from \"../utils/use-collections.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nfunction parseAddresses(raw: string): string[] {\n return raw\n .split(/[\\n,\\s]+/)\n .map((a) => a.trim())\n .filter((a) => /^0x[0-9a-fA-F]+$/.test(a));\n}\n\nfunction downloadCsv(links: PopClaimLink[]) {\n const href = URL.createObjectURL(new Blob([popClaimLinksCsv(links)], { type: \"text/csv\" }));\n const anchor = Object.assign(document.createElement(\"a\"), { href, download: \"claim-links.csv\" });\n anchor.click();\n URL.revokeObjectURL(href);\n}\n\nfunction IssueSection({\n onIssue,\n isSubmitting,\n}: {\n onIssue: (address: string) => void;\n isSubmitting: boolean;\n}) {\n const [raw, setRaw] = useState(\"\");\n const address = raw.trim();\n const valid = /^0x[0-9a-fA-F]{1,64}$/.test(address);\n\n return (\n <div className=\"bento-cell p-5 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Award className=\"h-4 w-4 text-green-500\" />\n <span className=\"font-semibold text-sm\">Issue directly</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Send the credential straight to one wallet — for a late participant, without republishing the list or\n changing anyone&apos;s claim link.\n </p>\n <input\n type=\"text\"\n placeholder=\"0x...\"\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n className=\"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm tabular-nums placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring\"\n />\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n disabled={!valid || isSubmitting}\n onClick={() => {\n onIssue(address);\n setRaw(\"\");\n }}\n >\n <Send className=\"h-3.5 w-3.5 mr-1.5\" />\n Issue credential\n </Button>\n </div>\n );\n}\n\nfunction AllowlistSection({\n onPublish,\n isSubmitting,\n links,\n}: {\n onPublish: (addresses: string[]) => void;\n isSubmitting: boolean;\n links: PopClaimLink[] | null;\n}) {\n const [raw, setRaw] = useState(\"\");\n const parsed = parseAddresses(raw);\n\n return (\n <div className=\"bento-cell p-5 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Users className=\"h-4 w-4 text-green-500\" />\n <span className=\"font-semibold text-sm\">Participants</span>\n {parsed.length > 0 && (\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {parsed.length} address{parsed.length !== 1 ? \"es\" : \"\"}\n </span>\n )}\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Paste every participant&apos;s wallet address. Publishing replaces the previous list and every link\n sent before it — send the new links to everyone who hasn&apos;t claimed yet. The list stays in this\n browser: download the claim links and send each participant theirs.\n </p>\n <Textarea\n placeholder={\"Paste Starknet addresses, one per line:\\n0x04a...\\n0x06b...\"}\n rows={8}\n value={raw}\n onChange={(e) => setRaw(e.target.value)}\n className=\"tabular-nums text-xs resize-none\"\n />\n <Button\n size=\"sm\"\n className=\"w-full bg-green-600 hover:bg-green-700 text-white\"\n disabled={parsed.length === 0 || isSubmitting}\n onClick={() => onPublish(parsed)}\n >\n {isSubmitting ? (\n <>\n <Loader2 className=\"h-3.5 w-3.5 animate-spin mr-1.5\" />\n Publishing…\n </>\n ) : (\n <>\n <CheckCircle2 className=\"h-3.5 w-3.5 mr-1.5\" />\n Publish {parsed.length > 0 ? `${parsed.length} participant${parsed.length !== 1 ? \"s\" : \"\"}` : \"participants\"}\n </>\n )}\n </Button>\n {links && (\n <div className=\"space-y-2 pt-2\">\n <Button variant=\"outline\" size=\"sm\" className=\"w-full\" onClick={() => downloadCsv(links)}>\n <Download className=\"h-3.5 w-3.5 mr-1.5\" />\n Download claim links (CSV)\n </Button>\n <ul className=\"max-h-48 overflow-auto text-xs tabular-nums space-y-1 text-muted-foreground\">\n {links.map((link) => (\n <li key={link.address} className=\"truncate\">{link.address}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n\nexport function PopManagePage({ contract }: { contract: string }) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const { collection, isLoading } = useCollection(contract);\n const tx = useTransaction();\n const [done, setDone] = useState({ title: \"\", description: \"\" });\n const [links, setLinks] = useState<PopClaimLink[] | null>(null);\n const isSubmitting = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwner =\n walletAddress &&\n collection?.owner &&\n normalizeAddress(\"STARKNET\", walletAddress) === normalizeAddress(\"STARKNET\", collection.owner);\n\n const issue = (recipient: string) => {\n setDone(successMessages.credentialIssued());\n void tx.run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-manage\", { owner: signer.address, collection: contract, action: \"issue\", recipient }));\n });\n };\n\n const publish = (addresses: string[]) => {\n const list = buildPopAllowlist(addresses);\n const count = Object.keys(list.proofs).length;\n setDone(successMessages.participantsPublished({ count }));\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () => app.getClient().api.intents.create(\"pop-manage\", { owner: signer.address, collection: contract, action: \"set_allowlist_root\", root: list.root }));\n })\n .then((ok) => {\n if (ok) setLinks(popClaimLinks(window.location.origin, contract, list));\n });\n };\n\n return (\n <WalletRequired icon={Award} title=\"Connect your wallet\" description=\"Connect to manage your event.\">\n {isLoading ? (\n <div className=\"max-w-xl mx-auto px-4 pt-10 pb-16 space-y-4\">\n <Skeleton className=\"h-6 w-24\" />\n <Skeleton className=\"h-32 w-full rounded-2xl\" />\n <Skeleton className=\"h-64 w-full rounded-2xl\" />\n </div>\n ) : !collection ? (\n <div className=\"max-w-xl mx-auto px-4 pt-24 pb-8 text-center space-y-4\">\n <AlertCircle className=\"h-10 w-10 text-muted-foreground/20 mx-auto\" />\n <p className=\"text-muted-foreground\">Collection not found.</p>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/launchpad/pop\">← Back</Link>\n </Button>\n </div>\n ) : !isOwner ? (\n <div className=\"max-w-xl mx-auto px-4 pt-24 pb-8 text-center space-y-4\">\n <Award className=\"h-10 w-10 text-muted-foreground/20 mx-auto\" />\n <p className=\"text-muted-foreground\">You are not the organizer of this event.</p>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/launchpad/pop\">← Back to events</Link>\n </Button>\n </div>\n ) : (\n <div className=\"max-w-xl mx-auto px-4 pt-10 pb-16 space-y-6\">\n <TransactionDialog tx={tx} title=\"Manage event\" workingLabel=\"Updating your event…\" firstStepLabel=\"Prepare\">\n <TransactionSuccess name={collection.name ?? \"Event\"} title={done.title} description={done.description} txHash={tx.txHash} actions={[{ label: \"Done\", onClick: tx.reset }]} />\n </TransactionDialog>\n\n <FadeIn>\n <Button asChild variant=\"ghost\" size=\"sm\" className=\"-ml-2\">\n <Link href=\"/launchpad/pop\">\n <ArrowLeft className=\"h-3.5 w-3.5 mr-1.5\" />\n All events\n </Link>\n </Button>\n </FadeIn>\n\n <FadeIn delay={0.04}>\n <div>\n <span className=\"pill-badge inline-flex gap-1.5 mb-2\">\n <Award className=\"h-3 w-3\" />\n Organizer\n </span>\n <h1 className=\"text-2xl font-bold mt-1\">Manage Event</h1>\n <p className=\"text-sm text-muted-foreground\">{collection.name ?? contract}</p>\n </div>\n </FadeIn>\n\n <FadeIn delay={0.08}>\n <div className=\"bento-cell p-4 flex items-center gap-3\">\n <Award className=\"h-4 w-4 text-green-500 shrink-0\" />\n <p className=\"text-xs text-muted-foreground\">\n Only participants on your <strong className=\"text-foreground\">published list</strong> can claim,\n with the link you send them.\n </p>\n </div>\n </FadeIn>\n\n <FadeIn delay={0.12}>\n <AllowlistSection onPublish={publish} isSubmitting={isSubmitting} links={links} />\n </FadeIn>\n\n <FadeIn delay={0.16}>\n <IssueSection onIssue={issue} isSubmitting={isSubmitting} />\n </FadeIn>\n </div>\n )}\n </WalletRequired>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CM;AA7CN,mBAAyB;AACzB,iBAAiC;AACjC,sBAAsF;AACtF,0BAA4F;AAC5F,oBAAuB;AACvB,kBAAiB;AACjB,2BAAgC;AAChC,+BAAuB;AACvB,sBAAyB;AACzB,sBAAyB;AACzB,gCAAkC;AAClC,iCAAmC;AACnC,6BAA+B;AAC/B,8BAA+B;AAC/B,8BAAgC;AAChC,6BAA8B;AAC9B,6BAA+B;AAE/B,SAAS,eAAe,KAAuB;AAC7C,SAAO,IACJ,MAAM,UAAU,EAChB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,mBAAmB,KAAK,CAAC,CAAC;AAC7C;AAEA,SAAS,YAAY,OAAuB;AAC1C,QAAM,OAAO,IAAI,gBAAgB,IAAI,KAAK,KAAC,kCAAiB,KAAK,CAAC,GAAG,EAAE,MAAM,WAAW,CAAC,CAAC;AAC1F,QAAM,SAAS,OAAO,OAAO,SAAS,cAAc,GAAG,GAAG,EAAE,MAAM,UAAU,kBAAkB,CAAC;AAC/F,SAAO,MAAM;AACb,MAAI,gBAAgB,IAAI;AAC1B;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,KAAK,MAAM,QAAI,uBAAS,EAAE;AACjC,QAAM,UAAU,IAAI,KAAK;AACzB,QAAM,QAAQ,wBAAwB,KAAK,OAAO;AAElD,SACE,6CAAC,SAAI,WAAU,4BACb;AAAA,iDAAC,SAAI,WAAU,2BACb;AAAA,kDAAC,6BAAM,WAAU,0BAAyB;AAAA,MAC1C,4CAAC,UAAK,WAAU,yBAAwB,4BAAc;AAAA,OACxD;AAAA,IACA,4CAAC,OAAE,WAAU,iCAAgC,sJAG7C;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,aAAY;AAAA,QACZ,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,QACtC,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,WAAU;AAAA,QACV,UAAU,CAAC,SAAS;AAAA,QACpB,SAAS,MAAM;AACb,kBAAQ,OAAO;AACf,iBAAO,EAAE;AAAA,QACX;AAAA,QAEA;AAAA,sDAAC,4BAAK,WAAU,sBAAqB;AAAA,UAAE;AAAA;AAAA;AAAA,IAEzC;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,CAAC,KAAK,MAAM,QAAI,uBAAS,EAAE;AACjC,QAAM,SAAS,eAAe,GAAG;AAEjC,SACE,6CAAC,SAAI,WAAU,4BACb;AAAA,iDAAC,SAAI,WAAU,2BACb;AAAA,kDAAC,6BAAM,WAAU,0BAAyB;AAAA,MAC1C,4CAAC,UAAK,WAAU,yBAAwB,0BAAY;AAAA,MACnD,OAAO,SAAS,KACf,6CAAC,UAAK,WAAU,yCACb;AAAA,eAAO;AAAA,QAAO;AAAA,QAAS,OAAO,WAAW,IAAI,OAAO;AAAA,SACvD;AAAA,OAEJ;AAAA,IACA,4CAAC,OAAE,WAAU,iCAAgC,oRAI7C;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,aAAa;AAAA,QACb,MAAM;AAAA,QACN,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,OAAO,EAAE,OAAO,KAAK;AAAA,QACtC,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,UAAU,OAAO,WAAW,KAAK;AAAA,QACjC,SAAS,MAAM,UAAU,MAAM;AAAA,QAE9B,yBACC,4EACE;AAAA,sDAAC,+BAAQ,WAAU,mCAAkC;AAAA,UAAE;AAAA,WAEzD,IAEA,4EACE;AAAA,sDAAC,oCAAa,WAAU,sBAAqB;AAAA,UAAE;AAAA,UACtC,OAAO,SAAS,IAAI,GAAG,OAAO,MAAM,eAAe,OAAO,WAAW,IAAI,MAAM,EAAE,KAAK;AAAA,WACjG;AAAA;AAAA,IAEJ;AAAA,IACC,SACC,6CAAC,SAAI,WAAU,kBACb;AAAA,mDAAC,wBAAO,SAAQ,WAAU,MAAK,MAAK,WAAU,UAAS,SAAS,MAAM,YAAY,KAAK,GACrF;AAAA,oDAAC,gCAAS,WAAU,sBAAqB;AAAA,QAAE;AAAA,SAE7C;AAAA,MACA,4CAAC,QAAG,WAAU,+EACX,gBAAM,IAAI,CAAC,SACV,4CAAC,QAAsB,WAAU,YAAY,eAAK,WAAzC,KAAK,OAA4C,CAC3D,GACH;AAAA,OACF;AAAA,KAEJ;AAEJ;AAEO,SAAS,cAAc,EAAE,SAAS,GAAyB;AAChE,QAAM,UAAM,sCAAgB;AAC5B,QAAM,gBAAgB,IAAI;AAC1B,QAAM,EAAE,YAAY,UAAU,QAAI,sCAAc,QAAQ;AACxD,QAAM,SAAK,uCAAe;AAC1B,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,EAAE,OAAO,IAAI,aAAa,GAAG,CAAC;AAC/D,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAgC,IAAI;AAC9D,QAAM,eAAe,GAAG,UAAU,eAAe,GAAG,UAAU,gBAAgB,GAAG,UAAU;AAE3F,QAAM,UACJ,iBACA,YAAY,aACZ,6BAAiB,YAAY,aAAa,UAAM,6BAAiB,YAAY,WAAW,KAAK;AAE/F,QAAM,QAAQ,CAAC,cAAsB;AACnC,YAAQ,wCAAgB,iBAAiB,CAAC;AAC1C,SAAK,GAAG,IAAI,OAAO,WAAW;AAC5B,gBAAM,wCAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,cAAc,EAAE,OAAO,OAAO,SAAS,YAAY,UAAU,QAAQ,SAAS,UAAU,CAAC,CAAC;AAAA,IAClK,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,CAAC,cAAwB;AACvC,UAAM,WAAO,mCAAkB,SAAS;AACxC,UAAM,QAAQ,OAAO,KAAK,KAAK,MAAM,EAAE;AACvC,YAAQ,wCAAgB,sBAAsB,EAAE,MAAM,CAAC,CAAC;AACxD,SAAK,GACF,IAAI,OAAO,WAAW;AACrB,gBAAM,wCAAe,QAAQ,MAAM,IAAI,UAAU,EAAE,IAAI,QAAQ,OAAO,cAAc,EAAE,OAAO,OAAO,SAAS,YAAY,UAAU,QAAQ,sBAAsB,MAAM,KAAK,KAAK,CAAC,CAAC;AAAA,IACrL,CAAC,EACA,KAAK,CAAC,OAAO;AACZ,UAAI,GAAI,cAAS,+BAAc,OAAO,SAAS,QAAQ,UAAU,IAAI,CAAC;AAAA,IACxE,CAAC;AAAA,EACL;AAEA,SACE,4CAAC,yCAAe,MAAM,2BAAO,OAAM,uBAAsB,aAAY,iCAClE,sBACC,6CAAC,SAAI,WAAU,+CACb;AAAA,gDAAC,4BAAS,WAAU,YAAW;AAAA,IAC/B,4CAAC,4BAAS,WAAU,2BAA0B;AAAA,IAC9C,4CAAC,4BAAS,WAAU,2BAA0B;AAAA,KAChD,IACE,CAAC,aACH,6CAAC,SAAI,WAAU,0DACb;AAAA,gDAAC,mCAAY,WAAU,8CAA6C;AAAA,IACpE,4CAAC,OAAE,WAAU,yBAAwB,mCAAqB;AAAA,IAC1D,4CAAC,wBAAO,SAAO,MAAC,SAAQ,WAAU,MAAK,MACrC,sDAAC,YAAAA,SAAA,EAAK,MAAK,kBAAiB,yBAAM,GACpC;AAAA,KACF,IACE,CAAC,UACH,6CAAC,SAAI,WAAU,0DACb;AAAA,gDAAC,6BAAM,WAAU,8CAA6C;AAAA,IAC9D,4CAAC,OAAE,WAAU,yBAAwB,sDAAwC;AAAA,IAC7E,4CAAC,wBAAO,SAAO,MAAC,SAAQ,WAAU,MAAK,MACrC,sDAAC,YAAAA,SAAA,EAAK,MAAK,kBAAiB,mCAAgB,GAC9C;AAAA,KACF,IAEA,6CAAC,SAAI,WAAU,+CACb;AAAA,gDAAC,+CAAkB,IAAQ,OAAM,gBAAe,cAAa,6BAAuB,gBAAe,WACjG,sDAAC,iDAAmB,MAAM,WAAW,QAAQ,SAAS,OAAO,KAAK,OAAO,aAAa,KAAK,aAAa,QAAQ,GAAG,QAAQ,SAAS,CAAC,EAAE,OAAO,QAAQ,SAAS,GAAG,MAAM,CAAC,GAAG,GAC9K;AAAA,IAEA,4CAAC,mCACC,sDAAC,wBAAO,SAAO,MAAC,SAAQ,SAAQ,MAAK,MAAK,WAAU,SAClD,uDAAC,YAAAA,SAAA,EAAK,MAAK,kBACT;AAAA,kDAAC,iCAAU,WAAU,sBAAqB;AAAA,MAAE;AAAA,OAE9C,GACF,GACF;AAAA,IAEA,4CAAC,mCAAO,OAAO,MACb,uDAAC,SACC;AAAA,mDAAC,UAAK,WAAU,uCACd;AAAA,oDAAC,6BAAM,WAAU,WAAU;AAAA,QAAE;AAAA,SAE/B;AAAA,MACA,4CAAC,QAAG,WAAU,2BAA0B,0BAAY;AAAA,MACpD,4CAAC,OAAE,WAAU,iCAAiC,qBAAW,QAAQ,UAAS;AAAA,OAC5E,GACF;AAAA,IAEA,4CAAC,mCAAO,OAAO,MACb,uDAAC,SAAI,WAAU,0CACb;AAAA,kDAAC,6BAAM,WAAU,mCAAkC;AAAA,MACnD,6CAAC,OAAE,WAAU,iCAAgC;AAAA;AAAA,QACjB,4CAAC,YAAO,WAAU,mBAAkB,4BAAc;AAAA,QAAS;AAAA,SAEvF;AAAA,OACF,GACF;AAAA,IAEA,4CAAC,mCAAO,OAAO,MACb,sDAAC,oBAAiB,WAAW,SAAS,cAA4B,OAAc,GAClF;AAAA,IAEA,4CAAC,mCAAO,OAAO,MACb,sDAAC,gBAAa,SAAS,OAAO,cAA4B,GAC5D;AAAA,KACF,GAEJ;AAEJ;","names":["Link"]}
@@ -14,6 +14,7 @@ import { TransactionDialog } from "./transaction-dialog.js";
14
14
  import { TransactionSuccess } from "./transaction-success.js";
15
15
  import { WalletRequired } from "./wallet-required.js";
16
16
  import { runIntentCalls } from "../utils/run-intent-calls.js";
17
+ import { successMessages } from "../utils/success-messages.js";
17
18
  import { useCollection } from "../utils/use-collections.js";
18
19
  import { useTransaction } from "../utils/use-transaction.js";
19
20
  function parseAddresses(raw) {
@@ -131,7 +132,7 @@ function PopManagePage({ contract }) {
131
132
  const isSubmitting = tx.phase === "preparing" || tx.phase === "submitting" || tx.phase === "confirming";
132
133
  const isOwner = walletAddress && collection?.owner && normalizeAddress("STARKNET", walletAddress) === normalizeAddress("STARKNET", collection.owner);
133
134
  const issue = (recipient) => {
134
- setDone({ title: "Credential issued", description: "The credential is now in their wallet." });
135
+ setDone(successMessages.credentialIssued());
135
136
  void tx.run(async (signer) => {
136
137
  await runIntentCalls(signer, () => app.getClient().api.intents.create("pop-manage", { owner: signer.address, collection: contract, action: "issue", recipient }));
137
138
  });
@@ -139,7 +140,7 @@ function PopManagePage({ contract }) {
139
140
  const publish = (addresses) => {
140
141
  const list = buildPopAllowlist(addresses);
141
142
  const count = Object.keys(list.proofs).length;
142
- setDone({ title: "Participants published", description: `Published ${count} participant${count !== 1 ? "s" : ""}.` });
143
+ setDone(successMessages.participantsPublished({ count }));
143
144
  void tx.run(async (signer) => {
144
145
  await runIntentCalls(signer, () => app.getClient().api.intents.create("pop-manage", { owner: signer.address, collection: contract, action: "set_allowlist_root", root: list.root }));
145
146
  }).then((ok) => {