decane-connect-kit 2.2.2 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -183,6 +183,9 @@ __export(index_exports, {
183
183
  DecaneError: () => DecaneError,
184
184
  DecaneErrorCode: () => DecaneErrorCode,
185
185
  DecaneKit: () => DecaneKit,
186
+ DecaneLogo: () => DecaneLogo,
187
+ DecaneMark: () => DecaneMark,
188
+ DecaneWordmark: () => DecaneWordmark,
186
189
  ExportNotAuthorizedError: () => ExportNotAuthorizedError,
187
190
  InvalidApiKeyError: () => InvalidApiKeyError,
188
191
  InvalidPinError: () => InvalidPinError,
@@ -211,6 +214,7 @@ __export(index_exports, {
211
214
  useSignMessage: () => useSignMessage,
212
215
  useSignTypedData: () => useSignTypedData,
213
216
  useSocialAuth: () => useSocialAuth,
217
+ useSocialBalance: () => useSocialBalance,
214
218
  useSocialWallet: () => useSocialWallet,
215
219
  useWalletSelector: () => useWalletSelector,
216
220
  verifyEmailCode: () => verifyEmailCode
@@ -2735,6 +2739,13 @@ async function signEvmTransaction(tee, chain, tx, jwt) {
2735
2739
  async function signEvmMessage(tee, chain, message, jwt) {
2736
2740
  return tee.sign({ chain, kind: "message", payload: message }, jwt);
2737
2741
  }
2742
+ async function signEvmTypedData(tee, chain, typedData, jwt) {
2743
+ const payload = JSON.stringify(
2744
+ typedData,
2745
+ (_k, v) => typeof v === "bigint" ? v.toString() : v
2746
+ );
2747
+ return tee.sign({ chain, kind: "typedData", payload }, jwt);
2748
+ }
2738
2749
 
2739
2750
  // src/social/signers/solana.ts
2740
2751
  var import_web3 = require("@solana/web3.js");
@@ -2973,10 +2984,7 @@ async function buildPortableBackup(deviceShare, recoveryShare, password, address
2973
2984
  };
2974
2985
  }
2975
2986
 
2976
- // src/social/client.ts
2977
- var DEFAULT_API_BASE = "https://backend.decane.app";
2978
- var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
2979
- var DEFAULT_SESSION_MINUTES = 30;
2987
+ // src/social/balance.ts
2980
2988
  var DEFAULT_RPCS = {
2981
2989
  "evm:1": "https://ethereum.publicnode.com",
2982
2990
  "evm:137": "https://polygon.publicnode.com",
@@ -2988,6 +2996,50 @@ var DEFAULT_RPCS = {
2988
2996
  "evm:84532": "https://base-sepolia.publicnode.com",
2989
2997
  "evm:31337": "http://localhost:8545"
2990
2998
  };
2999
+ var EVM_SYMBOLS = {
3000
+ "evm:137": "MATIC",
3001
+ "evm:56": "BNB"
3002
+ };
3003
+ function solanaEndpoint(chain, rpcUrls) {
3004
+ if (rpcUrls?.[chain]) return rpcUrls[chain];
3005
+ const cluster = chain.slice("solana:".length);
3006
+ return cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com";
3007
+ }
3008
+ async function fetchBalance(opts) {
3009
+ const { kind, address, chain, rpcUrls } = opts;
3010
+ if (kind === "evm") {
3011
+ const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
3012
+ if (!rpcUrl) {
3013
+ throw new Error(
3014
+ `No RPC URL for ${chain}. Pass rpcUrls: { '${chain}': 'https://...' } in social config.`
3015
+ );
3016
+ }
3017
+ const { JsonRpcProvider, formatEther } = await import("ethers");
3018
+ const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
3019
+ return { raw: wei, formatted: formatEther(wei), symbol: EVM_SYMBOLS[chain] ?? "ETH", decimals: 18 };
3020
+ }
3021
+ const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
3022
+ const lamports = await new Connection(solanaEndpoint(chain, rpcUrls)).getBalance(
3023
+ new PublicKey(address)
3024
+ );
3025
+ return {
3026
+ raw: BigInt(lamports),
3027
+ formatted: String(lamports / LAMPORTS_PER_SOL),
3028
+ symbol: "SOL",
3029
+ decimals: 9
3030
+ };
3031
+ }
3032
+ function formatBalanceDisplay(value) {
3033
+ if (value == null) return "\u2014";
3034
+ const n = Number(value);
3035
+ if (!Number.isFinite(n)) return value;
3036
+ return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
3037
+ }
3038
+
3039
+ // src/social/client.ts
3040
+ var DEFAULT_API_BASE = "https://backend.decane.app";
3041
+ var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
3042
+ var DEFAULT_SESSION_MINUTES = 30;
2991
3043
  function makePersistKey(apiKey) {
2992
3044
  return `decane:social:${apiKey.slice(0, 20)}`;
2993
3045
  }
@@ -3485,6 +3537,23 @@ async function createDecaneConnect(config) {
3485
3537
  const txResponse = await provider.broadcastTransaction(signedTx);
3486
3538
  return txResponse.hash;
3487
3539
  },
3540
+ async signTypedData(req) {
3541
+ const tee = session.requireActive();
3542
+ if (!req.chain.startsWith("evm:")) {
3543
+ throw new CallSequenceError("signTypedData is EVM-only (EIP-712).");
3544
+ }
3545
+ return signEvmTypedData(
3546
+ tee,
3547
+ req.chain,
3548
+ {
3549
+ domain: req.domain,
3550
+ types: req.types,
3551
+ message: req.message,
3552
+ primaryType: req.primaryType
3553
+ },
3554
+ auth?.jwt
3555
+ );
3556
+ },
3488
3557
  async signSolanaTransaction(serializedTx) {
3489
3558
  const tee = session.requireActive();
3490
3559
  let tx;
@@ -3510,6 +3579,42 @@ async function createDecaneConnect(config) {
3510
3579
  getAddresses() {
3511
3580
  return auth?.addresses ?? persisted?.addresses ?? null;
3512
3581
  },
3582
+ // Native-token balance. Read-only public chain data, so it works whenever an
3583
+ // address is known — including while the wallet is locked (no TEE session
3584
+ // needed). `chain` defaults to the first configured EVM chain, else the
3585
+ // first Solana chain.
3586
+ async getBalance(chain) {
3587
+ const addresses = auth?.addresses ?? persisted?.addresses;
3588
+ if (!addresses) throw new CallSequenceError("Not connected \u2014 no wallet address known");
3589
+ const resolvedChain = chain ?? config.chains.find((c) => c.startsWith("evm:")) ?? config.chains.find((c) => c.startsWith("solana:"));
3590
+ if (!resolvedChain) throw new CallSequenceError("No chain configured");
3591
+ const kind = resolvedChain.startsWith("solana:") ? "solana" : "evm";
3592
+ const address = kind === "evm" ? addresses.evm : addresses.solana;
3593
+ if (!address) throw new CallSequenceError(`This wallet has no ${kind} address`);
3594
+ return fetchBalance({ kind, address, chain: resolvedChain, rpcUrls: config.rpcUrls });
3595
+ },
3596
+ // Balances across every configured chain the wallet has an address for.
3597
+ // Per-chain failures resolve to null rather than rejecting the whole call,
3598
+ // so one dead RPC doesn't blank the entire list.
3599
+ async getBalances() {
3600
+ const addresses = auth?.addresses ?? persisted?.addresses;
3601
+ if (!addresses) throw new CallSequenceError("Not connected \u2014 no wallet address known");
3602
+ const targets = config.chains.filter((c) => {
3603
+ const kind = c.startsWith("solana:") ? "solana" : "evm";
3604
+ return kind === "evm" ? !!addresses.evm : !!addresses.solana;
3605
+ });
3606
+ return Promise.all(
3607
+ targets.map(async (chain) => {
3608
+ const kind = chain.startsWith("solana:") ? "solana" : "evm";
3609
+ const address = kind === "evm" ? addresses.evm : addresses.solana;
3610
+ try {
3611
+ return { chain, balance: await fetchBalance({ kind, address, chain, rpcUrls: config.rpcUrls }) };
3612
+ } catch {
3613
+ return { chain, balance: null };
3614
+ }
3615
+ })
3616
+ );
3617
+ },
3513
3618
  async rotateShares(opts) {
3514
3619
  if (!auth) throw new CallSequenceError("Not connected \u2014 call connect() first");
3515
3620
  const tee = session.requireActive();
@@ -3756,6 +3861,45 @@ var CSS_VARS = {
3756
3861
 
3757
3862
  // src/ui/icons.tsx
3758
3863
  var import_react = __toESM(require("react"), 1);
3864
+ function DecaneMark({ size = 28, muted = false }) {
3865
+ const uid = import_react.default.useId().replace(/:/g, "");
3866
+ const fid = `dl_logo_f_${uid}`;
3867
+ const w = size;
3868
+ const h = Math.round(size * 64 / 68);
3869
+ return /* @__PURE__ */ import_react.default.createElement(
3870
+ "svg",
3871
+ {
3872
+ width: w,
3873
+ height: h,
3874
+ viewBox: "0 0 68 64",
3875
+ fill: "none",
3876
+ xmlns: "http://www.w3.org/2000/svg",
3877
+ "aria-hidden": true,
3878
+ style: { display: "block", flexShrink: 0, opacity: muted ? 0.55 : 1 }
3879
+ },
3880
+ /* @__PURE__ */ import_react.default.createElement("g", { filter: `url(#${fid})` }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M32.8031 10.2986C33.1971 9.68929 34.0886 9.68929 34.4826 10.2986L35.7297 12.2273C36.1599 12.8926 35.6823 13.7703 34.89 13.7703H32.3957C31.6034 13.7703 31.1257 12.8926 31.556 12.2273L32.8031 10.2986Z", fill: "#FFD700" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M16.6095 20.8798C25.5139 8.28662 47.0755 12.2298 51.4641 20.5617C54.9502 24.0479 55.2167 30.8018 55.2167 30.8018C55.2167 30.8018 58.8421 37.862 57.4428 41.3601C55.7891 56.7522 13.9381 57.0066 11.3304 41.3601C9.93111 37.0351 13.4293 31.3744 13.4293 31.3744C13.4293 31.3744 12.9841 27.2404 16.6095 20.8798Z", fill: "#FFD700" }), /* @__PURE__ */ import_react.default.createElement("ellipse", { cx: "48.9999", cy: "39.2669", rx: "2.38155", ry: "1.89957", transform: "rotate(-22.395 48.9999 39.2669)", fill: "#FFE55F", fillOpacity: "0.45" }), /* @__PURE__ */ import_react.default.createElement("ellipse", { cx: "18.9785", cy: "39.2671", rx: "2.38155", ry: "1.89958", transform: "rotate(15.8893 18.9785 39.2671)", fill: "#FFE55F", fillOpacity: "0.26" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M43.5977 30.7344C43.1619 30.7344 42.6943 30.9653 42.3027 31.4824C41.9107 32.0001 41.6388 32.7597 41.6387 33.6406C41.6387 34.5217 41.9107 35.2821 42.3027 35.7998C42.6943 36.3168 43.1619 36.5479 43.5977 36.5479C44.0332 36.5477 44.5002 36.3166 44.8916 35.7998C45.2837 35.2821 45.5557 34.5217 45.5557 33.6406C45.5556 32.7597 45.2836 32.0001 44.8916 31.4824C44.5002 30.9656 44.0333 30.7345 43.5977 30.7344Z", fill: "#1A1A1A", stroke: "#F4EBBC", strokeWidth: "2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M25.1514 30.7344C25.5871 30.7344 26.0547 30.9653 26.4463 31.4824C26.8383 32.0001 27.1103 32.7597 27.1104 33.6406C27.1104 34.5217 26.8384 35.2821 26.4463 35.7998C26.0547 36.3168 25.5871 36.5479 25.1514 36.5479C24.7158 36.5477 24.2489 36.3166 23.8574 35.7998C23.4654 35.2821 23.1934 34.5217 23.1934 33.6406C23.1934 32.7597 23.4654 32.0001 23.8574 31.4824C24.2489 30.9656 24.7157 30.7345 25.1514 30.7344Z", fill: "#1A1A1A", stroke: "#F4EBBC", strokeWidth: "2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M26.0107 41.6924C26.0107 41.6924 28.0937 46.399 34.759 46.399C41.008 46.399 43.3109 41.6924 43.3109 41.6924", stroke: "#1A1A1A", strokeLinecap: "round" })),
3881
+ /* @__PURE__ */ import_react.default.createElement("defs", null, /* @__PURE__ */ import_react.default.createElement("filter", { id: fid, x: "0.589964", y: "0.334365", width: "66.5809", height: "62.9754", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB" }, /* @__PURE__ */ import_react.default.createElement("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }), /* @__PURE__ */ import_react.default.createElement("feColorMatrix", { in: "SourceAlpha", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0", result: "hardAlpha" }), /* @__PURE__ */ import_react.default.createElement("feOffset", { dx: "-0.501447", dy: "0.401157" }), /* @__PURE__ */ import_react.default.createElement("feGaussianBlur", { stdDeviation: "4.95429" }), /* @__PURE__ */ import_react.default.createElement("feComposite", { in2: "hardAlpha", operator: "out" }), /* @__PURE__ */ import_react.default.createElement("feColorMatrix", { type: "matrix", values: "0 0 0 0 0.996078 0 0 0 0 0.996078 0 0 0 0 0.996078 0 0 0 0.12 0" }), /* @__PURE__ */ import_react.default.createElement("feBlend", { mode: "normal", in2: "BackgroundImageFix", result: "effect1_dropShadow" }), /* @__PURE__ */ import_react.default.createElement("feBlend", { mode: "normal", in: "SourceGraphic", in2: "effect1_dropShadow", result: "shape" })))
3882
+ );
3883
+ }
3884
+ function DecaneWordmark({ size = 15, muted = false }) {
3885
+ return /* @__PURE__ */ import_react.default.createElement(
3886
+ "span",
3887
+ {
3888
+ style: {
3889
+ fontFamily: "var(--dc-font-sans, system-ui, sans-serif)",
3890
+ fontWeight: 800,
3891
+ fontSize: size,
3892
+ letterSpacing: "-0.03em",
3893
+ color: muted ? "var(--dc-text-muted)" : "var(--dc-text)",
3894
+ lineHeight: 1
3895
+ }
3896
+ },
3897
+ "decane"
3898
+ );
3899
+ }
3900
+ function DecaneLogo({ size = 20, muted = false }) {
3901
+ return /* @__PURE__ */ import_react.default.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: size * 0.34 } }, /* @__PURE__ */ import_react.default.createElement(DecaneMark, { size, muted }), /* @__PURE__ */ import_react.default.createElement(DecaneWordmark, { size: size * 0.78, muted }));
3902
+ }
3759
3903
  function WalletIcon({ src, name, size = 36 }) {
3760
3904
  if (src) {
3761
3905
  return /* @__PURE__ */ import_react.default.createElement(
@@ -4709,40 +4853,17 @@ function useBalance(kind, address, chain, rpcUrls) {
4709
4853
  if (!address || !chain) return;
4710
4854
  let cancelled = false;
4711
4855
  setState((s) => ({ ...s, loading: true }));
4712
- (async () => {
4713
- try {
4714
- if (kind === "evm") {
4715
- const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
4716
- if (!rpcUrl) {
4717
- if (!cancelled) setState({ loading: false, value: null, symbol: "ETH" });
4718
- return;
4719
- }
4720
- const { JsonRpcProvider, formatEther } = await import("ethers");
4721
- const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
4722
- if (!cancelled) setState({ loading: false, value: formatEther(wei), symbol: "ETH" });
4723
- } else {
4724
- const cluster = chain.slice("solana:".length);
4725
- const endpoint = rpcUrls?.[chain] ?? (cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com");
4726
- const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
4727
- const lamports = await new Connection(endpoint).getBalance(new PublicKey(address));
4728
- if (!cancelled) setState({ loading: false, value: String(lamports / LAMPORTS_PER_SOL), symbol: "SOL" });
4729
- }
4730
- } catch {
4731
- if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
4732
- }
4733
- })();
4856
+ fetchBalance({ kind, address, chain, rpcUrls }).then((b) => {
4857
+ if (!cancelled) setState({ loading: false, value: b.formatted, symbol: b.symbol });
4858
+ }).catch(() => {
4859
+ if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
4860
+ });
4734
4861
  return () => {
4735
4862
  cancelled = true;
4736
4863
  };
4737
4864
  }, [kind, address, chain, rpcUrls]);
4738
4865
  return state;
4739
4866
  }
4740
- function formatBalance(value) {
4741
- if (value == null) return "\u2014";
4742
- const n = Number(value);
4743
- if (!Number.isFinite(n)) return value;
4744
- return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
4745
- }
4746
4867
  function AddressRow({
4747
4868
  label,
4748
4869
  address,
@@ -4758,7 +4879,7 @@ function AddressRow({
4758
4879
  borderRadius: 10,
4759
4880
  padding: "10px 14px",
4760
4881
  marginBottom: 8
4761
- } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 10, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "0.06em", textTransform: "uppercase" } }, label), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 11, fontFamily: "monospace", color: "var(--dc-text)" } }, balance.loading ? "\u2026" : `${formatBalance(balance.value)} ${balance.symbol}`)), /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 13, fontFamily: "monospace", color: "var(--dc-text)", letterSpacing: "0.02em" } }, short), /* @__PURE__ */ import_react3.default.createElement(CopyButton, { value: address })));
4882
+ } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 10, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "0.06em", textTransform: "uppercase" } }, label), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 11, fontFamily: "monospace", color: "var(--dc-text)" } }, balance.loading ? "\u2026" : `${formatBalanceDisplay(balance.value)} ${balance.symbol}`)), /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 13, fontFamily: "monospace", color: "var(--dc-text)", letterSpacing: "0.02em" } }, short), /* @__PURE__ */ import_react3.default.createElement(CopyButton, { value: address })));
4762
4883
  }
