decane-connect-kit 2.3.0 → 2.4.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 +88 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -29
- package/dist/index.d.ts +48 -29
- package/dist/index.js +83 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1964,7 +1964,7 @@ function createDecane(config) {
|
|
|
1964
1964
|
}
|
|
1965
1965
|
|
|
1966
1966
|
// src/social/client.ts
|
|
1967
|
-
var
|
|
1967
|
+
var import_ethers3 = require("ethers");
|
|
1968
1968
|
var import_web32 = require("@solana/web3.js");
|
|
1969
1969
|
init_errors();
|
|
1970
1970
|
|
|
@@ -2059,7 +2059,8 @@ 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
|
}
|
|
@@ -2200,6 +2201,9 @@ var Storage = class {
|
|
|
2200
2201
|
}
|
|
2201
2202
|
};
|
|
2202
2203
|
|
|
2204
|
+
// src/social/session.ts
|
|
2205
|
+
var import_ethers = require("ethers");
|
|
2206
|
+
|
|
2203
2207
|
// src/social/teeClient.ts
|
|
2204
2208
|
var import_browser = require("@simplewebauthn/browser");
|
|
2205
2209
|
|
|
@@ -2480,6 +2484,11 @@ var TeeClient = class {
|
|
|
2480
2484
|
|
|
2481
2485
|
// src/social/session.ts
|
|
2482
2486
|
init_errors();
|
|
2487
|
+
function evmToTronAddress(evmAddress) {
|
|
2488
|
+
const hex41 = "41" + evmAddress.toLowerCase().replace(/^0x/, "");
|
|
2489
|
+
const checksum = (0, import_ethers.sha256)((0, import_ethers.sha256)("0x" + hex41)).slice(2, 10);
|
|
2490
|
+
return (0, import_ethers.encodeBase58)("0x" + hex41 + checksum);
|
|
2491
|
+
}
|
|
2483
2492
|
var SessionManager = class {
|
|
2484
2493
|
constructor(events, durationMs, teeUrl, requireAssertionPerSignature = false) {
|
|
2485
2494
|
this.events = events;
|
|
@@ -2489,6 +2498,7 @@ var SessionManager = class {
|
|
|
2489
2498
|
this.tee = null;
|
|
2490
2499
|
this.evmAddress = null;
|
|
2491
2500
|
this.solanaAddress = null;
|
|
2501
|
+
this.tronAddress = null;
|
|
2492
2502
|
this.expiresAt = null;
|
|
2493
2503
|
this.timeoutId = null;
|
|
2494
2504
|
}
|
|
@@ -2515,6 +2525,7 @@ var SessionManager = class {
|
|
|
2515
2525
|
this.tee.adoptHandle(handle, this.requireAssertionPerSignature);
|
|
2516
2526
|
this.evmAddress = addresses.evm;
|
|
2517
2527
|
this.solanaAddress = addresses.solana;
|
|
2528
|
+
this.tronAddress = addresses.tron ?? evmToTronAddress(addresses.evm);
|
|
2518
2529
|
this.expiresAt = expiresAtMs;
|
|
2519
2530
|
this.setExpiryTimer(expiresAtMs - Date.now());
|
|
2520
2531
|
this.events.emit("session-started");
|
|
@@ -2541,15 +2552,17 @@ var SessionManager = class {
|
|
|
2541
2552
|
"requireAssertionPerSignature was requested but this signer does not support it \u2014 refusing to open a session with weaker authority than configured."
|
|
2542
2553
|
);
|
|
2543
2554
|
}
|
|
2544
|
-
const
|
|
2545
|
-
if (!
|
|
2555
|
+
const resolved = verified ?? fallback;
|
|
2556
|
+
if (!resolved) {
|
|
2546
2557
|
this.tee = null;
|
|
2547
2558
|
throw new Error(
|
|
2548
2559
|
"No addresses available for this wallet \u2014 the signer could not derive them and none are recorded"
|
|
2549
2560
|
);
|
|
2550
2561
|
}
|
|
2562
|
+
const addresses = { evm: resolved.evm, solana: resolved.solana, tron: resolved.tron ?? evmToTronAddress(resolved.evm) };
|
|
2551
2563
|
this.evmAddress = addresses.evm;
|
|
2552
2564
|
this.solanaAddress = addresses.solana;
|
|
2565
|
+
this.tronAddress = addresses.tron;
|
|
2553
2566
|
const serverTtlMs = this.tee.sessionExpiresIn();
|
|
2554
2567
|
const effectiveMs = serverTtlMs != null ? Math.min(this.durationMs, serverTtlMs * 1e3) : this.durationMs;
|
|
2555
2568
|
this.expiresAt = Date.now() + effectiveMs;
|
|
@@ -2566,6 +2579,7 @@ var SessionManager = class {
|
|
|
2566
2579
|
this.tee = null;
|
|
2567
2580
|
this.evmAddress = null;
|
|
2568
2581
|
this.solanaAddress = null;
|
|
2582
|
+
this.tronAddress = null;
|
|
2569
2583
|
this.expiresAt = null;
|
|
2570
2584
|
if (this.timeoutId) {
|
|
2571
2585
|
clearTimeout(this.timeoutId);
|
|
@@ -2584,7 +2598,11 @@ var SessionManager = class {
|
|
|
2584
2598
|
}
|
|
2585
2599
|
addresses() {
|
|
2586
2600
|
if (!this.evmAddress || !this.solanaAddress) return null;
|
|
2587
|
-
return {
|
|
2601
|
+
return {
|
|
2602
|
+
evm: this.evmAddress,
|
|
2603
|
+
solana: this.solanaAddress,
|
|
2604
|
+
tron: this.tronAddress ?? evmToTronAddress(this.evmAddress)
|
|
2605
|
+
};
|
|
2588
2606
|
}
|
|
2589
2607
|
};
|
|
2590
2608
|
|
|
@@ -2767,12 +2785,12 @@ async function verifyEmailCode(api, email, code) {
|
|
|
2767
2785
|
}
|
|
2768
2786
|
|
|
2769
2787
|
// src/social/signers/evm.ts
|
|
2770
|
-
var
|
|
2788
|
+
var import_ethers2 = require("ethers");
|
|
2771
2789
|
async function signEvmTransaction(tee, chain, tx, jwt) {
|
|
2772
|
-
const resolved = await (0,
|
|
2773
|
-
const unsigned =
|
|
2790
|
+
const resolved = await (0, import_ethers2.resolveProperties)(tx);
|
|
2791
|
+
const unsigned = import_ethers2.Transaction.from(resolved).unsignedSerialized;
|
|
2774
2792
|
const payload = unsigned.startsWith("0x") ? unsigned.slice(2) : unsigned;
|
|
2775
|
-
const txHash = (0,
|
|
2793
|
+
const txHash = (0, import_ethers2.keccak256)("0x" + payload);
|
|
2776
2794
|
return tee.sign({ chain, kind: "transaction", payload, txHash }, jwt);
|
|
2777
2795
|
}
|
|
2778
2796
|
async function signEvmMessage(tee, chain, message, jwt) {
|
|
@@ -2787,7 +2805,7 @@ async function signEvmAuthorization(tee, chainId, address, nonce, jwt) {
|
|
|
2787
2805
|
const r = "0x" + hex.slice(0, 64);
|
|
2788
2806
|
const s = "0x" + hex.slice(64, 128);
|
|
2789
2807
|
const v = parseInt(hex.slice(128, 130), 16);
|
|
2790
|
-
return { yParity: v >= 27 ? v - 27 : v, r, s };
|
|
2808
|
+
return { chainId, address, nonce, yParity: v >= 27 ? v - 27 : v, r, s };
|
|
2791
2809
|
}
|
|
2792
2810
|
async function signEvmTypedData(tee, chain, typedData, jwt) {
|
|
2793
2811
|
const payload = JSON.stringify(
|
|
@@ -2948,9 +2966,6 @@ function createEthereumProvider(client, opts = {}) {
|
|
|
2948
2966
|
}
|
|
2949
2967
|
case "eth_signAuthorization":
|
|
2950
2968
|
case "wallet_sign7702Authorization": {
|
|
2951
|
-
if (!client.signAuthorization) {
|
|
2952
|
-
throw Object.assign(new Error("EIP-7702 is not supported by the connected signer."), { code: 4200 });
|
|
2953
|
-
}
|
|
2954
2969
|
const p = params[0];
|
|
2955
2970
|
const cid = p.chainId != null ? Number(asBigInt(p.chainId)) : chainId;
|
|
2956
2971
|
const address = p.address ?? p.contractAddress;
|
|
@@ -3440,9 +3455,11 @@ async function createDecaneConnect(config) {
|
|
|
3440
3455
|
let shareSet;
|
|
3441
3456
|
let evmAddress;
|
|
3442
3457
|
let solanaAddress;
|
|
3458
|
+
let tronAddress;
|
|
3443
3459
|
try {
|
|
3444
|
-
evmAddress = new
|
|
3460
|
+
evmAddress = new import_ethers3.Wallet(toHex2(master)).address;
|
|
3445
3461
|
solanaAddress = import_web32.Keypair.fromSeed(master).publicKey.toBase58();
|
|
3462
|
+
tronAddress = evmToTronAddress2(evmAddress);
|
|
3446
3463
|
shareSet = await splitMaster(master, 1);
|
|
3447
3464
|
} finally {
|
|
3448
3465
|
zeroize(master);
|
|
@@ -3473,10 +3490,11 @@ async function createDecaneConnect(config) {
|
|
|
3473
3490
|
// credential IDs, prfSalt, pinSalt stay on-device — never sent to server
|
|
3474
3491
|
},
|
|
3475
3492
|
evmAddress,
|
|
3476
|
-
solanaAddress
|
|
3493
|
+
solanaAddress,
|
|
3494
|
+
tronAddress
|
|
3477
3495
|
});
|
|
3478
3496
|
zeroize(shareSet.server);
|
|
3479
|
-
const addresses = { evm: evmAddress, solana: solanaAddress };
|
|
3497
|
+
const addresses = { evm: evmAddress, solana: solanaAddress, tron: tronAddress };
|
|
3480
3498
|
if (unlockMethod === "passkey" && meta.credentialId && meta.prfSalt) {
|
|
3481
3499
|
try {
|
|
3482
3500
|
await api.putRecoveryBackup(jwt, {
|
|
@@ -3499,6 +3517,7 @@ async function createDecaneConnect(config) {
|
|
|
3499
3517
|
}
|
|
3500
3518
|
addresses.evm = evmAddress = confirmed.evm;
|
|
3501
3519
|
addresses.solana = solanaAddress = confirmed.solana;
|
|
3520
|
+
addresses.tron = tronAddress = confirmed.tron ?? evmToTronAddress2(confirmed.evm);
|
|
3502
3521
|
if (config.offerRecoveryAtSignup !== false && config.onRecoveryShareOffer) {
|
|
3503
3522
|
try {
|
|
3504
3523
|
const choice = await config.onRecoveryShareOffer({ evmAddress, solanaAddress });
|
|
@@ -3522,7 +3541,7 @@ async function createDecaneConnect(config) {
|
|
|
3522
3541
|
}
|
|
3523
3542
|
async function returningUserUnlock(userId, jwt) {
|
|
3524
3543
|
const rawAddresses = await api.getAddresses(jwt);
|
|
3525
|
-
const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana } : null;
|
|
3544
|
+
const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana, tron: rawAddresses.tron ?? evmToTronAddress2(rawAddresses.evm) } : null;
|
|
3526
3545
|
const stored = await storage.getShare(userId);
|
|
3527
3546
|
let deviceShare;
|
|
3528
3547
|
if (!stored) {
|
|
@@ -3604,7 +3623,7 @@ async function createDecaneConnect(config) {
|
|
|
3604
3623
|
throw new ShareCorruptedError();
|
|
3605
3624
|
}
|
|
3606
3625
|
const rawAddresses = await api.getAddresses(result.jwt);
|
|
3607
|
-
const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana } : null;
|
|
3626
|
+
const recordedAddresses = rawAddresses.evm && rawAddresses.solana ? { evm: rawAddresses.evm, solana: rawAddresses.solana, tron: rawAddresses.tron ?? evmToTronAddress2(rawAddresses.evm) } : null;
|
|
3608
3627
|
const addresses = await session.start(deviceShare, result.jwt, recordedAddresses);
|
|
3609
3628
|
zeroize(deviceShare);
|
|
3610
3629
|
auth = { jwt: result.jwt, userId, addresses };
|
|
@@ -3736,6 +3755,10 @@ async function createDecaneConnect(config) {
|
|
|
3736
3755
|
const sig = await signSolanaMessage(tee, req.chain, msg, auth?.jwt);
|
|
3737
3756
|
return bufferToB64u(sig);
|
|
3738
3757
|
}
|
|
3758
|
+
if (req.chain.startsWith("tron:")) {
|
|
3759
|
+
const msg = typeof req.message === "string" ? req.message : new TextDecoder().decode(req.message);
|
|
3760
|
+
return tee.sign({ chain: req.chain, kind: "message", payload: msg }, auth?.jwt);
|
|
3761
|
+
}
|
|
3739
3762
|
throw new CallSequenceError(`Unsupported chain: ${req.chain}`);
|
|
3740
3763
|
},
|
|
3741
3764
|
async sendTransaction(req) {
|
|
@@ -3804,7 +3827,16 @@ async function createDecaneConnect(config) {
|
|
|
3804
3827
|
},
|
|
3805
3828
|
async signAuthorization(req) {
|
|
3806
3829
|
const tee = session.requireActive();
|
|
3807
|
-
|
|
3830
|
+
const delegate = req.address ?? req.contractAddress;
|
|
3831
|
+
if (!delegate) throw new CallSequenceError("signAuthorization requires `address` (the delegate contract).");
|
|
3832
|
+
return signEvmAuthorization(tee, req.chainId, delegate, req.nonce, auth?.jwt);
|
|
3833
|
+
},
|
|
3834
|
+
// The current session's access token (the Decane JWT), for authenticating
|
|
3835
|
+
// the user to your own backend — e.g. a sponsored-bundler proxy. Verify it
|
|
3836
|
+
// server-side against https://backend.decane.app/.well-known/jwks.json.
|
|
3837
|
+
// Null when there is no live session.
|
|
3838
|
+
getAccessToken() {
|
|
3839
|
+
return auth?.jwt ?? null;
|
|
3808
3840
|
},
|
|
3809
3841
|
getEthereumProvider(opts) {
|
|
3810
3842
|
if (!ethProvider) {
|
|
@@ -3828,6 +3860,14 @@ async function createDecaneConnect(config) {
|
|
|
3828
3860
|
const solChain = config.chains.find((c) => c.startsWith("solana:")) ?? "solana:mainnet";
|
|
3829
3861
|
return signSolanaTransaction(tee, solChain, tx, auth?.jwt);
|
|
3830
3862
|
},
|
|
3863
|
+
async signTronTransaction(rawDataHex) {
|
|
3864
|
+
const tee = session.requireActive();
|
|
3865
|
+
const tronChain = config.chains.find((c) => c.startsWith("tron:")) ?? "tron:mainnet";
|
|
3866
|
+
return tee.sign(
|
|
3867
|
+
{ chain: tronChain, kind: "transaction", payload: rawDataHex.replace(/^0x/, "") },
|
|
3868
|
+
auth?.jwt
|
|
3869
|
+
);
|
|
3870
|
+
},
|
|
3831
3871
|
async disconnect() {
|
|
3832
3872
|
session.end();
|
|
3833
3873
|
if (auth?.jwt) {
|
|
@@ -3983,12 +4023,19 @@ function b64uToBuffer(b64u) {
|
|
|
3983
4023
|
function toHex2(bytes) {
|
|
3984
4024
|
return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3985
4025
|
}
|
|
4026
|
+
function evmToTronAddress2(evmAddress) {
|
|
4027
|
+
const hex41 = "41" + evmAddress.toLowerCase().replace(/^0x/, "");
|
|
4028
|
+
const checksum = (0, import_ethers3.sha256)((0, import_ethers3.sha256)("0x" + hex41)).slice(2, 10);
|
|
4029
|
+
return (0, import_ethers3.encodeBase58)("0x" + hex41 + checksum);
|
|
4030
|
+
}
|
|
3986
4031
|
async function deriveAddressesFromShares(a, b) {
|
|
3987
4032
|
const master = await combineShares(a, b);
|
|
3988
4033
|
try {
|
|
4034
|
+
const evm = new import_ethers3.Wallet(toHex2(master)).address;
|
|
3989
4035
|
return {
|
|
3990
|
-
evm
|
|
3991
|
-
solana: import_web32.Keypair.fromSeed(master).publicKey.toBase58()
|
|
4036
|
+
evm,
|
|
4037
|
+
solana: import_web32.Keypair.fromSeed(master).publicKey.toBase58(),
|
|
4038
|
+
tron: evmToTronAddress2(evm)
|
|
3992
4039
|
};
|
|
3993
4040
|
} finally {
|
|
3994
4041
|
zeroize(master);
|
|
@@ -6003,6 +6050,11 @@ function DecaneKit({ config, children }) {
|
|
|
6003
6050
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
6004
6051
|
return sdk.signSolanaTransaction(tx);
|
|
6005
6052
|
}, []);
|
|
6053
|
+
const socialSignTronTransaction = (0, import_react5.useCallback)(async (rawDataHex) => {
|
|
6054
|
+
const sdk = socialRef.current;
|
|
6055
|
+
if (!sdk) throw new Error("Social wallet not connected");
|
|
6056
|
+
return sdk.signTronTransaction(rawDataHex);
|
|
6057
|
+
}, []);
|
|
6006
6058
|
const socialSignTypedData = (0, import_react5.useCallback)(async (req) => {
|
|
6007
6059
|
const sdk = socialRef.current;
|
|
6008
6060
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
@@ -6026,6 +6078,9 @@ function DecaneKit({ config, children }) {
|
|
|
6026
6078
|
},
|
|
6027
6079
|
[]
|
|
6028
6080
|
);
|
|
6081
|
+
const socialGetAccessToken = (0, import_react5.useCallback)(() => {
|
|
6082
|
+
return socialRef.current?.getAccessToken() ?? null;
|
|
6083
|
+
}, []);
|
|
6029
6084
|
const socialGetBalances = (0, import_react5.useCallback)(async () => {
|
|
6030
6085
|
const sdk = socialRef.current;
|
|
6031
6086
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
@@ -6090,6 +6145,8 @@ function DecaneKit({ config, children }) {
|
|
|
6090
6145
|
socialGetBalances,
|
|
6091
6146
|
socialGetEthereumProvider,
|
|
6092
6147
|
socialSignAuthorization,
|
|
6148
|
+
socialSignTronTransaction,
|
|
6149
|
+
socialGetAccessToken,
|
|
6093
6150
|
socialSignSolanaTransaction,
|
|
6094
6151
|
socialSignTypedData,
|
|
6095
6152
|
socialRotateShares,
|
|
@@ -6309,11 +6366,13 @@ function useSocialWallet() {
|
|
|
6309
6366
|
socialSignMessage,
|
|
6310
6367
|
socialSendTransaction,
|
|
6311
6368
|
socialSignSolanaTransaction,
|
|
6369
|
+
socialSignTronTransaction,
|
|
6312
6370
|
socialSignTypedData,
|
|
6313
6371
|
socialGetBalance,
|
|
6314
6372
|
socialGetBalances,
|
|
6315
6373
|
socialGetEthereumProvider,
|
|
6316
6374
|
socialSignAuthorization,
|
|
6375
|
+
socialGetAccessToken,
|
|
6317
6376
|
socialRotateShares,
|
|
6318
6377
|
socialExportPortableBackup,
|
|
6319
6378
|
socialHasRecoveryShare,
|
|
@@ -6350,6 +6409,10 @@ function useSocialWallet() {
|
|
|
6350
6409
|
(tx) => run(() => socialSignSolanaTransaction(tx)),
|
|
6351
6410
|
[socialSignSolanaTransaction]
|
|
6352
6411
|
);
|
|
6412
|
+
const signTronTransaction = (0, import_react6.useCallback)(
|
|
6413
|
+
(rawDataHex) => run(() => socialSignTronTransaction(rawDataHex)),
|
|
6414
|
+
[socialSignTronTransaction]
|
|
6415
|
+
);
|
|
6353
6416
|
const signTypedData = (0, import_react6.useCallback)(
|
|
6354
6417
|
(req) => run(() => socialSignTypedData(req)),
|
|
6355
6418
|
[socialSignTypedData]
|
|
@@ -6431,6 +6494,7 @@ function useSocialWallet() {
|
|
|
6431
6494
|
signMessage,
|
|
6432
6495
|
sendTransaction,
|
|
6433
6496
|
signSolanaTransaction: signSolanaTransaction2,
|
|
6497
|
+
signTronTransaction,
|
|
6434
6498
|
signTypedData,
|
|
6435
6499
|
// Balances (native token; read-only, works while locked)
|
|
6436
6500
|
getBalance,
|
|
@@ -6439,6 +6503,9 @@ function useSocialWallet() {
|
|
|
6439
6503
|
signAuthorization,
|
|
6440
6504
|
// An EIP-1193 provider for viem/wagmi/ethers (memoized).
|
|
6441
6505
|
getEthereumProvider: socialGetEthereumProvider,
|
|
6506
|
+
// The Decane JWT — authenticate the user to your own backend (bundler proxy,
|
|
6507
|
+
// etc.); verify server-side against backend.decane.app/.well-known/jwks.json.
|
|
6508
|
+
getAccessToken: socialGetAccessToken,
|
|
6442
6509
|
// Recovery (2-of-3 Shamir share set)
|
|
6443
6510
|
rotateShares,
|
|
6444
6511
|
exportPortableBackup,
|