decane-connect-kit 2.2.8 → 2.3.1
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 +273 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +272 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -294,6 +294,39 @@ interface BalanceResult {
|
|
|
294
294
|
decimals: number;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
interface Eip1193Provider {
|
|
298
|
+
request(args: {
|
|
299
|
+
method: string;
|
|
300
|
+
params?: unknown[] | object;
|
|
301
|
+
}): Promise<unknown>;
|
|
302
|
+
on(event: string, handler: (...args: unknown[]) => void): this;
|
|
303
|
+
removeListener(event: string, handler: (...args: unknown[]) => void): this;
|
|
304
|
+
/** Marks this as the Decane provider (parallel to wallets' isMetaMask etc.). */
|
|
305
|
+
readonly isDecane: true;
|
|
306
|
+
}
|
|
307
|
+
interface EthereumProviderOptions {
|
|
308
|
+
/** Initial chain id (numeric). Defaults to the first configured EVM chain, else 1. */
|
|
309
|
+
chainId?: number;
|
|
310
|
+
/** Per-chain RPC overrides ('evm:8453' -> url). Falls back to Decane's defaults. */
|
|
311
|
+
rpcUrls?: Record<string, string>;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Build an EIP-1193 provider over a connected Decane social client.
|
|
315
|
+
*
|
|
316
|
+
* `signAuthorization` (EIP-7702) is wired only when the client exposes it — that
|
|
317
|
+
* requires the TEE signer to support the authorization signing path.
|
|
318
|
+
*/
|
|
319
|
+
declare function createEthereumProvider(client: DecaneConnect, opts?: EthereumProviderOptions): Eip1193Provider;
|
|
320
|
+
|
|
321
|
+
interface SignedAuthorization {
|
|
322
|
+
chainId: number;
|
|
323
|
+
address: string;
|
|
324
|
+
nonce: number;
|
|
325
|
+
yParity: number;
|
|
326
|
+
r: string;
|
|
327
|
+
s: string;
|
|
328
|
+
}
|
|
329
|
+
|
|
297
330
|
type Chain = `evm:${number}` | `solana:${'mainnet' | 'devnet'}`;
|
|
298
331
|
interface DecaneConnectConfig {
|
|
299
332
|
/** Dashboard project ID (public). Sent with every request so the backend can
|
|
@@ -446,6 +479,36 @@ interface DecaneConnect {
|
|
|
446
479
|
sendTransaction(req: SendTransactionRequest): Promise<string>;
|
|
447
480
|
/** Sign EIP-712 typed data (EVM only). Throws on a Solana chain. */
|
|
448
481
|
signTypedData(req: SignTypedDataRequest): Promise<string>;
|
|
482
|
+
/**
|
|
483
|
+
* A standard EIP-1193 Ethereum provider backed by this wallet — drop it into
|
|
484
|
+
* viem (`custom(provider)`), wagmi, or ethers (`BrowserProvider`). Signing
|
|
485
|
+
* goes through the TEE; reads are forwarded to the chain RPC. Memoized, so
|
|
486
|
+
* repeated calls return the same instance (safe for wagmi).
|
|
487
|
+
*/
|
|
488
|
+
getEthereumProvider(opts?: {
|
|
489
|
+
chainId?: number;
|
|
490
|
+
}): Eip1193Provider;
|
|
491
|
+
/**
|
|
492
|
+
* Sign an EIP-7702 authorization, delegating this EOA to a smart-account
|
|
493
|
+
* implementation contract on `chainId`. Enables account-abstraction /
|
|
494
|
+
* sponsored-gas flows. Returns the full viem `SignedAuthorization` tuple, so
|
|
495
|
+
* it drops straight into a userOperation's `authorization` field or a type-4
|
|
496
|
+
* transaction's authorizationList. `address` and `contractAddress` are
|
|
497
|
+
* interchangeable (the latter matches Privy's/older viem's param name).
|
|
498
|
+
*/
|
|
499
|
+
signAuthorization(req: {
|
|
500
|
+
chainId: number;
|
|
501
|
+
address?: string;
|
|
502
|
+
contractAddress?: string;
|
|
503
|
+
nonce: number;
|
|
504
|
+
}): Promise<SignedAuthorization>;
|
|
505
|
+
/**
|
|
506
|
+
* The current session's access token (the Decane JWT). Use it to authenticate
|
|
507
|
+
* the user to your own backend (e.g. a sponsored-bundler proxy); verify it
|
|
508
|
+
* server-side against backend.decane.app/.well-known/jwks.json. Null with no
|
|
509
|
+
* live session.
|
|
510
|
+
*/
|
|
511
|
+
getAccessToken(): string | null;
|
|
449
512
|
signSolanaTransaction(tx: Uint8Array): Promise<Uint8Array>;
|
|
450
513
|
disconnect(): Promise<void>;
|
|
451
514
|
getAddresses(): {
|
|
@@ -866,6 +929,16 @@ declare function useSocialWallet(): {
|
|
|
866
929
|
chain: string;
|
|
867
930
|
balance: BalanceResult | null;
|
|
868
931
|
}[]>;
|
|
932
|
+
signAuthorization: (req: {
|
|
933
|
+
chainId: number;
|
|
934
|
+
address?: string;
|
|
935
|
+
contractAddress?: string;
|
|
936
|
+
nonce: number;
|
|
937
|
+
}) => Promise<SignedAuthorization>;
|
|
938
|
+
getEthereumProvider: (opts?: {
|
|
939
|
+
chainId?: number;
|
|
940
|
+
}) => Eip1193Provider;
|
|
941
|
+
getAccessToken: () => string | null;
|
|
869
942
|
rotateShares: (opts: {
|
|
870
943
|
password: string;
|
|
871
944
|
passwordHint?: string;
|
|
@@ -887,6 +960,9 @@ declare function useSocialBalance(chain?: string): {
|
|
|
887
960
|
error: string | null;
|
|
888
961
|
refetch: () => Promise<void>;
|
|
889
962
|
};
|
|
963
|
+
declare function useEthereumProvider(opts?: {
|
|
964
|
+
chainId?: number;
|
|
965
|
+
}): Eip1193Provider | null;
|
|
890
966
|
declare function useDecane(): {
|
|
891
967
|
provider: DecaneProvider;
|
|
892
968
|
wallets: UnifiedWalletAccount[];
|
|
@@ -959,4 +1035,4 @@ declare function useSignTypedData(): {
|
|
|
959
1035
|
reset: () => void;
|
|
960
1036
|
};
|
|
961
1037
|
|
|
962
|
-
export { type ActiveSession, AttestationError, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, CallSequenceError, type Chain, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type ConnectMode, type ConnectResult, type DecaneConfig, type DecaneConnect, type DecaneConnectConfig, DecaneConnectError, DecaneError, DecaneErrorCode, DecaneKit, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPinNotConfiguredError, ReconnectRequiredError, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SocialAuthState, type SocialConfig, SocialWalletModal, type Theme, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UserCancelledError, WalletSelector, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, createDecane, createDecaneConnect, startEmailAuth, useChainSwitch, useDecane, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, verifyEmailCode };
|
|
1038
|
+
export { type ActiveSession, AttestationError, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, CallSequenceError, type Chain, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type ConnectMode, type ConnectResult, type DecaneConfig, type DecaneConnect, type DecaneConnectConfig, DecaneConnectError, DecaneError, DecaneErrorCode, DecaneKit, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPinNotConfiguredError, ReconnectRequiredError, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, type Theme, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UserCancelledError, WalletSelector, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, createDecane, createDecaneConnect, createEthereumProvider, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, verifyEmailCode };
|
package/dist/index.d.ts
CHANGED
|
@@ -294,6 +294,39 @@ interface BalanceResult {
|
|
|
294
294
|
decimals: number;
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
interface Eip1193Provider {
|
|
298
|
+
request(args: {
|
|
299
|
+
method: string;
|
|
300
|
+
params?: unknown[] | object;
|
|
301
|
+
}): Promise<unknown>;
|
|
302
|
+
on(event: string, handler: (...args: unknown[]) => void): this;
|
|
303
|
+
removeListener(event: string, handler: (...args: unknown[]) => void): this;
|
|
304
|
+
/** Marks this as the Decane provider (parallel to wallets' isMetaMask etc.). */
|
|
305
|
+
readonly isDecane: true;
|
|
306
|
+
}
|
|
307
|
+
interface EthereumProviderOptions {
|
|
308
|
+
/** Initial chain id (numeric). Defaults to the first configured EVM chain, else 1. */
|
|
309
|
+
chainId?: number;
|
|
310
|
+
/** Per-chain RPC overrides ('evm:8453' -> url). Falls back to Decane's defaults. */
|
|
311
|
+
rpcUrls?: Record<string, string>;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Build an EIP-1193 provider over a connected Decane social client.
|
|
315
|
+
*
|
|
316
|
+
* `signAuthorization` (EIP-7702) is wired only when the client exposes it — that
|
|
317
|
+
* requires the TEE signer to support the authorization signing path.
|
|
318
|
+
*/
|
|
319
|
+
declare function createEthereumProvider(client: DecaneConnect, opts?: EthereumProviderOptions): Eip1193Provider;
|
|
320
|
+
|
|
321
|
+
interface SignedAuthorization {
|
|
322
|
+
chainId: number;
|
|
323
|
+
address: string;
|
|
324
|
+
nonce: number;
|
|
325
|
+
yParity: number;
|
|
326
|
+
r: string;
|
|
327
|
+
s: string;
|
|
328
|
+
}
|
|
329
|
+
|
|
297
330
|
type Chain = `evm:${number}` | `solana:${'mainnet' | 'devnet'}`;
|
|
298
331
|
interface DecaneConnectConfig {
|
|
299
332
|
/** Dashboard project ID (public). Sent with every request so the backend can
|
|
@@ -446,6 +479,36 @@ interface DecaneConnect {
|
|
|
446
479
|
sendTransaction(req: SendTransactionRequest): Promise<string>;
|
|
447
480
|
/** Sign EIP-712 typed data (EVM only). Throws on a Solana chain. */
|
|
448
481
|
signTypedData(req: SignTypedDataRequest): Promise<string>;
|
|
482
|
+
/**
|
|
483
|
+
* A standard EIP-1193 Ethereum provider backed by this wallet — drop it into
|
|
484
|
+
* viem (`custom(provider)`), wagmi, or ethers (`BrowserProvider`). Signing
|
|
485
|
+
* goes through the TEE; reads are forwarded to the chain RPC. Memoized, so
|
|
486
|
+
* repeated calls return the same instance (safe for wagmi).
|
|
487
|
+
*/
|
|
488
|
+
getEthereumProvider(opts?: {
|
|
489
|
+
chainId?: number;
|
|
490
|
+
}): Eip1193Provider;
|
|
491
|
+
/**
|
|
492
|
+
* Sign an EIP-7702 authorization, delegating this EOA to a smart-account
|
|
493
|
+
* implementation contract on `chainId`. Enables account-abstraction /
|
|
494
|
+
* sponsored-gas flows. Returns the full viem `SignedAuthorization` tuple, so
|
|
495
|
+
* it drops straight into a userOperation's `authorization` field or a type-4
|
|
496
|
+
* transaction's authorizationList. `address` and `contractAddress` are
|
|
497
|
+
* interchangeable (the latter matches Privy's/older viem's param name).
|
|
498
|
+
*/
|
|
499
|
+
signAuthorization(req: {
|
|
500
|
+
chainId: number;
|
|
501
|
+
address?: string;
|
|
502
|
+
contractAddress?: string;
|
|
503
|
+
nonce: number;
|
|
504
|
+
}): Promise<SignedAuthorization>;
|
|
505
|
+
/**
|
|
506
|
+
* The current session's access token (the Decane JWT). Use it to authenticate
|
|
507
|
+
* the user to your own backend (e.g. a sponsored-bundler proxy); verify it
|
|
508
|
+
* server-side against backend.decane.app/.well-known/jwks.json. Null with no
|
|
509
|
+
* live session.
|
|
510
|
+
*/
|
|
511
|
+
getAccessToken(): string | null;
|
|
449
512
|
signSolanaTransaction(tx: Uint8Array): Promise<Uint8Array>;
|
|
450
513
|
disconnect(): Promise<void>;
|
|
451
514
|
getAddresses(): {
|
|
@@ -866,6 +929,16 @@ declare function useSocialWallet(): {
|
|
|
866
929
|
chain: string;
|
|
867
930
|
balance: BalanceResult | null;
|
|
868
931
|
}[]>;
|
|
932
|
+
signAuthorization: (req: {
|
|
933
|
+
chainId: number;
|
|
934
|
+
address?: string;
|
|
935
|
+
contractAddress?: string;
|
|
936
|
+
nonce: number;
|
|
937
|
+
}) => Promise<SignedAuthorization>;
|
|
938
|
+
getEthereumProvider: (opts?: {
|
|
939
|
+
chainId?: number;
|
|
940
|
+
}) => Eip1193Provider;
|
|
941
|
+
getAccessToken: () => string | null;
|
|
869
942
|
rotateShares: (opts: {
|
|
870
943
|
password: string;
|
|
871
944
|
passwordHint?: string;
|
|
@@ -887,6 +960,9 @@ declare function useSocialBalance(chain?: string): {
|
|
|
887
960
|
error: string | null;
|
|
888
961
|
refetch: () => Promise<void>;
|
|
889
962
|
};
|
|
963
|
+
declare function useEthereumProvider(opts?: {
|
|
964
|
+
chainId?: number;
|
|
965
|
+
}): Eip1193Provider | null;
|
|
890
966
|
declare function useDecane(): {
|
|
891
967
|
provider: DecaneProvider;
|
|
892
968
|
wallets: UnifiedWalletAccount[];
|
|
@@ -959,4 +1035,4 @@ declare function useSignTypedData(): {
|
|
|
959
1035
|
reset: () => void;
|
|
960
1036
|
};
|
|
961
1037
|
|
|
962
|
-
export { type ActiveSession, AttestationError, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, CallSequenceError, type Chain, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type ConnectMode, type ConnectResult, type DecaneConfig, type DecaneConnect, type DecaneConnectConfig, DecaneConnectError, DecaneError, DecaneErrorCode, DecaneKit, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPinNotConfiguredError, ReconnectRequiredError, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SocialAuthState, type SocialConfig, SocialWalletModal, type Theme, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UserCancelledError, WalletSelector, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, createDecane, createDecaneConnect, startEmailAuth, useChainSwitch, useDecane, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, verifyEmailCode };
|
|
1038
|
+
export { type ActiveSession, AttestationError, type AuthResult, BUILT_IN_CHAINS, type BalanceResult, type CAIP25Method, type CAIP25SessionRequest, type CAIP25SessionResult, CHAINS, CallSequenceError, type Chain, type ChainDescriptor, type ChainId, type ChainScope, type ChainSupport, type ChainType, type ConnectMode, type ConnectResult, type DecaneConfig, type DecaneConnect, type DecaneConnectConfig, DecaneConnectError, DecaneError, DecaneErrorCode, DecaneKit, DecaneLogo, DecaneMark, type DecaneProvider, DecaneWordmark, type Eip1193Provider, type EthereumProviderOptions, ExportNotAuthorizedError, InvalidApiKeyError, InvalidPinError, InvalidRecoveryFileError, NetworkError, NewDeviceError, OriginNotAllowedError, type PortableBackup, PromptPinNotConfiguredError, ReconnectRequiredError, RecoveryFailedError, type RecoveryProgress, type RecoveryShareFile, RecoveryWalletMismatchError, type SdkEvent, type SendTransactionRequest, SessionExpiredError, ShareCorruptedError, type SignMessageRequest, type SignTypedDataRequest, type SignedAuthorization, type SocialAuthState, type SocialConfig, SocialWalletModal, type Theme, type TxParams, type UnifiedWalletAccount, UnlockRequiredError, UserCancelledError, WalletSelector, WebAuthnNotSupportedError, type WrappedShareMeta, WrongPasswordError, createDecane, createDecaneConnect, createEthereumProvider, startEmailAuth, useChainSwitch, useDecane, useEthereumProvider, useSendTransaction, useSignMessage, useSignTypedData, useSocialAuth, useSocialBalance, useSocialWallet, useWalletSelector, verifyEmailCode };
|
package/dist/index.js
CHANGED
|
@@ -2705,6 +2705,17 @@ async function signEvmTransaction(tee, chain, tx, jwt) {
|
|
|
2705
2705
|
async function signEvmMessage(tee, chain, message, jwt) {
|
|
2706
2706
|
return tee.sign({ chain, kind: "message", payload: message }, jwt);
|
|
2707
2707
|
}
|
|
2708
|
+
async function signEvmAuthorization(tee, chainId, address, nonce, jwt) {
|
|
2709
|
+
const serialized = await tee.sign(
|
|
2710
|
+
{ chain: `evm:${chainId}`, kind: "authorization", payload: JSON.stringify({ chainId, address, nonce }) },
|
|
2711
|
+
jwt
|
|
2712
|
+
);
|
|
2713
|
+
const hex = serialized.startsWith("0x") ? serialized.slice(2) : serialized;
|
|
2714
|
+
const r = "0x" + hex.slice(0, 64);
|
|
2715
|
+
const s = "0x" + hex.slice(64, 128);
|
|
2716
|
+
const v = parseInt(hex.slice(128, 130), 16);
|
|
2717
|
+
return { chainId, address, nonce, yParity: v >= 27 ? v - 27 : v, r, s };
|
|
2718
|
+
}
|
|
2708
2719
|
async function signEvmTypedData(tee, chain, typedData, jwt) {
|
|
2709
2720
|
const payload = JSON.stringify(
|
|
2710
2721
|
typedData,
|
|
@@ -2713,6 +2724,191 @@ async function signEvmTypedData(tee, chain, typedData, jwt) {
|
|
|
2713
2724
|
return tee.sign({ chain, kind: "typedData", payload }, jwt);
|
|
2714
2725
|
}
|
|
2715
2726
|
|
|
2727
|
+
// src/social/balance.ts
|
|
2728
|
+
var DEFAULT_RPCS = {
|
|
2729
|
+
"evm:1": "https://ethereum.publicnode.com",
|
|
2730
|
+
"evm:137": "https://polygon.publicnode.com",
|
|
2731
|
+
"evm:8453": "https://base.publicnode.com",
|
|
2732
|
+
"evm:10": "https://optimism.publicnode.com",
|
|
2733
|
+
"evm:42161": "https://arbitrum-one.publicnode.com",
|
|
2734
|
+
"evm:56": "https://bsc.publicnode.com",
|
|
2735
|
+
"evm:11155111": "https://ethereum-sepolia.publicnode.com",
|
|
2736
|
+
"evm:84532": "https://base-sepolia.publicnode.com",
|
|
2737
|
+
"evm:31337": "http://localhost:8545"
|
|
2738
|
+
};
|
|
2739
|
+
var EVM_SYMBOLS = {
|
|
2740
|
+
"evm:137": "MATIC",
|
|
2741
|
+
"evm:56": "BNB"
|
|
2742
|
+
};
|
|
2743
|
+
function solanaEndpoint(chain, rpcUrls) {
|
|
2744
|
+
if (rpcUrls?.[chain]) return rpcUrls[chain];
|
|
2745
|
+
const cluster = chain.slice("solana:".length);
|
|
2746
|
+
return cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com";
|
|
2747
|
+
}
|
|
2748
|
+
async function fetchBalance(opts) {
|
|
2749
|
+
const { kind, address, chain, rpcUrls } = opts;
|
|
2750
|
+
if (kind === "evm") {
|
|
2751
|
+
const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
|
|
2752
|
+
if (!rpcUrl) {
|
|
2753
|
+
throw new Error(
|
|
2754
|
+
`No RPC URL for ${chain}. Pass rpcUrls: { '${chain}': 'https://...' } in social config.`
|
|
2755
|
+
);
|
|
2756
|
+
}
|
|
2757
|
+
const { JsonRpcProvider, formatEther } = await import("ethers");
|
|
2758
|
+
const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
|
|
2759
|
+
return { raw: wei, formatted: formatEther(wei), symbol: EVM_SYMBOLS[chain] ?? "ETH", decimals: 18 };
|
|
2760
|
+
}
|
|
2761
|
+
const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
|
|
2762
|
+
const lamports = await new Connection(solanaEndpoint(chain, rpcUrls)).getBalance(
|
|
2763
|
+
new PublicKey(address)
|
|
2764
|
+
);
|
|
2765
|
+
return {
|
|
2766
|
+
raw: BigInt(lamports),
|
|
2767
|
+
formatted: String(lamports / LAMPORTS_PER_SOL),
|
|
2768
|
+
symbol: "SOL",
|
|
2769
|
+
decimals: 9
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
function formatBalanceDisplay(value) {
|
|
2773
|
+
if (value == null) return "\u2014";
|
|
2774
|
+
const n = Number(value);
|
|
2775
|
+
if (!Number.isFinite(n)) return value;
|
|
2776
|
+
return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
// src/social/eip1193.ts
|
|
2780
|
+
function toHex(n) {
|
|
2781
|
+
return "0x" + n.toString(16);
|
|
2782
|
+
}
|
|
2783
|
+
function hexToBytes2(hex) {
|
|
2784
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
2785
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
2786
|
+
for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(clean.substr(i * 2, 2), 16);
|
|
2787
|
+
return bytes;
|
|
2788
|
+
}
|
|
2789
|
+
function asBigInt(v) {
|
|
2790
|
+
if (v == null) return void 0;
|
|
2791
|
+
if (typeof v === "bigint") return v;
|
|
2792
|
+
if (typeof v === "number") return BigInt(v);
|
|
2793
|
+
if (typeof v === "string") return BigInt(v);
|
|
2794
|
+
return void 0;
|
|
2795
|
+
}
|
|
2796
|
+
function createEthereumProvider(client, opts = {}) {
|
|
2797
|
+
let chainId = opts.chainId ?? 1;
|
|
2798
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
2799
|
+
function emit(event, ...args) {
|
|
2800
|
+
listeners.get(event)?.forEach((h) => {
|
|
2801
|
+
try {
|
|
2802
|
+
h(...args);
|
|
2803
|
+
} catch {
|
|
2804
|
+
}
|
|
2805
|
+
});
|
|
2806
|
+
}
|
|
2807
|
+
client.on("connected", () => {
|
|
2808
|
+
const evm = client.getAddresses()?.evm;
|
|
2809
|
+
emit("connect", { chainId: toHex(chainId) });
|
|
2810
|
+
if (evm) emit("accountsChanged", [evm]);
|
|
2811
|
+
});
|
|
2812
|
+
client.on("disconnected", () => {
|
|
2813
|
+
emit("accountsChanged", []);
|
|
2814
|
+
emit("disconnect", { code: 4900, message: "Wallet disconnected" });
|
|
2815
|
+
});
|
|
2816
|
+
const chainStr = () => `evm:${chainId}`;
|
|
2817
|
+
async function rpc(method, params) {
|
|
2818
|
+
const url = opts.rpcUrls?.[`evm:${chainId}`] ?? DEFAULT_RPCS[`evm:${chainId}`];
|
|
2819
|
+
if (!url) {
|
|
2820
|
+
throw Object.assign(new Error(`No RPC for chain ${chainId}. Pass rpcUrls.`), { code: 4900 });
|
|
2821
|
+
}
|
|
2822
|
+
let res;
|
|
2823
|
+
try {
|
|
2824
|
+
res = await fetch(url, {
|
|
2825
|
+
method: "POST",
|
|
2826
|
+
headers: { "Content-Type": "application/json" },
|
|
2827
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: Date.now(), method, params })
|
|
2828
|
+
});
|
|
2829
|
+
} catch (e) {
|
|
2830
|
+
throw Object.assign(new Error(`RPC request failed: ${e.message}`), { code: 4900 });
|
|
2831
|
+
}
|
|
2832
|
+
const json = await res.json();
|
|
2833
|
+
if (json.error) throw Object.assign(new Error(json.error.message), { code: json.error.code });
|
|
2834
|
+
return json.result;
|
|
2835
|
+
}
|
|
2836
|
+
async function request(args) {
|
|
2837
|
+
const params = Array.isArray(args.params) ? args.params : args.params ? [args.params] : [];
|
|
2838
|
+
const addr = () => client.getAddresses()?.evm ?? null;
|
|
2839
|
+
switch (args.method) {
|
|
2840
|
+
case "eth_requestAccounts":
|
|
2841
|
+
case "eth_accounts": {
|
|
2842
|
+
const a = addr();
|
|
2843
|
+
return a ? [a] : [];
|
|
2844
|
+
}
|
|
2845
|
+
case "eth_chainId":
|
|
2846
|
+
return toHex(chainId);
|
|
2847
|
+
case "net_version":
|
|
2848
|
+
return String(chainId);
|
|
2849
|
+
case "personal_sign": {
|
|
2850
|
+
const message = params[0];
|
|
2851
|
+
const bytes = typeof message === "string" && message.startsWith("0x") ? hexToBytes2(message) : message;
|
|
2852
|
+
return client.signMessage({ chain: chainStr(), message: bytes });
|
|
2853
|
+
}
|
|
2854
|
+
case "eth_signTypedData_v4":
|
|
2855
|
+
case "eth_signTypedData": {
|
|
2856
|
+
const raw = params[1];
|
|
2857
|
+
const td = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
2858
|
+
return client.signTypedData({
|
|
2859
|
+
chain: chainStr(),
|
|
2860
|
+
domain: td.domain,
|
|
2861
|
+
types: td.types,
|
|
2862
|
+
message: td.message,
|
|
2863
|
+
primaryType: td.primaryType
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
case "eth_sendTransaction": {
|
|
2867
|
+
const tx = params[0];
|
|
2868
|
+
return client.sendTransaction({
|
|
2869
|
+
chain: chainStr(),
|
|
2870
|
+
to: tx.to,
|
|
2871
|
+
value: asBigInt(tx.value),
|
|
2872
|
+
data: tx.data ?? tx.input,
|
|
2873
|
+
gasLimit: asBigInt(tx.gas ?? tx.gasLimit)
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
case "eth_signAuthorization":
|
|
2877
|
+
case "wallet_sign7702Authorization": {
|
|
2878
|
+
const p = params[0];
|
|
2879
|
+
const cid = p.chainId != null ? Number(asBigInt(p.chainId)) : chainId;
|
|
2880
|
+
const address = p.address ?? p.contractAddress;
|
|
2881
|
+
const nonce = p.nonce != null ? Number(asBigInt(p.nonce)) : 0;
|
|
2882
|
+
return client.signAuthorization({ chainId: cid, address, nonce });
|
|
2883
|
+
}
|
|
2884
|
+
case "wallet_switchEthereumChain": {
|
|
2885
|
+
const p = params[0];
|
|
2886
|
+
chainId = Number(asBigInt(p.chainId));
|
|
2887
|
+
emit("chainChanged", toHex(chainId));
|
|
2888
|
+
return null;
|
|
2889
|
+
}
|
|
2890
|
+
case "wallet_addEthereumChain":
|
|
2891
|
+
return null;
|
|
2892
|
+
default:
|
|
2893
|
+
return rpc(args.method, params);
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
const provider = {
|
|
2897
|
+
request,
|
|
2898
|
+
on(event, handler) {
|
|
2899
|
+
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
2900
|
+
listeners.get(event).add(handler);
|
|
2901
|
+
return this;
|
|
2902
|
+
},
|
|
2903
|
+
removeListener(event, handler) {
|
|
2904
|
+
listeners.get(event)?.delete(handler);
|
|
2905
|
+
return this;
|
|
2906
|
+
},
|
|
2907
|
+
isDecane: true
|
|
2908
|
+
};
|
|
2909
|
+
return provider;
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2716
2912
|
// src/social/signers/solana.ts
|
|
2717
2913
|
import { VersionedTransaction as VTx } from "@solana/web3.js";
|
|
2718
2914
|
function b64(bytes) {
|
|
@@ -2950,58 +3146,6 @@ async function buildPortableBackup(deviceShare, recoveryShare, password, address
|
|
|
2950
3146
|
};
|
|
2951
3147
|
}
|
|
2952
3148
|
|
|
2953
|
-
// src/social/balance.ts
|
|
2954
|
-
var DEFAULT_RPCS = {
|
|
2955
|
-
"evm:1": "https://ethereum.publicnode.com",
|
|
2956
|
-
"evm:137": "https://polygon.publicnode.com",
|
|
2957
|
-
"evm:8453": "https://base.publicnode.com",
|
|
2958
|
-
"evm:10": "https://optimism.publicnode.com",
|
|
2959
|
-
"evm:42161": "https://arbitrum-one.publicnode.com",
|
|
2960
|
-
"evm:56": "https://bsc.publicnode.com",
|
|
2961
|
-
"evm:11155111": "https://ethereum-sepolia.publicnode.com",
|
|
2962
|
-
"evm:84532": "https://base-sepolia.publicnode.com",
|
|
2963
|
-
"evm:31337": "http://localhost:8545"
|
|
2964
|
-
};
|
|
2965
|
-
var EVM_SYMBOLS = {
|
|
2966
|
-
"evm:137": "MATIC",
|
|
2967
|
-
"evm:56": "BNB"
|
|
2968
|
-
};
|
|
2969
|
-
function solanaEndpoint(chain, rpcUrls) {
|
|
2970
|
-
if (rpcUrls?.[chain]) return rpcUrls[chain];
|
|
2971
|
-
const cluster = chain.slice("solana:".length);
|
|
2972
|
-
return cluster === "devnet" ? "https://api.devnet.solana.com" : "https://api.mainnet-beta.solana.com";
|
|
2973
|
-
}
|
|
2974
|
-
async function fetchBalance(opts) {
|
|
2975
|
-
const { kind, address, chain, rpcUrls } = opts;
|
|
2976
|
-
if (kind === "evm") {
|
|
2977
|
-
const rpcUrl = rpcUrls?.[chain] ?? DEFAULT_RPCS[chain];
|
|
2978
|
-
if (!rpcUrl) {
|
|
2979
|
-
throw new Error(
|
|
2980
|
-
`No RPC URL for ${chain}. Pass rpcUrls: { '${chain}': 'https://...' } in social config.`
|
|
2981
|
-
);
|
|
2982
|
-
}
|
|
2983
|
-
const { JsonRpcProvider, formatEther } = await import("ethers");
|
|
2984
|
-
const wei = await new JsonRpcProvider(rpcUrl).getBalance(address);
|
|
2985
|
-
return { raw: wei, formatted: formatEther(wei), symbol: EVM_SYMBOLS[chain] ?? "ETH", decimals: 18 };
|
|
2986
|
-
}
|
|
2987
|
-
const { Connection, PublicKey, LAMPORTS_PER_SOL } = await import("@solana/web3.js");
|
|
2988
|
-
const lamports = await new Connection(solanaEndpoint(chain, rpcUrls)).getBalance(
|
|
2989
|
-
new PublicKey(address)
|
|
2990
|
-
);
|
|
2991
|
-
return {
|
|
2992
|
-
raw: BigInt(lamports),
|
|
2993
|
-
formatted: String(lamports / LAMPORTS_PER_SOL),
|
|
2994
|
-
symbol: "SOL",
|
|
2995
|
-
decimals: 9
|
|
2996
|
-
};
|
|
2997
|
-
}
|
|
2998
|
-
function formatBalanceDisplay(value) {
|
|
2999
|
-
if (value == null) return "\u2014";
|
|
3000
|
-
const n = Number(value);
|
|
3001
|
-
if (!Number.isFinite(n)) return value;
|
|
3002
|
-
return n === 0 ? "0" : n < 1e-4 ? "<0.0001" : n.toFixed(4).replace(/\.?0+$/, "");
|
|
3003
|
-
}
|
|
3004
|
-
|
|
3005
3149
|
// src/social/client.ts
|
|
3006
3150
|
var DEFAULT_API_BASE = "https://backend.decane.app";
|
|
3007
3151
|
var DEFAULT_TEE_URL = "https://4405742df08d19abc549a05ade2a7154d98bd87f-8443.dstack-pha-prod9.phala.network";
|
|
@@ -3074,6 +3218,7 @@ async function createDecaneConnect(config) {
|
|
|
3074
3218
|
);
|
|
3075
3219
|
let auth = null;
|
|
3076
3220
|
let persisted = loadPersisted(PERSIST_KEY);
|
|
3221
|
+
let ethProvider = null;
|
|
3077
3222
|
const persistSession = config.persistSession !== false;
|
|
3078
3223
|
const SESSION_KEY = sessionPersistKey(config.apiKey);
|
|
3079
3224
|
function persistLiveSession() {
|
|
@@ -3220,7 +3365,7 @@ async function createDecaneConnect(config) {
|
|
|
3220
3365
|
let evmAddress;
|
|
3221
3366
|
let solanaAddress;
|
|
3222
3367
|
try {
|
|
3223
|
-
evmAddress = new Wallet(
|
|
3368
|
+
evmAddress = new Wallet(toHex2(master)).address;
|
|
3224
3369
|
solanaAddress = Keypair.fromSeed(master).publicKey.toBase58();
|
|
3225
3370
|
shareSet = await splitMaster(master, 1);
|
|
3226
3371
|
} finally {
|
|
@@ -3581,6 +3726,30 @@ async function createDecaneConnect(config) {
|
|
|
3581
3726
|
auth?.jwt
|
|
3582
3727
|
);
|
|
3583
3728
|
},
|
|
3729
|
+
async signAuthorization(req) {
|
|
3730
|
+
const tee = session.requireActive();
|
|
3731
|
+
const delegate = req.address ?? req.contractAddress;
|
|
3732
|
+
if (!delegate) throw new CallSequenceError("signAuthorization requires `address` (the delegate contract).");
|
|
3733
|
+
return signEvmAuthorization(tee, req.chainId, delegate, req.nonce, auth?.jwt);
|
|
3734
|
+
},
|
|
3735
|
+
// The current session's access token (the Decane JWT), for authenticating
|
|
3736
|
+
// the user to your own backend — e.g. a sponsored-bundler proxy. Verify it
|
|
3737
|
+
// server-side against https://backend.decane.app/.well-known/jwks.json.
|
|
3738
|
+
// Null when there is no live session.
|
|
3739
|
+
getAccessToken() {
|
|
3740
|
+
return auth?.jwt ?? null;
|
|
3741
|
+
},
|
|
3742
|
+
getEthereumProvider(opts) {
|
|
3743
|
+
if (!ethProvider) {
|
|
3744
|
+
const firstEvm = config.chains.find((c) => c.startsWith("evm:"));
|
|
3745
|
+
const defaultChainId = firstEvm ? parseInt(firstEvm.slice(4), 10) : 1;
|
|
3746
|
+
ethProvider = createEthereumProvider(client, {
|
|
3747
|
+
chainId: opts?.chainId ?? defaultChainId,
|
|
3748
|
+
rpcUrls: config.rpcUrls
|
|
3749
|
+
});
|
|
3750
|
+
}
|
|
3751
|
+
return ethProvider;
|
|
3752
|
+
},
|
|
3584
3753
|
async signSolanaTransaction(serializedTx) {
|
|
3585
3754
|
const tee = session.requireActive();
|
|
3586
3755
|
let tx;
|
|
@@ -3744,14 +3913,14 @@ function b64uToBuffer(b64u) {
|
|
|
3744
3913
|
const b644 = b64u.replace(/-/g, "+").replace(/_/g, "/");
|
|
3745
3914
|
return Uint8Array.from(atob(b644), (c) => c.charCodeAt(0));
|
|
3746
3915
|
}
|
|
3747
|
-
function
|
|
3916
|
+
function toHex2(bytes) {
|
|
3748
3917
|
return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3749
3918
|
}
|
|
3750
3919
|
async function deriveAddressesFromShares(a, b) {
|
|
3751
3920
|
const master = await combineShares(a, b);
|
|
3752
3921
|
try {
|
|
3753
3922
|
return {
|
|
3754
|
-
evm: new Wallet(
|
|
3923
|
+
evm: new Wallet(toHex2(master)).address,
|
|
3755
3924
|
solana: Keypair.fromSeed(master).publicKey.toBase58()
|
|
3756
3925
|
};
|
|
3757
3926
|
} finally {
|
|
@@ -5784,6 +5953,22 @@ function DecaneKit({ config, children }) {
|
|
|
5784
5953
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
5785
5954
|
return sdk.getBalance(chain);
|
|
5786
5955
|
}, []);
|
|
5956
|
+
const socialGetEthereumProvider = useCallback3((opts) => {
|
|
5957
|
+
const sdk = socialRef.current;
|
|
5958
|
+
if (!sdk) throw new Error("Social wallet not connected");
|
|
5959
|
+
return sdk.getEthereumProvider(opts);
|
|
5960
|
+
}, []);
|
|
5961
|
+
const socialSignAuthorization = useCallback3(
|
|
5962
|
+
async (req) => {
|
|
5963
|
+
const sdk = socialRef.current;
|
|
5964
|
+
if (!sdk) throw new Error("Social wallet not connected");
|
|
5965
|
+
return sdk.signAuthorization(req);
|
|
5966
|
+
},
|
|
5967
|
+
[]
|
|
5968
|
+
);
|
|
5969
|
+
const socialGetAccessToken = useCallback3(() => {
|
|
5970
|
+
return socialRef.current?.getAccessToken() ?? null;
|
|
5971
|
+
}, []);
|
|
5787
5972
|
const socialGetBalances = useCallback3(async () => {
|
|
5788
5973
|
const sdk = socialRef.current;
|
|
5789
5974
|
if (!sdk) throw new Error("Social wallet not connected");
|
|
@@ -5846,6 +6031,9 @@ function DecaneKit({ config, children }) {
|
|
|
5846
6031
|
socialSendTransaction,
|
|
5847
6032
|
socialGetBalance,
|
|
5848
6033
|
socialGetBalances,
|
|
6034
|
+
socialGetEthereumProvider,
|
|
6035
|
+
socialSignAuthorization,
|
|
6036
|
+
socialGetAccessToken,
|
|
5849
6037
|
socialSignSolanaTransaction,
|
|
5850
6038
|
socialSignTypedData,
|
|
5851
6039
|
socialRotateShares,
|
|
@@ -5918,7 +6106,7 @@ function useDecaneContext() {
|
|
|
5918
6106
|
}
|
|
5919
6107
|
|
|
5920
6108
|
// src/ui/hooks.ts
|
|
5921
|
-
import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4 } from "react";
|
|
6109
|
+
import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4, useMemo } from "react";
|
|
5922
6110
|
function useSocialAuth() {
|
|
5923
6111
|
const {
|
|
5924
6112
|
socialAuth,
|
|
@@ -6068,6 +6256,9 @@ function useSocialWallet() {
|
|
|
6068
6256
|
socialSignTypedData,
|
|
6069
6257
|
socialGetBalance,
|
|
6070
6258
|
socialGetBalances,
|
|
6259
|
+
socialGetEthereumProvider,
|
|
6260
|
+
socialSignAuthorization,
|
|
6261
|
+
socialGetAccessToken,
|
|
6071
6262
|
socialRotateShares,
|
|
6072
6263
|
socialExportPortableBackup,
|
|
6073
6264
|
socialHasRecoveryShare,
|
|
@@ -6112,6 +6303,10 @@ function useSocialWallet() {
|
|
|
6112
6303
|
(chain) => run(() => socialGetBalance(chain)),
|
|
6113
6304
|
[socialGetBalance]
|
|
6114
6305
|
);
|
|
6306
|
+
const signAuthorization = useCallback4(
|
|
6307
|
+
(req) => run(() => socialSignAuthorization(req)),
|
|
6308
|
+
[socialSignAuthorization]
|
|
6309
|
+
);
|
|
6115
6310
|
const getBalances = useCallback4(
|
|
6116
6311
|
() => run(() => socialGetBalances()),
|
|
6117
6312
|
[socialGetBalances]
|
|
@@ -6185,6 +6380,13 @@ function useSocialWallet() {
|
|
|
6185
6380
|
// Balances (native token; read-only, works while locked)
|
|
6186
6381
|
getBalance,
|
|
6187
6382
|
getBalances,
|
|
6383
|
+
// EVM interop
|
|
6384
|
+
signAuthorization,
|
|
6385
|
+
// An EIP-1193 provider for viem/wagmi/ethers (memoized).
|
|
6386
|
+
getEthereumProvider: socialGetEthereumProvider,
|
|
6387
|
+
// The Decane JWT — authenticate the user to your own backend (bundler proxy,
|
|
6388
|
+
// etc.); verify server-side against backend.decane.app/.well-known/jwks.json.
|
|
6389
|
+
getAccessToken: socialGetAccessToken,
|
|
6188
6390
|
// Recovery (2-of-3 Shamir share set)
|
|
6189
6391
|
rotateShares,
|
|
6190
6392
|
exportPortableBackup,
|
|
@@ -6242,6 +6444,18 @@ function useSocialBalance(chain) {
|
|
|
6242
6444
|
}, [addrKey, chain]);
|
|
6243
6445
|
return { balance, loading, error, refetch };
|
|
6244
6446
|
}
|
|
6447
|
+
function useEthereumProvider(opts) {
|
|
6448
|
+
const { socialAuth, socialGetEthereumProvider } = useDecaneContext();
|
|
6449
|
+
const chainId = opts?.chainId;
|
|
6450
|
+
return useMemo(() => {
|
|
6451
|
+
if (!socialAuth.addresses?.evm) return null;
|
|
6452
|
+
try {
|
|
6453
|
+
return socialGetEthereumProvider(chainId ? { chainId } : void 0);
|
|
6454
|
+
} catch {
|
|
6455
|
+
return null;
|
|
6456
|
+
}
|
|
6457
|
+
}, [socialAuth.addresses?.evm, chainId]);
|
|
6458
|
+
}
|
|
6245
6459
|
function toDecaneError(err) {
|
|
6246
6460
|
if (err instanceof DecaneError) return err;
|
|
6247
6461
|
const msg = err instanceof Error ? err.message : err?.message != null ? String(err.message) : String(err);
|
|
@@ -6498,9 +6712,11 @@ export {
|
|
|
6498
6712
|
WrongPasswordError,
|
|
6499
6713
|
createDecane,
|
|
6500
6714
|
createDecaneConnect,
|
|
6715
|
+
createEthereumProvider,
|
|
6501
6716
|
startEmailAuth,
|
|
6502
6717
|
useChainSwitch,
|
|
6503
6718
|
useDecane,
|
|
6719
|
+
useEthereumProvider,
|
|
6504
6720
|
useSendTransaction,
|
|
6505
6721
|
useSignMessage,
|
|
6506
6722
|
useSignTypedData,
|