4763
4884
  function SignInView({
4764
4885
  onGoogleSignIn,
@@ -5135,34 +5256,7 @@ function SocialWalletModal({
5135
5256
  top: 0,
5136
5257
  zIndex: 1,
5137
5258
  background: "linear-gradient(90deg, transparent, var(--dc-accent) 30%, var(--dc-accent) 70%, transparent)"
5138
- } }), /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: {
5139
- width: 34,
5140
- height: 34,
5141
- borderRadius: 10,
5142
- background: "var(--dc-surface)",
5143
- border: "1px solid var(--dc-border)",
5144
- display: "flex",
5145
- alignItems: "center",
5146
- justifyContent: "center",
5147
- flexShrink: 0
5148
- } }, /* @__PURE__ */ import_react3.default.createElement("svg", { width: "16", height: "18", viewBox: "0 0 16 18", fill: "none" }, /* @__PURE__ */ import_react3.default.createElement(
5149
- "path",
5150
- {
5151
- d: "M8 1L1.5 3.5V8.5C1.5 12.09 4.35 15.4 8 16.5C11.65 15.4 14.5 12.09 14.5 8.5V3.5L8 1Z",
5152
- stroke: "var(--dc-accent)",
5153
- strokeWidth: "1.4",
5154
- strokeLinejoin: "round"
5155
- }
5156
- ), /* @__PURE__ */ import_react3.default.createElement(
5157
- "path",
5158
- {
5159
- d: "M5.5 9L7 10.5L10.5 7",
5160
- stroke: "var(--dc-accent)",
5161
- strokeWidth: "1.4",
5162
- strokeLinecap: "round",
5163
- strokeLinejoin: "round"
5164
- }
5165
- ))), /* @__PURE__ */ import_react3.default.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 15, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em" } }, "Social Wallet"), /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 1 } }, "Decane non-custodial \xB7 key split three ways")), /* @__PURE__ */ import_react3.default.createElement(
5259
+ } }), /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 11 } }, /* @__PURE__ */ import_react3.default.createElement(DecaneMark, { size: 38 }), /* @__PURE__ */ import_react3.default.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "baseline", gap: 6 } }, /* @__PURE__ */ import_react3.default.createElement(DecaneWordmark, { size: 15 }), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "-0.01em" } }, "wallet")), /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Non-custodial \xB7 key split three ways")), /* @__PURE__ */ import_react3.default.createElement(
5166
5260
  "button",
