@medialane/ui 0.311.0 → 0.313.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 (55) hide show
  1. package/dist/components/account/input-otp.d.cts +2 -2
  2. package/dist/components/account/input-otp.d.ts +2 -2
  3. package/dist/components/account-page.cjs +48 -46
  4. package/dist/components/account-page.cjs.map +1 -1
  5. package/dist/components/account-page.js +48 -46
  6. package/dist/components/account-page.js.map +1 -1
  7. package/dist/components/button.d.cts +2 -2
  8. package/dist/components/button.d.ts +2 -2
  9. package/dist/components/launchpad/edition-mint-schema.d.cts +19 -19
  10. package/dist/components/launchpad/edition-mint-schema.d.ts +19 -19
  11. package/dist/components/launchpad/pop-create-schema.d.cts +10 -10
  12. package/dist/components/launchpad/pop-create-schema.d.ts +10 -10
  13. package/dist/components/media-wallet/media-wallet-send.cjs +2 -5
  14. package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
  15. package/dist/components/media-wallet/media-wallet-send.js +2 -5
  16. package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
  17. package/dist/components/portfolio-header.cjs +4 -1
  18. package/dist/components/portfolio-header.cjs.map +1 -1
  19. package/dist/components/portfolio-header.d.cts +4 -1
  20. package/dist/components/portfolio-header.d.ts +4 -1
  21. package/dist/components/portfolio-header.js +4 -1
  22. package/dist/components/portfolio-header.js.map +1 -1
  23. package/dist/components/token-card.cjs +2 -2
  24. package/dist/components/token-card.cjs.map +1 -1
  25. package/dist/components/token-card.js +2 -2
  26. package/dist/components/token-card.js.map +1 -1
  27. package/dist/components/transfer-collection-ownership.cjs +1 -1
  28. package/dist/components/transfer-collection-ownership.cjs.map +1 -1
  29. package/dist/components/transfer-collection-ownership.js +1 -1
  30. package/dist/components/transfer-collection-ownership.js.map +1 -1
  31. package/dist/index.d.cts +0 -1
  32. package/dist/index.d.ts +0 -1
  33. package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
  34. package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
  35. package/dist/utils/send-token.cjs +40 -0
  36. package/dist/utils/send-token.cjs.map +1 -0
  37. package/dist/utils/send-token.d.cts +19 -0
  38. package/dist/utils/send-token.d.ts +19 -0
  39. package/dist/utils/send-token.js +16 -0
  40. package/dist/utils/send-token.js.map +1 -0
  41. package/dist/utils/use-collection-settings.d.cts +19 -19
  42. package/dist/utils/use-collection-settings.d.ts +19 -19
  43. package/dist/utils/use-collections.d.cts +212 -205
  44. package/dist/utils/use-collections.d.ts +212 -205
  45. package/dist/utils/use-orders.d.cts +299 -299
  46. package/dist/utils/use-orders.d.ts +299 -299
  47. package/dist/utils/use-pop.d.cts +57 -55
  48. package/dist/utils/use-pop.d.ts +57 -55
  49. package/dist/utils/use-tiers.d.cts +76 -73
  50. package/dist/utils/use-tiers.d.ts +76 -73
  51. package/dist/utils/use-tokens-by-ip-type.d.cts +78 -77
  52. package/dist/utils/use-tokens-by-ip-type.d.ts +78 -77
  53. package/dist/utils/use-tokens.d.cts +234 -229
  54. package/dist/utils/use-tokens.d.ts +234 -229
  55. package/package.json +3 -3
@@ -1,13 +1,13 @@
1
- import * as zod from 'zod';
1
+ import * as z from 'zod';
2
2
 
