decane-connect-kit 2.3.1 → 2.5.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.
package/dist/index.cjs CHANGED
@@ -1964,7 +1964,7 @@ function createDecane(config) {
1964
1964
  }
1965
1965
 
1966
1966
  // src/social/client.ts
1967
- var import_ethers2 = require("ethers");
1967
+ var import_ethers3 = require("ethers");
1968
1968
  var import_web32 = require("@solana/web3.js");
1969
1969
  init_errors();
1970
1970
 
@@ -2059,10 +2059,26 @@ var ApiClient = class {
2059
2059
  iv: bytesToB64(share.iv),
2060
2060
  wrappedShareMeta: btoa(JSON.stringify(share.wrappedShareMeta)),
2061
2061
  evmAddress: share.evmAddress,
2062
- solanaAddress: share.solanaAddress
2062
+ solanaAddress: share.solanaAddress,
2063
+ tronAddress: share.tronAddress
2063
2064
  })
2064
2065
  });
2065
2066
  }
2067
+ // ── Transaction history ───────────────────────────────────────────────────
2068
+ async recordTransaction(jwt, tx) {
2069
+ const body = await this._request("/transactions", {
2070
+ method: "POST",
2071
+ headers: { Authorization: `Bearer ${jwt}` },
2072
+ body: JSON.stringify(tx)
2073
+ });
2074
+ return body.transaction;
2075
+ }
2076
+ async getTransactions(jwt, limit = 50) {
2077
+ const body = await this._request(`/transactions?limit=${encodeURIComponent(String(limit))}`, {
2078
+ headers: { Authorization: `Bearer ${jwt}` }
2079
+ });
2080
+ return body.transactions;
2081
+ }
2066
2082
  // ── WebAuthn registration (additive to the PRF-only passkey flow) ─────────