5167
5261
  {
5168
5262
  onClick: onClose,
@@ -5265,7 +5359,14 @@ function SocialWalletModal({
5265
5359
  }
5266
5360
  },
5267
5361
  disconnecting ? "Signing out\u2026" : "Sign out"
5268
- ))))
5362
+ ))), /* @__PURE__ */ import_react3.default.createElement("div", { style: {
5363
+ padding: "11px 16px",
5364
+ borderTop: "1px solid var(--dc-border)",
5365
+ display: "flex",
5366
+ alignItems: "center",
5367
+ justifyContent: "center",
5368
+ gap: 6
5369
+ } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 10.5, color: "var(--dc-text-muted)", letterSpacing: "0.02em" } }, "Secured by"), /* @__PURE__ */ import_react3.default.createElement(DecaneMark, { size: 13, muted: true }), /* @__PURE__ */ import_react3.default.createElement(DecaneWordmark, { size: 11, muted: true })))
5269
5370
  );
5270
5371
  return (0, import_react_dom2.createPortal)(modal, document.body);
5271
5372
  }
@@ -5451,6 +5552,21 @@ function DecaneKit({ config, children }) {
5451
5552
  if (!sdk) throw new Error("Social wallet not connected");
5452
5553
  return sdk.signSolanaTransaction(tx);
5453
5554
  }, []);