3
- declare const popCreateSchema: zod.ZodEffects<zod.ZodObject<{
4
- name: zod.ZodString;
5
- symbol: zod.ZodString;
6
- description: zod.ZodOptional<zod.ZodString>;
7
- external_link: zod.ZodOptional<zod.ZodEffects<zod.ZodString, string, string>>;
8
- claimEndDate: zod.ZodString;
9
- claimEndTime: zod.ZodDefault<zod.ZodString>;
10
- }, "strip", zod.ZodTypeAny, {
3
+ declare const popCreateSchema: z.ZodEffects<z.ZodObject<{
4
+ name: z.ZodString;
5
+ symbol: z.ZodString;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ external_link: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
8
+ claimEndDate: z.ZodString;
9
+ claimEndTime: z.ZodDefault<z.ZodString>;
10
+ }, "strip", z.ZodTypeAny, {
11
11
  symbol: string;
12
12
  name: string;
13
13
  claimEndDate: string;
@@ -36,6 +36,6 @@ declare const popCreateSchema: zod.ZodEffects<zod.ZodObject<{
36
36
  external_link?: string | undefined;
37
37
  claimEndTime?: string | undefined;
38
38
  }>;
39
- type PopCreateValues = zod.infer<typeof popCreateSchema>;
39
+ type PopCreateValues = z.infer<typeof popCreateSchema>;
40
40
 
41
41
  export { type PopCreateValues, popCreateSchema };
@@ -1,13 +1,13 @@
1
- import * as zod from 'zod';
1
+ import * as z from 'zod';
2
2
 
3
- declare const popCreateSchema: zod.ZodEffects<zod.ZodObject<{
4
- name: zod.ZodString;
5
- symbol: zod.ZodString;
6
- description: zod.ZodOptional<zod.ZodString>;
7
- external_link: zod.ZodOptional<zod.ZodEffects<zod.ZodString, string, string>>;
8
- claimEndDate: zod.ZodString;
9
- claimEndTime: zod.ZodDefault<zod.ZodString>;
10
- }, "strip", zod.ZodTypeAny, {
3
+ declare const popCreateSchema: z.ZodEffects<z.ZodObject<{
4
+ name: z.ZodString;
5
+ symbol: z.ZodString;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ external_link: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
8
+ claimEndDate: z.ZodString;
9
+ claimEndTime: z.ZodDefault<z.ZodString>;
10
+ }, "strip", z.ZodTypeAny, {
11
11
  symbol: string;
12
12
  name: string;
13
13
  claimEndDate: string;
@@ -36,6 +36,6 @@ declare const popCreateSchema: zod.ZodEffects<zod.ZodObject<{
36
36
  external_link?: string | undefined;
37
37
  claimEndTime?: string | undefined;
38
38
  }>;
39
- type PopCreateValues = zod.infer<typeof popCreateSchema>;
39
+ type PopCreateValues = z.infer<typeof popCreateSchema>;
40
40
 
41
41
  export { type PopCreateValues, popCreateSchema };
@@ -39,7 +39,7 @@ var import_wallet_tokens = require("../../utils/media-wallet/wallet-tokens.js");
39
39
  var import_success_dialog = require("./success-dialog.js");
40
40
  var import_types = require("./types.js");
41
41
  var import_address = require("../../utils/address.js");
42
- var import_run_intent_calls = require("../../utils/run-intent-calls.js");
42
+ var import_send_token = require("../../utils/send-token.js");
43
43
  var import_success_messages = require("../../utils/success-messages.js");
44
44
  var import_medialane_app = require("../medialane-app.js");
45
45
  function isValidStarknetAddress(address) {
@@ -122,10 +122,7 @@ function MediaWalletSend({
122
122
  const dest = to.trim();
123
123
  const amt = amountRaw;
124
124
  await run(async (signer) => {
125
- const result = await (0, import_run_intent_calls.runIntentCalls)(
126
- signer,
127
- () => getClient().api.intents.create("transfer-token", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() })
128
- );
125
+ const result = await (0, import_send_token.sendToken)(signer, getClient(), { token: currency.address, recipient: dest, amount: amt });
129
126
  setTxHash(result.txHash);
130
127
  return result;
131
128
  });
@@ -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 { 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"]}
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 { sendToken } from \"../../utils/send-token.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 sendToken(signer, getClient(), { token: currency.address, recipient: dest, amount: amt });\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"]}
@@ -16,7 +16,7 @@ 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
18
  import { shortenAddress } from "../../utils/address.js";
19
- import { runIntentCalls } from "../../utils/run-intent-calls.js";
19
+ import { sendToken } from "../../utils/send-token.js";
20
20
  import { successMessages } from "../../utils/success-messages.js";
21
21
  import { useMedialaneApp } from "../medialane-app.js";
22
22
  function isValidStarknetAddress(address) {
@@ -99,10 +99,7 @@ function MediaWalletSend({
99
99
  const dest = to.trim();
100
100
  const amt = amountRaw;
101
101
  await run(async (signer) => {
102
- const result = await runIntentCalls(
103
- signer,
104
- () => getClient().api.intents.create("transfer-token", { owner: signer.address, token: currency.address, recipient: dest, amount: amt.toString() })
105
- );
102
+ const result = await sendToken(signer, getClient(), { token: currency.address, recipient: dest, amount: amt });
106
103
  setTxHash(result.txHash);
107
104
  return result;
108
105
  });
@@ -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 { 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":";AA+HM,SACE,KADF;AA7HN,SAAS,gBAAgB;AACzB,SAAS,SAAS,UAAU,OAAO,+BAAkE;AACrG,SAAS,aAAa,oBAAoB;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB,uBAAuB;AACjD,SAAS,KAAK,aAAa;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,aAAa,mBAAmB;AACzC,SAAS,qBAAqB;AAC9B,SAAS,qBAAuC;AAChD,SAAS,qBAAqB;AAC9B,SAAS,yBAA+C;AACxD,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAEhC,SAAS,uBAAuB,SAA0B;AACxD,MAAI;AACF,4BAAwB,QAAQ,KAAK,CAAC;AACtC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,gBAAgB,UAA6B,SAAiB,OAAe,IAAY,WAAmB;AACzH,QAAM,UAAU,IAAI,QAAQ,EAAE,UAAU,SAAS,QAAQ,OAAO,cAAc,IAAI,CAAC;AACnF,QAAM,OAAa;AAAA,IACjB,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,UAAU,SAAS,QAAQ,EAAE,WAAW,IAAI,QAAQ,MAAM,QAAQ,SAAS,EAAE,CAAC;AAAA,EAChF;AACA,QAAM,MAAM,MAAM,QAAQ,kBAAkB,IAAI;AAChD,SAAO,EAAE,QAAQ,IAAI,aAAa,MAAM,IAAI,KAAK;AACnD;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,EAAE,kBAAkB,eAAe,IAAI,kBAAkB;AAC/D,QAAM,EAAE,UAAU,IAAI,gBAAgB;AACtC,QAAM,EAAE,QAAQ,IAAI,iBAAiB;AACrC,QAAM,EAAE,KAAK,QAAQ,OAAO,MAAM,IAAI,eAAe;AAErD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAsB,gBAAgB,cAAc,CAAC,CAAC;AACtF,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC5C,QAAM,MAAM,gBAAgB,OAAO,OAAO;AAC1C,QAAM,OAAO,gBAAgB,QAAQ,OAAO;AAC5C,QAAM,OAAO,gBAAgB,QAAQ,OAAO;AAE5C,QAAM,yBAAwD;AAAA,IAC5D,MAAM,KAAK;AAAA,IAAY,KAAK,IAAI;AAAA,IAAY,MAAM,KAAK;AAAA,IAAY,MAAM,KAAK;AAAA,EAChF;AACA,QAAM,EAAE,YAAY,gBAAgB,IAAI,gBAAgB,SAAS,SAAS,OAAO;AAEjF,QAAM,CAAC,IAAI,KAAK,IAAI,SAAS,EAAE;AAC/B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AACvC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAwB,IAAI;AAExD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,KAAK,MAAM,IAAI,SAA+C,IAAI;AACzE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAE5D,QAAM,iBAAiB,uBAAuB,EAAE;AAChD,QAAM,cAAc,gBAAgB,KAAK,EAAE,QAAQ,OAAO,KAAK,GAAG,QAAQ,SAAS,QAAQ,IAAI,eAAe,GAAG,KAAK,CAAC,EAAE,CAAC;AAC1H,MAAI;AACJ,MAAI;AACF,gBAAY,OAAO,KAAK,IAAI,OAAO,YAAY,OAAO,KAAK,GAAG,SAAS,QAAQ,CAAC,IAAI;AAAA,EACtF,QAAQ;AACN,gBAAY;AAAA,EACd;AACA,QAAM,oBAAoB,aAAa,QAAQ,mBAAmB,QAAQ,YAAY;AACtF,QAAM,eAAe,kBAAkB,aAAa,QAAQ,YAAY,MAAM,CAAC;AAE/E,QAAM,iBAAiB,YAAY;AACjC,QAAI;AACF,YAAM,OAAO,MAAM,UAAU,UAAU,SAAS;AAChD,UAAI,KAAM,OAAM,KAAK,KAAK,CAAC;AAAA,IAC7B,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AACnB,QAAI,mBAAmB,KAAM;AAC7B,cAAU,aAAa,gBAAgB,SAAS,GAAG,SAAS,QAAQ,CAAC;AAAA,EACvE;AAEA,QAAM,aAAa,MAAM;AACvB,QAAI,CAAC,WAAW,CAAC,gBAAgB,aAAa,KAAM;AACpD,gBAAY,IAAI;AAChB,WAAO,IAAI;AACX,mBAAe,IAAI;AACnB,oBAAgB,UAAU,EAAE,UAAU,SAAS,SAAS,SAAS,GAAG,KAAK,GAAG,SAAS,EAClF,KAAK,CAAC,MAAM,OAAO,EAAE,KAAK,EAAE,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,EACnD,MAAM,CAAC,MAAM,YAAY,cAAc,CAAC,EAAE,OAAO,CAAC;AAAA,EACvD;AAEA,QAAM,OAAO,YAAY;AACvB,QAAI,CAAC,gBAAgB,aAAa,KAAM;AACxC,mBAAe,KAAK;AACpB,UAAM,OAAO,GAAG,KAAK;AACrB,UAAM,MAAM;AACZ,UAAM,IAAI,OAAO,WAAW;AAC1B,YAAM,SAAS,MAAM;AAAA,QAAe;AAAA,QAAQ,MAC1C,UAAU,EAAE,IAAI,QAAQ,OAAO,kBAAkB,EAAE,OAAO,OAAO,SAAS,OAAO,SAAS,SAAS,WAAW,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;AAAA,MAC9I;AACA,gBAAU,OAAO,MAAM;AACvB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SACE,qBAAC,UAAK,WAAU,sCACd;AAAA,yBAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,cAAW,QAAQ,MAAM,WAAW,EAAE,MAAM,OAAO,CAAC,GAAG;AAAA,MACxD,oBAAC,QAAG,WAAU,iFAAgF,kBAAI;AAAA,OACpG;AAAA,IAEC,SACC,oBAAC,SAAI,WAAU,0FACZ,iBACH;AAAA,IAGF,qBAAC,SAAI,WAAU,uBACb;AAAA,2BAAC,SACC;AAAA,6BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,MAAM,EAAE,OAAO,KAAK;AAAA,cACrC,aAAY;AAAA,cACZ,YAAY;AAAA,cACZ,WAAU;AAAA;AAAA,UACZ;AAAA,UACC,GAAG,KAAK,MAAM,MACb;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA,WAEJ;AAAA,QACC,GAAG,KAAK,MAAM,MAAM,CAAC,kBACpB,oBAAC,OAAE,WAAU,wCAAuC,2CAA6B;AAAA,SAErF;AAAA,MAEA,qBAAC,SACC;AAAA,6BAAC,SAAI,WAAU,YACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,cACP,UAAU,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,QAAQ,YAAY,EAAE,CAAC;AAAA,cACjE,aAAY;AAAA,cACZ,WAAU;AAAA,cACV,WAAU;AAAA;AAAA,UACZ;AAAA,UACA,qBAAC,SAAI,WAAU,yEACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,MAAM,cAAc,IAAI;AAAA,gBACjC,WAAU;AAAA,gBAEV;AAAA,sCAAC,gBAAa,QAAQ,SAAS,QAAQ,MAAM,IAAI;AAAA,kBAAE;AAAA,kBAAE,SAAS;AAAA;AAAA;AAAA,YAChE;AAAA,aACF;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,iDACb;AAAA,+BAAC,UAAK,WAAU,iCAAgC;AAAA;AAAA,YACpC,mBAAmB,OAAO,IAAI,iBAAiB,SAAS,QAAQ,IAAI;AAAA,aAChF;AAAA,UACC,qBAAqB,oBAAC,UAAK,WAAU,4BAA2B,qCAAuB;AAAA,WAC1F;AAAA,SACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,QAAO;AAAA,UACP,KAAG;AAAA,UACH,SAAS;AAAA,UACT,UAAU,WAAW,gBAAgB,CAAC;AAAA,UACtC,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,oBAAC,aAAU,uFAAyE;AAAA,OACtF;AAAA,IAEC,cACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU,CAAC,MAAM;AACf,sBAAY,CAAC;AACb,wBAAc,KAAK;AAAA,QACrB;AAAA,QACA,SAAS,MAAM,cAAc,KAAK;AAAA;AAAA,IACpC;AAAA,IAGD,eACC,oBAAC,eAAY,OAAM,mBAAkB,SAAS,MAAM,eAAe,KAAK,GACtE,+BAAC,SAAI,WAAU,uBACb;AAAA,2BAAC,SAAI,WAAU,2BACb;AAAA,4BAAC,SAAI,WAAU,gFACb,8BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI,8BAAC,UAAK,GAAE,wCAAuC,GACjD,GACF;AAAA,QACA,qBAAC,SAAI,WAAU,kBACb;AAAA,8BAAC,SAAI,WAAU,iBAAgB,kBAAI;AAAA,UACnC,qBAAC,SAAI,WAAU,oDAAmD;AAAA;AAAA,YAAK,MAAM,GAAG,KAAK,CAAC;AAAA,aAAE;AAAA,WAC1F;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,gEACb;AAAA,4BAAC,gBAAa,QAAQ,SAAS,QAAQ,MAAM,IAAI;AAAA,QACjD,oBAAC,SAAI,WAAU,gCAAgC,mBAAS,QAAO;AAAA,QAC/D,qBAAC,SAAI,WAAU,yCAAwC;AAAA;AAAA,UACnD,OAAO,KAAK;AAAA,UAAE;AAAA,UAAE,SAAS;AAAA,WAC7B;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,iFACb;AAAA,6BAAC,SAAI,WAAU,kDACb;AAAA,8BAAC,UAAK,WAAU,yBAAwB,oBAAM;AAAA,UAC9C,qBAAC,UAAK,WAAU,eAAe;AAAA,mBAAO,KAAK;AAAA,YAAE;AAAA,YAAE,SAAS;AAAA,aAAO;AAAA,WACjE;AAAA,QACA,qBAAC,SAAI,WAAU,kDACb;AAAA,8BAAC,UAAK,WAAU,yBAAwB,uBAAS;AAAA,UACjD,oBAAC,UAAK,WAAU,yBAAyB,gBAAM,GAAG,KAAK,CAAC,GAAE;AAAA,WAC5D;AAAA,QACA,qBAAC,SAAI,WAAU,kDACb;AAAA,8BAAC,UAAK,WAAU,yBAAwB,sBAAQ;AAAA,UAChD,oBAAC,UAAK,WAAU,eAAe,mBAAS,QAAO;AAAA,WACjD;AAAA,QACA,qBAAC,SAAI,WAAU,kDACb;AAAA,8BAAC,UAAK,WAAU,yBAAwB,kBAAI;AAAA,UAC5C,oBAAC,UAAK,WAAU,yBAAwB,sBAAQ;AAAA,WAClD;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,wFACb;AAAA,4BAAC,UAAK,WAAU,yBAAwB,2BAAa;AAAA,QACrD,oBAAC,UAAK,WAAU,eACb,qBAAW,gBAAgB,MAAM,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,QAAQ,SAAS,KAAK,KAAK,oBACtG;AAAA,SACF;AAAA,MACC,YAAY,qBAAC,OAAE,WAAU,iCAAgC;AAAA;AAAA,QAAsB;AAAA,SAAS;AAAA,MAEzF,qBAAC,SAAI,WAAU,cACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,eAAe,KAAK;AAAA,YACnC,WAAU;AAAA,YACX;AAAA;AAAA,QAED;AAAA,QACA,oBAAC,gBAAa,QAAO,SAAQ,KAAG,MAAC,SAAS,MAAM,WAAU,UAAS,qBAEnE;AAAA,SACF;AAAA,OACF,GACF;AAAA,IAGD,WAAW,gBAAgB,oBAAC,eAAY,OAAM,2BAAqB;AAAA,IACnE,WAAW,aAAa,UACvB;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,YAAY;AAAA,QACnB,SAAS,YAAY;AAAA,QACrB;AAAA,QACA,SAAS,MAAM;AACb,gBAAM;AACN,iBAAO;AAAA,QACT;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;","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 { sendToken } from \"../../utils/send-token.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 sendToken(signer, getClient(), { token: currency.address, recipient: dest, amount: amt });\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":[]}
@@ -39,6 +39,8 @@ var import_address_display = require("./address-display.js");
39
39
  function PortfolioHeader({
40
40
  address,
41
41
  score,
42
+ label = "Portfolio",
43
+ trailing,
42
44
  className
43
45
  }) {
44
46
  const scoreChip = score && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white", children: [
@@ -50,7 +52,7 @@ function PortfolioHeader({
50
52
  ] });
51
53
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_cn.cn)("flex items-center justify-between gap-4", className), children: [
52
54
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0", children: [
53
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: "Portfolio" }),
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: label }),
54
56
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
55
57
  import_address_display.AddressDisplay,
56
58
  {
@@ -60,6 +62,7 @@ function PortfolioHeader({
60
62
  }
61
63
  )
62
64
  ] }),
65
+ trailing,
63
66
  score?.href ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: score.href, className: "shrink-0 active:opacity-80", children: scoreChip }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "shrink-0", children: scoreChip })