2067
2083
  async getWebAuthnRegisterOptions(jwt, rpId, rpName) {
2068
2084
  return this._request(`/webauthn/register-options?rpId=${encodeURIComponent(rpId)}&rpName=${encodeURIComponent(rpName)}`, {
@@ -2200,6 +2216,9 @@ var Storage = class {
2200
2216
  }
2201
2217
  };
2202
2218
 
2219
+ // src/social/session.ts
2220
+ var import_ethers = require("ethers");
2221
+
2203
2222
  // src/social/teeClient.ts
2204
2223
  var import_browser = require("@simplewebauthn/browser");
2205
2224
 
@@ -2480,6 +2499,11 @@ var TeeClient = class {
2480
2499
 
2481
2500
  // src/social/session.ts
2482
2501
  init_errors();
2502
+ function evmToTronAddress(evmAddress) {
2503
+ const hex41 = "41" + evmAddress.toLowerCase().replace(/^0x/, "");
2504
+ const checksum = (0, import_ethers.sha256)((0, import_ethers.sha256)("0x" + hex41)).slice(2, 10);
2505
+ return (0, import_ethers.encodeBase58)("0x" + hex41 + checksum);
2506
+ }
2483
2507
  var SessionManager = class {
2484
2508
  constructor(events, durationMs, teeUrl, requireAssertionPerSignature = false) {
2485
2509
  this.events = events;
@@ -2489,6 +2513,7 @@ var SessionManager = class {
2489
2513
  this.tee = null;
2490
2514
  this.evmAddress = null;
2491
2515
  this.solanaAddress = null;
2516
+ this.tronAddress = null;
2492
2517
  this.expiresAt = null;
2493
2518
  this.timeoutId = null;
2494
2519
  }
@@ -2515,6 +2540,7 @@ var SessionManager = class {
2515
2540
  this.tee.adoptHandle(handle, this.requireAssertionPerSignature);
2516
2541
  this.evmAddress = addresses.evm;
2517
2542
  this.solanaAddress = addresses.solana;
2543
+ this.tronAddress = addresses.tron ?? evmToTronAddress(addresses.evm);
2518
2544
  this.expiresAt = expiresAtMs;
2519
2545
  this.setExpiryTimer(expiresAtMs - Date.now());
2520
2546
  this.events.emit("session-started");
@@ -2541,15 +2567,17 @@ var SessionManager = class {
2541
2567
  "requireAssertionPerSignature was requested but this signer does not support it \u2014 refusing to open a session with weaker authority than configured."
2542
2568
  );
2543
2569
  }
2544
- const addresses = verified ?? fallback;
2545
- if (!addresses) {
2570
+ const resolved = verified ?? fallback;
2571
+ if (!resolved) {
2546
2572
  this.tee = null;
2547
2573
  throw new Error(
2548
2574
  "No addresses available for this wallet \u2014 the signer could not derive them and none are recorded"
2549
2575
  );
2550
2576
  }
2577
+ const addresses = { evm: resolved.evm, solana: resolved.solana, tron: resolved.tron ?? evmToTronAddress(resolved.evm) };
2551
2578
  this.evmAddress = addresses.evm;
2552
2579
  this.solanaAddress = addresses.solana;
2580
+ this.tronAddress = addresses.tron;
2553
2581
  const serverTtlMs = this.tee.sessionExpiresIn();
2554
2582
  const effectiveMs = serverTtlMs != null ? Math.min(this.durationMs, serverTtlMs * 1e3) : this.durationMs;
2555
2583
  this.expiresAt = Date.now() + effectiveMs;
@@ -2566,6 +2594,7 @@ var SessionManager = class {
2566
2594
  this.tee = null;
2567
2595
  this.evmAddress = null;
2568
2596
  this.solanaAddress = null;
2597
+ this.tronAddress = null;
2569
2598
  this.expiresAt = null;
2570
2599
  if (this.timeoutId) {
2571
2600
  clearTimeout(this.timeoutId);
@@ -2584,7 +2613,11 @@ var SessionManager = class {
2584
2613
  }
2585
2614
  addresses() {
2586
2615
  if (!this.evmAddress || !this.solanaAddress) return null;
2587
- return { evm: this.evmAddress, solana: this.solanaAddress };
2616
+ return {
2617
+ evm: this.evmAddress,
2618
+ solana: this.solanaAddress,
2619
+ tron: this.tronAddress ?? evmToTronAddress(this.evmAddress)
2620
+ };
2588
2621
  }
2589
2622
  };
2590
2623
 
@@ -2767,12 +2800,12 @@ async function verifyEmailCode(api, email, code) {
2767
2800
  }
2768
2801
 
2769
2802
  // src/social/signers/evm.ts
2770
- var import_ethers = require("ethers");
2803
+ var import_ethers2 = require("ethers");
2771
2804
  async function signEvmTransaction(tee, chain, tx, jwt) {
2772
- const resolved = await (0, import_ethers.resolveProperties)(tx);
2773
- const unsigned = import_ethers.Transaction.from(resolved).unsignedSerialized;
2805
+ const resolved = await (0, import_ethers2.resolveProperties)(tx);
2806
+ const unsigned = import_ethers2.Transaction.from(resolved).unsignedSerialized;
2774
2807
  const payload = unsigned.startsWith("0x") ? unsigned.slice(2) : unsigned;
2775
- const txHash = (0, import_ethers.keccak256)("0x" + payload);
2808
+ const txHash = (0, import_ethers2.keccak256)("0x" + payload);
2776
2809
  return tee.sign({ chain, kind: "transaction", payload, txHash }, jwt);
2777
2810
  }
2778
2811
  async function signEvmMessage(tee, chain, message, jwt) {
@@ -3437,9 +3470,11 @@ async function createDecaneConnect(config) {
3437
3470
  let shareSet;
3438
3471
  let evmAddress;
3439
3472
  let solanaAddress;
3473
+ let tronAddress;
3440
3474
  try {
3441
- evmAddress = new import_ethers2.Wallet(toHex2(master)).address;
3475
+ evmAddress = new import_ethers3.Wallet(toHex2(master)).address;
3442
3476
  solanaAddress = import_web32.Keypair.fromSeed(master).publicKey.toBase58();
3477
+ tronAddress = evmToTronAddress2(evmAddress);
3443
3478
  shareSet = await splitMaster(master, 1);
3444
3479
  } finally {
3445
3480
  zeroize(master);
@@ -3470,10 +3505,11 @@ async function createDecaneConnect(config) {
3470
3505
  // credential IDs, prfSalt, pinSalt stay on-device — never sent to server
3471
3506
  },
3472
3507
  evmAddress,
3473
- solanaAddress
3508
+ solanaAddress,
3509
+ tronAddress
3474
3510
  });
3475
3511
  zeroize(shareSet.server);
3476
- const addresses = { evm: evmAddress, solana: solanaAddress };
3512
+ const addresses = { evm: evmAddress, solana: solanaAddress, tron: tronAddress };
3477
3513
  if (unlockMethod === "passkey" && meta.credentialId && meta.prfSalt) {
3478
3514
  try {
3479
3515
  await api.putRecoveryBackup(jwt, {
@@ -3496,6 +3532,7 @@ async function createDecaneConnect(config) {
3496
3532
  }
3497
3533
  addresses.evm = evmAddress = confirmed.evm;
3498
3534
  addresses.solana = solanaAddress = confirmed.solana;
3535
+ addresses.tron = tronAddress = confirmed.tron ?? evmToTronAddress2(confirmed.evm);
3499
3536
  if (config.offerRecoveryAtSignup !== false && config.onRecoveryShareOffer) {
3500
3537
  try {
3501
3538
  const choice = await config.onRecoveryShareOffer({ evmAddress, solanaAddress });
@@ -3519,7 +3556,7 @@ async function createDecaneConnect(config) {
3519
3556
  }
3520
3557
  async function returningUserUnlock(userId, jwt) {
3521
3558
  const rawAddresses = await api.getAddresses(jwt);
3522
- const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana } : null;
3559
+ const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana, tron: rawAddresses.tron ?? evmToTronAddress2(rawAddresses.evm) } : null;
3523
3560
  const stored = await storage.getShare(userId);
3524
3561
  let deviceShare;
3525
3562
  if (!stored) {
@@ -3601,7 +3638,7 @@ async function createDecaneConnect(config) {
3601
3638
  throw new ShareCorruptedError();
3602
3639
  }
3603
3640
  const rawAddresses = await api.getAddresses(result.jwt);
3604
- const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana } : null;
3641
+ const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana, tron: rawAddresses.tron ?? evmToTronAddress2(rawAddresses.evm) } : null;
3605
3642
  const addresses = await session.start(deviceShare, result.jwt, recordedAddresses);
3606
3643
  zeroize(deviceShare);
3607
3644
  auth = { jwt: result.jwt, userId, addresses };
@@ -3733,6 +3770,10 @@ async function createDecaneConnect(config) {
3733
3770
  const sig = await signSolanaMessage(tee, req.chain, msg, auth?.jwt);
3734
3771
  return bufferToB64u(sig);
3735
3772
  }
3773
+ if (req.chain.startsWith("tron:")) {
3774
+ const msg = typeof req.message === "string" ? req.message : new TextDecoder().decode(req.message);
3775
+ return tee.sign({ chain: req.chain, kind: "message", payload: msg }, auth?.jwt);
3776
+ }
3736
3777
  throw new CallSequenceError(`Unsupported chain: ${req.chain}`);
3737
3778
  },
3738
3779
  async sendTransaction(req) {
@@ -3780,6 +3821,16 @@ async function createDecaneConnect(config) {
3780
3821
  };
3781
3822
  const signedTx = await signEvmTransaction(tee, req.chain, tx, auth?.jwt);
3782
3823
  const txResponse = await provider.broadcastTransaction(signedTx);
3824
+ if (auth?.jwt) {
3825
+ void api.recordTransaction(auth.jwt, {
3826
+ chain: req.chain,
3827
+ txHash: txResponse.hash,
3828
+ to: req.to,
3829
+ value: (req.value ?? 0n).toString(),
3830
+ kind: "send"
3831
+ }).catch(() => {
3832
+ });
3833
+ }
3783
3834
  return txResponse.hash;
3784
3835
  },
3785
3836
  async signTypedData(req) {
@@ -3812,6 +3863,14 @@ async function createDecaneConnect(config) {
3812
3863
  getAccessToken() {
3813
3864
  return auth?.jwt ?? null;
3814
3865
  },
3866
+ async recordTransaction(tx) {
3867
+ if (!auth?.jwt) throw new CallSequenceError("Not connected \u2014 call connect() first");
3868
+ return api.recordTransaction(auth.jwt, tx);
3869
+ },
3870
+ async getTransactionHistory(limit = 50) {
3871
+ if (!auth?.jwt) throw new CallSequenceError("Not connected \u2014 call connect() first");
3872
+ return api.getTransactions(auth.jwt, limit);
3873
+ },
3815
3874
  getEthereumProvider(opts) {
3816
3875
  if (!ethProvider) {
3817
3876
  const firstEvm = config.chains.find((c) => c.startsWith("evm:"));
@@ -3834,6 +3893,14 @@ async function createDecaneConnect(config) {
3834
3893
  const solChain = config.chains.find((c) => c.startsWith("solana:")) ?? "solana:mainnet";
3835
3894
  return signSolanaTransaction(tee, solChain, tx, auth?.jwt);
3836
3895
  },
3896
+ async signTronTransaction(rawDataHex) {
3897
+ const tee = session.requireActive();
3898
+ const tronChain = config.chains.find((c) => c.startsWith("tron:")) ?? "tron:mainnet";
3899
+ return tee.sign(
3900
+ { chain: tronChain, kind: "transaction", payload: rawDataHex.replace(/^0x/, "") },
3901
+ auth?.jwt
3902
+ );
3903
+ },
3837
3904
  async disconnect() {
3838
3905
  session.end();
3839
3906
  if (auth?.jwt) {
@@ -3989,12 +4056,19 @@ function b64uToBuffer(b64u) {
3989
4056
  function toHex2(bytes) {
3990
4057
  return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
3991
4058
  }
4059
+ function evmToTronAddress2(evmAddress) {
4060
+ const hex41 = "41" + evmAddress.toLowerCase().replace(/^0x/, "");
4061
+ const checksum = (0, import_ethers3.sha256)((0, import_ethers3.sha256)("0x" + hex41)).slice(2, 10);
4062
+ return (0, import_ethers3.encodeBase58)("0x" + hex41 + checksum);
4063
+ }
3992
4064
  async function deriveAddressesFromShares(a, b) {
3993
4065
  const master = await combineShares(a, b);
3994
4066
  try {
4067
+ const evm = new import_ethers3.Wallet(toHex2(master)).address;
3995
4068
  return {
3996
- evm: new import_ethers2.Wallet(toHex2(master)).address,
3997
- solana: import_web32.Keypair.fromSeed(master).publicKey.toBase58()
4069
+ evm,
4070
+ solana: import_web32.Keypair.fromSeed(master).publicKey.toBase58(),
4071
+ tron: evmToTronAddress2(evm)
3998
4072
  };
3999
4073
  } finally {
4000
4074
  zeroize(master);
@@ -6009,6 +6083,21 @@ function DecaneKit({ config, children }) {
6009
6083
  if (!sdk) throw new Error("Social wallet not connected");
6010
6084
  return sdk.signSolanaTransaction(tx);
6011
6085
  }, []);
6086
+ const socialSignTronTransaction = (0, import_react5.useCallback)(async (rawDataHex) => {
6087
+ const sdk = socialRef.current;
6088
+ if (!sdk) throw new Error("Social wallet not connected");
6089
+ return sdk.signTronTransaction(rawDataHex);
6090
+ }, []);
6091
+ const socialRecordTransaction = (0, import_react5.useCallback)(async (tx) => {
6092
+ const sdk = socialRef.current;
6093
+ if (!sdk) throw new Error("Social wallet not connected");
6094
+ return sdk.recordTransaction(tx);
6095
+ }, []);
6096
+ const socialGetTransactionHistory = (0, import_react5.useCallback)(async (limit) => {
6097
+ const sdk = socialRef.current;
6098
+ if (!sdk) throw new Error("Social wallet not connected");
6099
+ return sdk.getTransactionHistory(limit);
6100
+ }, []);
6012
6101
  const socialSignTypedData = (0, import_react5.useCallback)(async (req) => {
6013
6102
  const sdk = socialRef.current;
6014
6103
  if (!sdk) throw new Error("Social wallet not connected");
@@ -6099,6 +6188,9 @@ function DecaneKit({ config, children }) {
6099
6188
  socialGetBalances,
6100
6189
  socialGetEthereumProvider,
6101
6190
  socialSignAuthorization,
6191
+ socialSignTronTransaction,
6192
+ socialRecordTransaction,
6193
+ socialGetTransactionHistory,
6102
6194
  socialGetAccessToken,
6103
6195
  socialSignSolanaTransaction,
6104
6196
  socialSignTypedData,
@@ -6319,6 +6411,9 @@ function useSocialWallet() {
6319
6411
  socialSignMessage,
6320
6412
  socialSendTransaction,
6321
6413
  socialSignSolanaTransaction,
6414
+ socialSignTronTransaction,
6415
+ socialRecordTransaction,
6416
+ socialGetTransactionHistory,
6322
6417
  socialSignTypedData,
6323
6418
  socialGetBalance,
6324
6419
  socialGetBalances,
@@ -6361,6 +6456,18 @@ function useSocialWallet() {
6361
6456
  (tx) => run(() => socialSignSolanaTransaction(tx)),
6362
6457
  [socialSignSolanaTransaction]
6363
6458
  );
6459
+ const signTronTransaction = (0, import_react6.useCallback)(
6460
+ (rawDataHex) => run(() => socialSignTronTransaction(rawDataHex)),
6461
+ [socialSignTronTransaction]
6462
+ );
6463
+ const recordTransaction = (0, import_react6.useCallback)(
6464
+ (tx) => run(() => socialRecordTransaction(tx)),
6465
+ [socialRecordTransaction]
6466
+ );
6467
+ const getTransactionHistory = (0, import_react6.useCallback)(
6468
+ (limit) => socialGetTransactionHistory(limit),
6469
+ [socialGetTransactionHistory]
6470
+ );
6364
6471
  const signTypedData = (0, import_react6.useCallback)(
6365
6472
  (req) => run(() => socialSignTypedData(req)),
6366
6473
  [socialSignTypedData]
@@ -6442,6 +6549,9 @@ function useSocialWallet() {
6442
6549
  signMessage,
6443
6550
  sendTransaction,
6444
6551
  signSolanaTransaction: signSolanaTransaction2,
6552
+ signTronTransaction,
6553
+ recordTransaction,
6554
+ getTransactionHistory,
6445
6555
  signTypedData,
6446
6556
  // Balances (native token; read-only, works while locked)
6447
6557
  getBalance,