5555
+ const socialSignTypedData = (0, import_react4.useCallback)(async (req) => {
5556
+ const sdk = socialRef.current;
5557
+ if (!sdk) throw new Error("Social wallet not connected");
5558
+ return sdk.signTypedData({ ...req, chain: req.chain });
5559
+ }, []);
5560
+ const socialGetBalance = (0, import_react4.useCallback)(async (chain) => {
5561
+ const sdk = socialRef.current;
5562
+ if (!sdk) throw new Error("Social wallet not connected");
5563
+ return sdk.getBalance(chain);
5564
+ }, []);
5565
+ const socialGetBalances = (0, import_react4.useCallback)(async () => {
5566
+ const sdk = socialRef.current;
5567
+ if (!sdk) throw new Error("Social wallet not connected");
5568
+ return sdk.getBalances();
5569
+ }, []);
5454
5570
  const socialRotateShares = (0, import_react4.useCallback)(async (opts) => {
5455
5571
  const sdk = socialRef.current;
5456
5572
  if (!sdk) throw new Error("Social wallet not connected");
@@ -5506,7 +5622,10 @@ function DecaneKit({ config, children }) {
5506
5622
  socialDisconnect,
5507
5623
  socialSignMessage,
5508
5624
  socialSendTransaction,
5625
+ socialGetBalance,
5626
+ socialGetBalances,
5509
5627
  socialSignSolanaTransaction,
5628
+ socialSignTypedData,
5510
5629
  socialRotateShares,
5511
5630
  socialExportPortableBackup,
5512
5631
  socialHasRecoveryShare,
@@ -5704,6 +5823,9 @@ function useSocialWallet() {
5704
5823
  socialSignMessage,
5705
5824
  socialSendTransaction,
5706
5825
  socialSignSolanaTransaction,
5826
+ socialSignTypedData,
5827
+ socialGetBalance,
5828
+ socialGetBalances,
5707
5829
  socialRotateShares,
5708
5830
  socialExportPortableBackup,
5709
5831
  socialHasRecoveryShare,
@@ -5740,6 +5862,18 @@ function useSocialWallet() {
5740
5862
  (tx) => run(() => socialSignSolanaTransaction(tx)),
5741
5863
  [socialSignSolanaTransaction]
5742
5864
  );
5865
+ const signTypedData = (0, import_react5.useCallback)(
5866
+ (req) => run(() => socialSignTypedData(req)),
5867
+ [socialSignTypedData]
5868
+ );
5869
+ const getBalance = (0, import_react5.useCallback)(
5870
+ (chain) => run(() => socialGetBalance(chain)),
5871
+ [socialGetBalance]
5872
+ );
5873
+ const getBalances = (0, import_react5.useCallback)(
5874
+ () => run(() => socialGetBalances()),
5875
+ [socialGetBalances]
5876
+ );
5743
5877
  const unlock = (0, import_react5.useCallback)(async () => {
5744
5878
  setError(null);
5745
5879
  try {
@@ -5801,6 +5935,10 @@ function useSocialWallet() {
5801
5935
  signMessage,
5802
5936
  sendTransaction,
5803
5937
  signSolanaTransaction: signSolanaTransaction2,
5938
+ signTypedData,
5939
+ // Balances (native token; read-only, works while locked)
5940
+ getBalance,
5941
+ getBalances,
5804
5942
  // Recovery (2-of-3 Shamir share set)
5805
5943
  rotateShares,
5806
5944
  exportPortableBackup,
@@ -5812,6 +5950,52 @@ function useSocialWallet() {
5812
5950
  clearError: () => setError(null)
5813
5951
  };
5814
5952
  }
5953
+ function useSocialBalance(chain) {
5954
+ const { socialAuth, socialGetBalance } = useDecaneContext();
5955
+ const [balance, setBalance] = (0, import_react5.useState)(null);
5956
+ const [loading, setLoading] = (0, import_react5.useState)(false);
5957
+ const [error, setError] = (0, import_react5.useState)(null);
5958
+ const addrKey = `${socialAuth.addresses?.evm ?? ""}|${socialAuth.addresses?.solana ?? ""}`;
5959
+ const refetch = (0, import_react5.useCallback)(async () => {
5960
+ if (!socialAuth.addresses) {
5961
+ setBalance(null);
5962
+ return;
5963
+ }
5964
+ setLoading(true);
5965
+ setError(null);
5966
+ try {
5967
+ setBalance(await socialGetBalance(chain));
5968
+ } catch (e) {
5969
+ setError(e.message);
5970
+ setBalance(null);
5971
+ } finally {
5972
+ setLoading(false);
5973
+ }
5974
+ }, [socialGetBalance, chain, socialAuth.addresses]);
5975
+ (0, import_react5.useEffect)(() => {
5976
+ let cancelled = false;
5977
+ if (!socialAuth.addresses) {
5978
+ setBalance(null);
5979
+ return;
5980
+ }
5981
+ setLoading(true);
5982
+ setError(null);
5983
+ socialGetBalance(chain).then((b) => {
5984
+ if (!cancelled) setBalance(b);
5985
+ }).catch((e) => {
5986
+ if (!cancelled) {
5987
+ setError(e.message);
5988
+ setBalance(null);
5989
+ }
5990
+ }).finally(() => {
5991
+ if (!cancelled) setLoading(false);
5992
+ });
5993
+ return () => {
5994
+ cancelled = true;
5995
+ };
5996
+ }, [addrKey, chain]);
5997
+ return { balance, loading, error, refetch };
5998
+ }
5815
5999
  function toDecaneError(err) {
5816
6000
  if (err instanceof DecaneError) return err;
5817
6001
  const msg = err instanceof Error ? err.message : err?.message != null ? String(err.message) : String(err);
@@ -6045,6 +6229,9 @@ function useSignTypedData() {
6045
6229
  DecaneError,
6046
6230
  DecaneErrorCode,
6047
6231
  DecaneKit,
6232
+ DecaneLogo,
6233
+ DecaneMark,
6234
+ DecaneWordmark,
6048
6235
  ExportNotAuthorizedError,
6049
6236
  InvalidApiKeyError,
6050
6237
  InvalidPinError,
@@ -6073,6 +6260,7 @@ function useSignTypedData() {
6073
6260
  useSignMessage,
6074
6261
  useSignTypedData,
6075
6262
  useSocialAuth,
6263
+ useSocialBalance,
6076
6264
  useSocialWallet,
6077
6265
  useWalletSelector,
6078
6266
  verifyEmailCode