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.js CHANGED
@@ -2668,6 +2668,13 @@ async function signEvmTransaction(tee, chain, tx, jwt) {
2668
2668
  async function signEvmMessage(tee, chain, message, jwt) {
2669
2669
  return tee.sign({ chain, kind: "message", payload: message }, jwt);
2670
2670
  }
2671
+ async function signEvmTypedData(tee, chain, typedData, jwt) {
2672
+ const payload = JSON.stringify(
2673
+ typedData,
2674
+ (_k, v) => typeof v === "bigint" ? v.toString() : v
2675
+ );
2676
+ return tee.sign({ chain, kind: "typedData", payload }, jwt);
2677
+ }
2671
2678
 
2672
2679
  // src/social/signers/solana.ts
2673
2680
  import { VersionedTransaction as VTx } from "@solana/web3.js";
@@ -2906,10 +2913,7 @@ async function buildPortableBackup(deviceShare, recoveryShare, password, address
2906
2913
  };
2907
2914
  }
2908
2915
 
2909
- // src/social/client.ts
2910
- var DEFAULT_API_BASE = "https://backend.decane.app";
2911
- var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
2912
- var DEFAULT_SESSION_MINUTES = 30;
2916
+ // src/social/balance.ts
2913
2917
  var DEFAULT_RPCS = {
2914
2918
  "evm:1": "https://ethereum.publicnode.com",
2915
2919
  "evm:137": "https://polygon.publicnode.com",
@@ -2921,6 +2925,50 @@ var DEFAULT_RPCS = {
2921
2925
  "evm:84532": "https://base-sepolia.publicnode.com",
2922
2926
  "evm:31337": "http://localhost:8545"
2923
2927
  };
2928
+ var EVM_SYMBOLS = {
2929
+ "evm:137": "MATIC",
2930
+ "evm:56": "BNB"
2931
+ };
2932
+ function solanaEndpoint(chain, rpcUrls) {
2933
+ if (rpcUrls?.[chain]) return rpcUrls[chain];
2934
+ const cluster = chain.slice("solana:".length);
2935
+ return cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com";
2936
+ }
2937
+ async function fetchBalance(opts) {
2938
+ const { kind, address, chain, rpcUrls } = opts;
2939
+ if (kind === "evm") {
2940
+ const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
2941
+ if (!rpcUrl) {
2942
+ throw new Error(
2943
+ `No RPC URL for ${chain}. Pass rpcUrls: { '${chain}': 'https://...' } in social config.`
2944
+ );
2945
+ }
2946
+ const { JsonRpcProvider, formatEther } = await import("ethers");
2947
+ const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
2948
+ return { raw: wei, formatted: formatEther(wei), symbol: EVM_SYMBOLS[chain] ?? "ETH", decimals: 18 };
2949
+ }
2950
+ const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
2951
+ const lamports = await new Connection(solanaEndpoint(chain, rpcUrls)).getBalance(
2952
+ new PublicKey(address)
2953
+ );
2954
+ return {
2955
+ raw: BigInt(lamports),
2956
+ formatted: String(lamports / LAMPORTS_PER_SOL),
2957
+ symbol: "SOL",
2958
+ decimals: 9
2959
+ };
2960
+ }
2961
+ function formatBalanceDisplay(value) {
2962
+ if (value == null) return "\u2014";
2963
+ const n = Number(value);
2964
+ if (!Number.isFinite(n)) return value;
2965
+ return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
2966
+ }
2967
+
2968
+ // src/social/client.ts
2969
+ var DEFAULT_API_BASE = "https://backend.decane.app";
2970
+ var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
2971
+ var DEFAULT_SESSION_MINUTES = 30;
2924
2972
  function makePersistKey(apiKey) {
2925
2973
  return `decane:social:${apiKey.slice(0, 20)}`;
2926
2974
  }
@@ -3418,6 +3466,23 @@ async function createDecaneConnect(config) {
3418
3466
  const txResponse = await provider.broadcastTransaction(signedTx);
3419
3467
  return txResponse.hash;
3420
3468
  },
3469
+ async signTypedData(req) {
3470
+ const tee = session.requireActive();
3471
+ if (!req.chain.startsWith("evm:")) {
3472
+ throw new CallSequenceError("signTypedData is EVM-only (EIP-712).");
3473
+ }
3474
+ return signEvmTypedData(
3475
+ tee,
3476
+ req.chain,
3477
+ {
3478
+ domain: req.domain,
3479
+ types: req.types,
3480
+ message: req.message,
3481
+ primaryType: req.primaryType
3482
+ },
3483
+ auth?.jwt
3484
+ );
3485
+ },
3421
3486
  async signSolanaTransaction(serializedTx) {
3422
3487
  const tee = session.requireActive();
3423
3488
  let tx;
@@ -3443,6 +3508,42 @@ async function createDecaneConnect(config) {
3443
3508
  getAddresses() {
3444
3509
  return auth?.addresses ?? persisted?.addresses ?? null;
3445
3510
  },
3511
+ // Native-token balance. Read-only public chain data, so it works whenever an
3512
+ // address is known — including while the wallet is locked (no TEE session
3513
+ // needed). `chain` defaults to the first configured EVM chain, else the
3514
+ // first Solana chain.
3515
+ async getBalance(chain) {
3516
+ const addresses = auth?.addresses ?? persisted?.addresses;
3517
+ if (!addresses) throw new CallSequenceError("Not connected \u2014 no wallet address known");
3518
+ const resolvedChain = chain ?? config.chains.find((c) => c.startsWith("evm:")) ?? config.chains.find((c) => c.startsWith("solana:"));
3519
+ if (!resolvedChain) throw new CallSequenceError("No chain configured");
3520
+ const kind = resolvedChain.startsWith("solana:") ? "solana" : "evm";
3521
+ const address = kind === "evm" ? addresses.evm : addresses.solana;
3522
+ if (!address) throw new CallSequenceError(`This wallet has no ${kind} address`);
3523
+ return fetchBalance({ kind, address, chain: resolvedChain, rpcUrls: config.rpcUrls });
3524
+ },
3525
+ // Balances across every configured chain the wallet has an address for.
3526
+ // Per-chain failures resolve to null rather than rejecting the whole call,
3527
+ // so one dead RPC doesn't blank the entire list.
3528
+ async getBalances() {
3529
+ const addresses = auth?.addresses ?? persisted?.addresses;
3530
+ if (!addresses) throw new CallSequenceError("Not connected \u2014 no wallet address known");
3531
+ const targets = config.chains.filter((c) => {
3532
+ const kind = c.startsWith("solana:") ? "solana" : "evm";
3533
+ return kind === "evm" ? !!addresses.evm : !!addresses.solana;
3534
+ });
3535
+ return Promise.all(
3536
+ targets.map(async (chain) => {
3537
+ const kind = chain.startsWith("solana:") ? "solana" : "evm";
3538
+ const address = kind === "evm" ? addresses.evm : addresses.solana;
3539
+ try {
3540
+ return { chain, balance: await fetchBalance({ kind, address, chain, rpcUrls: config.rpcUrls }) };
3541
+ } catch {
3542
+ return { chain, balance: null };
3543
+ }
3544
+ })
3545
+ );
3546
+ },
3446
3547
  async rotateShares(opts) {
3447
3548
  if (!auth) throw new CallSequenceError("Not connected \u2014 call connect() first");
3448
3549
  const tee = session.requireActive();
@@ -3689,6 +3790,45 @@ var CSS_VARS = {
3689
3790
 
3690
3791
  // src/ui/icons.tsx
3691
3792
  import React from "react";
3793
+ function DecaneMark({ size = 28, muted = false }) {
3794
+ const uid = React.useId().replace(/:/g, "");
3795
+ const fid = `dl_logo_f_${uid}`;
3796
+ const w = size;
3797
+ const h = Math.round(size * 64 / 68);
3798
+ return /* @__PURE__ */ React.createElement(
3799
+ "svg",
3800
+ {
3801
+ width: w,
3802
+ height: h,
3803
+ viewBox: "0 0 68 64",
3804
+ fill: "none",
3805
+ xmlns: "http://www.w3.org/2000/svg",
3806
+ "aria-hidden": true,
3807
+ style: { display: "block", flexShrink: 0, opacity: muted ? 0.55 : 1 }
3808
+ },
3809
+ /* @__PURE__ */ React.createElement("g", { filter: `url(#${fid})` }, /* @__PURE__ */ React.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__ */ React.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__ */ React.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__ */ React.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__ */ React.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__ */ React.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__ */ React.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" })),
3810
+ /* @__PURE__ */ React.createElement("defs", null, /* @__PURE__ */ React.createElement("filter", { id: fid, x: "0.589964", y: "0.334365", width: "66.5809", height: "62.9754", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB" }, /* @__PURE__ */ React.createElement("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }), /* @__PURE__ */ React.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__ */ React.createElement("feOffset", { dx: "-0.501447", dy: "0.401157" }), /* @__PURE__ */ React.createElement("feGaussianBlur", { stdDeviation: "4.95429" }), /* @__PURE__ */ React.createElement("feComposite", { in2: "hardAlpha", operator: "out" }), /* @__PURE__ */ React.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__ */ React.createElement("feBlend", { mode: "normal", in2: "BackgroundImageFix", result: "effect1_dropShadow" }), /* @__PURE__ */ React.createElement("feBlend", { mode: "normal", in: "SourceGraphic", in2: "effect1_dropShadow", result: "shape" })))
3811
+ );
3812
+ }
3813
+ function DecaneWordmark({ size = 15, muted = false }) {
3814
+ return /* @__PURE__ */ React.createElement(
3815
+ "span",
3816
+ {
3817
+ style: {
3818
+ fontFamily: "var(--dc-font-sans, system-ui, sans-serif)",
3819
+ fontWeight: 800,
3820
+ fontSize: size,
3821
+ letterSpacing: "-0.03em",
3822
+ color: muted ? "var(--dc-text-muted)" : "var(--dc-text)",
3823
+ lineHeight: 1
3824
+ }
3825
+ },
3826
+ "decane"
3827
+ );
3828
+ }
3829
+ function DecaneLogo({ size = 20, muted = false }) {
3830
+ return /* @__PURE__ */ React.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: size * 0.34 } }, /* @__PURE__ */ React.createElement(DecaneMark, { size, muted }), /* @__PURE__ */ React.createElement(DecaneWordmark, { size: size * 0.78, muted }));
3831
+ }
3692
3832
  function WalletIcon({ src, name, size = 36 }) {
3693
3833
  if (src) {
3694
3834
  return /* @__PURE__ */ React.createElement(
@@ -4642,40 +4782,17 @@ function useBalance(kind, address, chain, rpcUrls) {
4642
4782
  if (!address || !chain) return;
4643
4783
  let cancelled = false;
4644
4784
  setState((s) => ({ ...s, loading: true }));
4645
- (async () => {
4646
- try {
4647
- if (kind === "evm") {
4648
- const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
4649
- if (!rpcUrl) {
4650
- if (!cancelled) setState({ loading: false, value: null, symbol: "ETH" });
4651
- return;
4652
- }
4653
- const { JsonRpcProvider, formatEther } = await import("ethers");
4654
- const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
4655
- if (!cancelled) setState({ loading: false, value: formatEther(wei), symbol: "ETH" });
4656
- } else {
4657
- const cluster = chain.slice("solana:".length);
4658
- const endpoint = rpcUrls?.[chain] ?? (cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com");
4659
- const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
4660
- const lamports = await new Connection(endpoint).getBalance(new PublicKey(address));
4661
- if (!cancelled) setState({ loading: false, value: String(lamports / LAMPORTS_PER_SOL), symbol: "SOL" });
4662
- }
4663
- } catch {
4664
- if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
4665
- }
4666
- })();
4785
+ fetchBalance({ kind, address, chain, rpcUrls }).then((b) => {
4786
+ if (!cancelled) setState({ loading: false, value: b.formatted, symbol: b.symbol });
4787
+ }).catch(() => {
4788
+ if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
4789
+ });
4667
4790
  return () => {
4668
4791
  cancelled = true;
4669
4792
  };
4670
4793
  }, [kind, address, chain, rpcUrls]);
4671
4794
  return state;
4672
4795
  }
4673
- function formatBalance(value) {
4674
- if (value == null) return "\u2014";
4675
- const n = Number(value);
4676
- if (!Number.isFinite(n)) return value;
4677
- return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
4678
- }
4679
4796
  function AddressRow({
4680
4797
  label,
4681
4798
  address,
@@ -4691,7 +4808,7 @@ function AddressRow({
4691
4808
  borderRadius: 10,
4692
4809
  padding: "10px 14px",
4693
4810
  marginBottom: 8
4694
- } }, /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5 } }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 10, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "0.06em", textTransform: "uppercase" } }, label), /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 11, fontFamily: "monospace", color: "var(--dc-text)" } }, balance.loading ? "\u2026" : `${formatBalance(balance.value)} ${balance.symbol}`)), /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 13, fontFamily: "monospace", color: "var(--dc-text)", letterSpacing: "0.02em" } }, short), /* @__PURE__ */ React3.createElement(CopyButton, { value: address })));
4811
+ } }, /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5 } }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 10, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "0.06em", textTransform: "uppercase" } }, label), /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 11, fontFamily: "monospace", color: "var(--dc-text)" } }, balance.loading ? "\u2026" : `${formatBalanceDisplay(balance.value)} ${balance.symbol}`)), /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 13, fontFamily: "monospace", color: "var(--dc-text)", letterSpacing: "0.02em" } }, short), /* @__PURE__ */ React3.createElement(CopyButton, { value: address })));
4695
4812
  }