64
67
  ] });
65
68
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/portfolio-header.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { AddressDisplay } from \"./address-display.js\";\n\nexport interface PortfolioHeaderScore {\n\n levelName: string;\n totalXp: number;\n\n href?: string;\n}\n\nexport interface PortfolioHeaderProps {\n address: string;\n score?: PortfolioHeaderScore | null;\n className?: string;\n}\n\nexport function PortfolioHeader({\n address,\n score,\n className,\n}: PortfolioHeaderProps) {\n const scoreChip = score && (\n <div className=\"rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white\">\n <span className=\"text-sm font-bold\">\n {score.levelName}\n </span>\n <span className=\"text-xs font-medium text-white/80 tabular-nums\">\n {score.totalXp.toLocaleString()} XP\n </span>\n </div>\n );\n\n return (\n <div className={cn(\"flex items-center justify-between gap-4\", className)}>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n Portfolio\n </p>\n <AddressDisplay\n address={address}\n chars={6}\n className=\"text-2xl sm:text-3xl font-black tracking-tight text-foreground\"\n />\n </div>\n {score?.href ? (\n <Link href={score.href} className=\"shrink-0 active:opacity-80\">\n {scoreChip}\n </Link>\n ) : (\n <div className=\"shrink-0\">{scoreChip}</div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BM;AAzBN,kBAAiB;AACjB,gBAAmB;AACnB,6BAA+B;AAgBxB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,YAAY,SAChB,6CAAC,SAAI,WAAU,uIACb;AAAA,gDAAC,UAAK,WAAU,qBACb,gBAAM,WACT;AAAA,IACA,6CAAC,UAAK,WAAU,kDACb;AAAA,YAAM,QAAQ,eAAe;AAAA,MAAE;AAAA,OAClC;AAAA,KACF;AAGF,SACE,6CAAC,SAAI,eAAW,cAAG,2CAA2C,SAAS,GACrE;AAAA,iDAAC,SAAI,WAAU,WACb;AAAA,kDAAC,OAAE,WAAU,6CAA4C,uBAEzD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO;AAAA,UACP,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC,OAAO,OACN,4CAAC,YAAAA,SAAA,EAAK,MAAM,MAAM,MAAM,WAAU,8BAC/B,qBACH,IAEA,4CAAC,SAAI,WAAU,YAAY,qBAAU;AAAA,KAEzC;AAEJ;","names":["Link"]}
1
+ {"version":3,"sources":["../../src/components/portfolio-header.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Link from \"./link.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { AddressDisplay } from \"./address-display.js\";\n\nexport interface PortfolioHeaderScore {\n\n levelName: string;\n totalXp: number;\n\n href?: string;\n}\n\nexport interface PortfolioHeaderProps {\n address: string;\n score?: PortfolioHeaderScore | null;\n label?: string;\n trailing?: ReactNode;\n className?: string;\n}\n\nexport function PortfolioHeader({\n address,\n score,\n label = \"Portfolio\",\n trailing,\n className,\n}: PortfolioHeaderProps) {\n const scoreChip = score && (\n <div className=\"rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white\">\n <span className=\"text-sm font-bold\">\n {score.levelName}\n </span>\n <span className=\"text-xs font-medium text-white/80 tabular-nums\">\n {score.totalXp.toLocaleString()} XP\n </span>\n </div>\n );\n\n return (\n <div className={cn(\"flex items-center justify-between gap-4\", className)}>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {label}\n </p>\n <AddressDisplay\n address={address}\n chars={6}\n className=\"text-2xl sm:text-3xl font-black tracking-tight text-foreground\"\n />\n </div>\n {trailing}\n {score?.href ? (\n <Link href={score.href} className=\"shrink-0 active:opacity-80\">\n {scoreChip}\n </Link>\n ) : (\n <div className=\"shrink-0\">{scoreChip}</div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCM;AA7BN,kBAAiB;AACjB,gBAAmB;AACnB,6BAA+B;AAkBxB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,YAAY,SAChB,6CAAC,SAAI,WAAU,uIACb;AAAA,gDAAC,UAAK,WAAU,qBACb,gBAAM,WACT;AAAA,IACA,6CAAC,UAAK,WAAU,kDACb;AAAA,YAAM,QAAQ,eAAe;AAAA,MAAE;AAAA,OAClC;AAAA,KACF;AAGF,SACE,6CAAC,SAAI,eAAW,cAAG,2CAA2C,SAAS,GACrE;AAAA,iDAAC,SAAI,WAAU,WACb;AAAA,kDAAC,OAAE,WAAU,6CACV,iBACH;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO;AAAA,UACP,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC;AAAA,IACA,OAAO,OACN,4CAAC,YAAAA,SAAA,EAAK,MAAM,MAAM,MAAM,WAAU,8BAC/B,qBACH,IAEA,4CAAC,SAAI,WAAU,YAAY,qBAAU;AAAA,KAEzC;AAEJ;","names":["Link"]}
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
 
3
4
  interface PortfolioHeaderScore {
4
5
  levelName: string;
@@ -8,8 +9,10 @@ interface PortfolioHeaderScore {
8
9
  interface PortfolioHeaderProps {
9
10
  address: string;
10
11
  score?: PortfolioHeaderScore | null;
12
+ label?: string;
13
+ trailing?: ReactNode;
11
14
  className?: string;
12
15
  }
13
- declare function PortfolioHeader({ address, score, className, }: PortfolioHeaderProps): react_jsx_runtime.JSX.Element;
16
+ declare function PortfolioHeader({ address, score, label, trailing, className, }: PortfolioHeaderProps): react_jsx_runtime.JSX.Element;
14
17
 
15
18
  export { PortfolioHeader, type PortfolioHeaderProps, type PortfolioHeaderScore };
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
 
3
4
  interface PortfolioHeaderScore {
4
5
  levelName: string;
@@ -8,8 +9,10 @@ interface PortfolioHeaderScore {
8
9
  interface PortfolioHeaderProps {
9
10
  address: string;
10
11
  score?: PortfolioHeaderScore | null;
12
+ label?: string;
13
+ trailing?: ReactNode;
11
14
  className?: string;
12
15
  }
13
- declare function PortfolioHeader({ address, score, className, }: PortfolioHeaderProps): react_jsx_runtime.JSX.Element;
16
+ declare function PortfolioHeader({ address, score, label, trailing, className, }: PortfolioHeaderProps): react_jsx_runtime.JSX.Element;
14
17
 
15
18
  export { PortfolioHeader, type PortfolioHeaderProps, type PortfolioHeaderScore };
@@ -6,6 +6,8 @@ import { AddressDisplay } from "./address-display.js";
6
6
  function PortfolioHeader({
7
7
  address,
8
8
  score,
9
+ label = "Portfolio",
10
+ trailing,
9
11
  className
10
12
  }) {
11
13
  const scoreChip = score && /* @__PURE__ */ jsxs("div", { className: "rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white", children: [
@@ -17,7 +19,7 @@ function PortfolioHeader({
17
19
  ] });
18
20
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-4", className), children: [
19
21
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
20
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: "Portfolio" }),
22
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground", children: label }),
21
23
  /* @__PURE__ */ jsx(
22
24
  AddressDisplay,
23
25
  {
@@ -27,6 +29,7 @@ function PortfolioHeader({
27
29
  }
28
30
  )
29
31
  ] }),
32
+ trailing,
30
33
  score?.href ? /* @__PURE__ */ jsx(Link, { href: score.href, className: "shrink-0 active:opacity-80", children: scoreChip }) : /* @__PURE__ */ jsx("div", { className: "shrink-0", children: scoreChip })
31
34
  ] });
32
35
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/portfolio-header.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { AddressDisplay } from \"./address-display.js\";\n\nexport interface PortfolioHeaderScore {\n\n levelName: string;\n totalXp: number;\n\n href?: string;\n}\n\nexport interface PortfolioHeaderProps {\n address: string;\n score?: PortfolioHeaderScore | null;\n className?: string;\n}\n\nexport function PortfolioHeader({\n address,\n score,\n className,\n}: PortfolioHeaderProps) {\n const scoreChip = score && (\n <div className=\"rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white\">\n <span className=\"text-sm font-bold\">\n {score.levelName}\n </span>\n <span className=\"text-xs font-medium text-white/80 tabular-nums\">\n {score.totalXp.toLocaleString()} XP\n </span>\n </div>\n );\n\n return (\n <div className={cn(\"flex items-center justify-between gap-4\", className)}>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n Portfolio\n </p>\n <AddressDisplay\n address={address}\n chars={6}\n className=\"text-2xl sm:text-3xl font-black tracking-tight text-foreground\"\n />\n </div>\n {score?.href ? (\n <Link href={score.href} className=\"shrink-0 active:opacity-80\">\n {scoreChip}\n </Link>\n ) : (\n <div className=\"shrink-0\">{scoreChip}</div>\n )}\n </div>\n );\n}\n"],"mappings":";AA2BM,cAGA,YAHA;AAzBN,OAAO,UAAU;AACjB,SAAS,UAAU;AACnB,SAAS,sBAAsB;AAgBxB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,YAAY,SAChB,qBAAC,SAAI,WAAU,uIACb;AAAA,wBAAC,UAAK,WAAU,qBACb,gBAAM,WACT;AAAA,IACA,qBAAC,UAAK,WAAU,kDACb;AAAA,YAAM,QAAQ,eAAe;AAAA,MAAE;AAAA,OAClC;AAAA,KACF;AAGF,SACE,qBAAC,SAAI,WAAW,GAAG,2CAA2C,SAAS,GACrE;AAAA,yBAAC,SAAI,WAAU,WACb;AAAA,0BAAC,OAAE,WAAU,6CAA4C,uBAEzD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO;AAAA,UACP,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC,OAAO,OACN,oBAAC,QAAK,MAAM,MAAM,MAAM,WAAU,8BAC/B,qBACH,IAEA,oBAAC,SAAI,WAAU,YAAY,qBAAU;AAAA,KAEzC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/portfolio-header.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Link from \"./link.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { AddressDisplay } from \"./address-display.js\";\n\nexport interface PortfolioHeaderScore {\n\n levelName: string;\n totalXp: number;\n\n href?: string;\n}\n\nexport interface PortfolioHeaderProps {\n address: string;\n score?: PortfolioHeaderScore | null;\n label?: string;\n trailing?: ReactNode;\n className?: string;\n}\n\nexport function PortfolioHeader({\n address,\n score,\n label = \"Portfolio\",\n trailing,\n className,\n}: PortfolioHeaderProps) {\n const scoreChip = score && (\n <div className=\"rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve px-3.5 py-1.5 flex items-baseline gap-2 whitespace-nowrap text-white\">\n <span className=\"text-sm font-bold\">\n {score.levelName}\n </span>\n <span className=\"text-xs font-medium text-white/80 tabular-nums\">\n {score.totalXp.toLocaleString()} XP\n </span>\n </div>\n );\n\n return (\n <div className={cn(\"flex items-center justify-between gap-4\", className)}>\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {label}\n </p>\n <AddressDisplay\n address={address}\n chars={6}\n className=\"text-2xl sm:text-3xl font-black tracking-tight text-foreground\"\n />\n </div>\n {trailing}\n {score?.href ? (\n <Link href={score.href} className=\"shrink-0 active:opacity-80\">\n {scoreChip}\n </Link>\n ) : (\n <div className=\"shrink-0\">{scoreChip}</div>\n )}\n </div>\n );\n}\n"],"mappings":";AAgCM,cAGA,YAHA;AA7BN,OAAO,UAAU;AACjB,SAAS,UAAU;AACnB,SAAS,sBAAsB;AAkBxB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,YAAY,SAChB,qBAAC,SAAI,WAAU,uIACb;AAAA,wBAAC,UAAK,WAAU,qBACb,gBAAM,WACT;AAAA,IACA,qBAAC,UAAK,WAAU,kDACb;AAAA,YAAM,QAAQ,eAAe;AAAA,MAAE;AAAA,OAClC;AAAA,KACF;AAGF,SACE,qBAAC,SAAI,WAAW,GAAG,2CAA2C,SAAS,GACrE;AAAA,yBAAC,SAAI,WAAU,WACb;AAAA,0BAAC,OAAE,WAAU,6CACV,iBACH;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO;AAAA,UACP,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IACC;AAAA,IACA,OAAO,OACN,oBAAC,QAAK,MAAM,MAAM,MAAM,WAAU,8BAC/B,qBACH,IAEA,oBAAC,SAAI,WAAU,YAAY,qBAAU;AAAA,KAEzC;AAEJ;","names":[]}
@@ -134,7 +134,7 @@ function TokenCard({
134
134
  },
135
135
  children: [
136
136
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-3.5 w-3.5 mr-1.5" }),
137
- "List"
137
+ "Sell"
138
138
  ]
139
139
  }