4696
4813
  function SignInView({
4697
4814
  onGoogleSignIn,
@@ -5068,34 +5185,7 @@ function SocialWalletModal({
5068
5185
  top: 0,
5069
5186
  zIndex: 1,
5070
5187
  background: "linear-gradient(90deg, transparent, var(--dc-accent) 30%, var(--dc-accent) 70%, transparent)"
5071
- } }), /* @__PURE__ */ React3.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ React3.createElement("div", { style: {
5072
- width: 34,
5073
- height: 34,
5074
- borderRadius: 10,
5075
- background: "var(--dc-surface)",
5076
- border: "1px solid var(--dc-border)",
5077
- display: "flex",
5078
- alignItems: "center",
5079
- justifyContent: "center",
5080
- flexShrink: 0
5081
- } }, /* @__PURE__ */ React3.createElement("svg", { width: "16", height: "18", viewBox: "0 0 16 18", fill: "none" }, /* @__PURE__ */ React3.createElement(
5082
- "path",
5083
- {
5084
- 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",
5085
- stroke: "var(--dc-accent)",
5086
- strokeWidth: "1.4",
5087
- strokeLinejoin: "round"
5088
- }
5089
- ), /* @__PURE__ */ React3.createElement(
5090
- "path",
5091
- {
5092
- d: "M5.5 9L7 10.5L10.5 7",
5093
- stroke: "var(--dc-accent)",
5094
- strokeWidth: "1.4",
5095
- strokeLinecap: "round",
5096
- strokeLinejoin: "round"
5097
- }
5098
- ))), /* @__PURE__ */ React3.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React3.createElement("div", { style: { fontSize: 15, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em" } }, "Social Wallet"), /* @__PURE__ */ React3.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 1 } }, "Decane non-custodial \xB7 key split three ways")), /* @__PURE__ */ React3.createElement(
5188
+ } }), /* @__PURE__ */ React3.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 11 } }, /* @__PURE__ */ React3.createElement(DecaneMark, { size: 38 }), /* @__PURE__ */ React3.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "baseline", gap: 6 } }, /* @__PURE__ */ React3.createElement(DecaneWordmark, { size: 15 }), /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "-0.01em" } }, "wallet")), /* @__PURE__ */ React3.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Non-custodial \xB7 key split three ways")), /* @__PURE__ */ React3.createElement(
5099
5189
  "button",
5100
5190
  {
5101
5191
  onClick: onClose,
@@ -5198,7 +5288,14 @@ function SocialWalletModal({
5198
5288
  }
5199
5289
  },
5200
5290
  disconnecting ? "Signing out\u2026" : "Sign out"
5201
- ))))
5291
+ ))), /* @__PURE__ */ React3.createElement("div", { style: {
5292
+ padding: "11px 16px",
5293
+ borderTop: "1px solid var(--dc-border)",
5294
+ display: "flex",
5295
+ alignItems: "center",
5296
+ justifyContent: "center",
5297
+ gap: 6
5298
+ } }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: 10.5, color: "var(--dc-text-muted)", letterSpacing: "0.02em" } }, "Secured by"), /* @__PURE__ */ React3.createElement(DecaneMark, { size: 13, muted: true }), /* @__PURE__ */ React3.createElement(DecaneWordmark, { size: 11, muted: true })))
5202
5299
  );
5203
5300
  return createPortal2(modal, document.body);
5204
5301
  }
@@ -5391,6 +5488,21 @@ function DecaneKit({ config, children }) {
5391
5488
  if (!sdk) throw new Error("Social wallet not connected");
5392
5489
  return sdk.signSolanaTransaction(tx);
5393
5490
  }, []);
5491
+ const socialSignTypedData = useCallback3(async (req) => {
5492
+ const sdk = socialRef.current;
5493
+ if (!sdk) throw new Error("Social wallet not connected");
5494
+ return sdk.signTypedData({ ...req, chain: req.chain });
5495
+ }, []);
5496
+ const socialGetBalance = useCallback3(async (chain) => {
5497
+ const sdk = socialRef.current;
5498
+ if (!sdk) throw new Error("Social wallet not connected");
5499
+ return sdk.getBalance(chain);
5500
+ }, []);
5501
+ const socialGetBalances = useCallback3(async () => {
5502
+ const sdk = socialRef.current;
5503
+ if (!sdk) throw new Error("Social wallet not connected");
5504
+ return sdk.getBalances();
5505
+ }, []);
5394
5506
  const socialRotateShares = useCallback3(async (opts) => {
5395
5507
  const sdk = socialRef.current;
5396
5508
  if (!sdk) throw new Error("Social wallet not connected");
@@ -5446,7 +5558,10 @@ function DecaneKit({ config, children }) {
5446
5558
  socialDisconnect,
5447
5559
  socialSignMessage,
5448
5560
  socialSendTransaction,
5561
+ socialGetBalance,
5562
+ socialGetBalances,
5449
5563
  socialSignSolanaTransaction,
5564
+ socialSignTypedData,
5450
5565
  socialRotateShares,
5451
5566
  socialExportPortableBackup,
5452
5567
  socialHasRecoveryShare,
@@ -5644,6 +5759,9 @@ function useSocialWallet() {
5644
5759
  socialSignMessage,
5645
5760
  socialSendTransaction,
5646
5761
  socialSignSolanaTransaction,
5762
+ socialSignTypedData,
5763
+ socialGetBalance,
5764
+ socialGetBalances,
5647
5765
  socialRotateShares,
5648
5766
  socialExportPortableBackup,
5649
5767
  socialHasRecoveryShare,
@@ -5680,6 +5798,18 @@ function useSocialWallet() {
5680
5798
  (tx) => run(() => socialSignSolanaTransaction(tx)),
5681
5799
  [socialSignSolanaTransaction]
5682
5800
  );
5801
+ const signTypedData = useCallback4(
5802
+ (req) => run(() => socialSignTypedData(req)),
5803
+ [socialSignTypedData]
5804
+ );
5805
+ const getBalance = useCallback4(
5806
+ (chain) => run(() => socialGetBalance(chain)),
5807
+ [socialGetBalance]
5808
+ );
5809
+ const getBalances = useCallback4(
5810
+ () => run(() => socialGetBalances()),
5811
+ [socialGetBalances]
5812
+ );
5683
5813
  const unlock = useCallback4(async () => {
5684
5814
  setError(null);
5685
5815
  try {
@@ -5741,6 +5871,10 @@ function useSocialWallet() {
5741
5871
  signMessage,
5742
5872
  sendTransaction,
5743
5873
  signSolanaTransaction: signSolanaTransaction2,
5874
+ signTypedData,
5875
+ // Balances (native token; read-only, works while locked)
5876
+ getBalance,
5877
+ getBalances,
5744
5878
  // Recovery (2-of-3 Shamir share set)
5745
5879
  rotateShares,
5746
5880
  exportPortableBackup,
@@ -5752,6 +5886,52 @@ function useSocialWallet() {
5752
5886
  clearError: () => setError(null)
5753
5887
  };
5754
5888
  }
5889
+ function useSocialBalance(chain) {
5890
+ const { socialAuth, socialGetBalance } = useDecaneContext();
5891
+ const [balance, setBalance] = useState4(null);
5892
+ const [loading, setLoading] = useState4(false);
5893
+ const [error, setError] = useState4(null);
5894
+ const addrKey = `${socialAuth.addresses?.evm ?? ""}|${socialAuth.addresses?.solana ?? ""}`;
5895
+ const refetch = useCallback4(async () => {
5896
+ if (!socialAuth.addresses) {
5897
+ setBalance(null);
5898
+ return;
5899
+ }
5900
+ setLoading(true);
5901
+ setError(null);
5902
+ try {
5903
+ setBalance(await socialGetBalance(chain));
5904
+ } catch (e) {
5905
+ setError(e.message);
5906
+ setBalance(null);
5907
+ } finally {
5908
+ setLoading(false);
5909
+ }
5910
+ }, [socialGetBalance, chain, socialAuth.addresses]);
5911
+ useEffect4(() => {
5912
+ let cancelled = false;
5913
+ if (!socialAuth.addresses) {
5914
+ setBalance(null);
5915
+ return;
5916
+ }
5917
+ setLoading(true);
5918
+ setError(null);
5919
+ socialGetBalance(chain).then((b) => {
5920
+ if (!cancelled) setBalance(b);
5921
+ }).catch((e) => {
5922
+ if (!cancelled) {
5923
+ setError(e.message);
5924
+ setBalance(null);
5925
+ }
5926
+ }).finally(() => {
5927
+ if (!cancelled) setLoading(false);
5928
+ });
5929
+ return () => {
5930
+ cancelled = true;
5931
+ };
5932
+ }, [addrKey, chain]);
5933
+ return { balance, loading, error, refetch };
5934
+ }
5755
5935
  function toDecaneError(err) {
5756
5936
  if (err instanceof DecaneError) return err;
5757
5937
  const msg = err instanceof Error ? err.message : err?.message != null ? String(err.message) : String(err);
@@ -5984,6 +6164,9 @@ export {
5984
6164
  DecaneError,
5985
6165
  DecaneErrorCode,
5986
6166
  DecaneKit,
6167
+ DecaneLogo,
6168
+ DecaneMark,
6169
+ DecaneWordmark,
5987
6170
  ExportNotAuthorizedError,
5988
6171
  InvalidApiKeyError,
5989
6172
  InvalidPinError,
@@ -6012,6 +6195,7 @@ export {
6012
6195
  useSignMessage,
6013
6196
  useSignTypedData,
6014
6197
  useSocialAuth,
6198
+ useSocialBalance,
6015
6199
  useSocialWallet,
6016
6200
  useWalletSelector,
6017
6201
  verifyEmailCode