140
140
  ) : null : listingOrder && onBuy ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -181,7 +181,7 @@ function TokenCard({
181
181
  onClick: () => onList(token),
182
182
  children: [
183
183
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-3.5 w-3.5" }),
184
- "List"
184
+ "Sell"
185
185
  ]
186
186
  }
187
187
  ),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base group relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n List\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n List\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["buildAssetHref","buildCollectionHref","Link"]}
1
+ {"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base group relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n Sell\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n Sell\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["buildAssetHref","buildCollectionHref","Link"]}
@@ -119,7 +119,7 @@ function TokenCard({
119
119
  },
120
120
  children: [
121
121
  /* @__PURE__ */ jsx(Tag, { className: "h-3.5 w-3.5 mr-1.5" }),
122
- "List"
122
+ "Sell"
123
123
  ]
124
124
  }
125
125
  ) : null : listingOrder && onBuy ? /* @__PURE__ */ jsx("div", { className: "btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8", children: /* @__PURE__ */ jsxs(
@@ -166,7 +166,7 @@ function TokenCard({
166
166
  onClick: () => onList(token),
167
167
  children: [
168
168
  /* @__PURE__ */ jsx(Tag, { className: "h-3.5 w-3.5" }),
169
- "List"
169
+ "Sell"
170
170
  ]
171
171
  }
172
172
  ),