Phantom Connect SDK

repository·main·Indexed 41 days ago

https://github.com/phantom/phantom-connect-sdk

A suite of SDKs for React, React Native, Browser, and Server designed to integrate Phantom's wallet capabilities, including embedded wallets and extension support. It provides dual provider support (Injected and Embedded) and tools for managing organizations, authenticators (keypair, OIDC), and multi-chain wallets across Solana, Ethereum, Bitcoin, and Sui.

Tokens
133K
Snippets
428
Records
556
Agent score
47%

What's inside Phantom Connect SDK

  1. Handle Auto-Connect and Session Management

    main

    The SDK can automatically reconnect to existing sessions to provide a seamless experience. This is controlled by the autoConnect option.

    • autoConnect: true (Default for embedded): The SDK checks for a valid session immediately upon instantiation. If a session exists, it connects in the background.
    • autoConnect: false: You must manually call sdk.connect() every time the user needs to authenticate.

    Pattern for checking connection: Always check sdk.isConnected() (or sdk.solana.isConnected / sdk.ethereum.isConnected()) before attempting to use the SDK to determine if a manual connect() call is required.

    const sdk = new BrowserSDK({
      providers: ["google", "apple"],
      appId: "your-app-id",
      addressTypes: [AddressType.solana],
      autoConnect: true,
    });
    
    if (sdk.isConnected()) {
      // Use existing session
      const addresses = await sdk.getAddresses();
    } else {
      // Trigger manual connection
      await sdk.connect({ provider: "google" });
    }
  2. Implement Dapp-Sponsored Transactions with presignTransaction

    main

    For use cases requiring a second signer (e.g., your backend acting as a fee payer), use the presignTransaction option within signAndSendTransaction.

    Important Constraints:

    • Phantom embedded wallets do not accept pre-signed transactions. You must use this option to allow Phantom to construct/validate the transaction before your backend co-signs it.
    • This restriction does not apply to injected providers (like the Phantom browser extension).
    • presignTransaction only applies to Solana transactions via the embedded provider. EVM and injected providers are unaffected.
    • Security: Never hold a fee payer keypair in frontend code. The callback should call your backend to perform the partial signing.
    import { useSolana, base64urlDecode, base64urlEncode } from "@phantom/react-sdk";
    import { VersionedTransaction } from "@solana/web3.js";
    
    function SendWithFeeSponsor() {
      const { solana } = useSolana();
    
      const sendSponsored = async () => {
        const result = await solana.signAndSendTransaction(transaction, {
          presignTransaction: async (tx, context) => {
            // Send the transaction to your backend for fee payer signing.
            const response = await fetch("/api/presign", {
              method: "POST",
              body: JSON.stringify({ transaction: tx, networkId: context.networkId }),
              headers: { "Content-Type": "application/json" },
            });
            const { transaction: signedTx } = await response.json();
            return signedTx; // base64url-encoded, partially signed by the fee payer
          },
        });
      };
    }
  3. Supported transaction input formats

    main

    The parser automatically detects the following input formats for conversion:

    Message Formats:

    • String: Plain text messages (UTF-8).
    • Uint8Array/Buffer: Raw byte data.
    • Base64/Base64url: Already encoded data (will be re-encoded to base64url).

    Transaction Formats:

    • @solana/web3.js: Transaction objects (calls .serialize()).
    • @solana/kit: Solana Kit transaction objects.
    • Viem: Ethereum transaction objects with standard fields.
    • Ethers: Ethereum transaction objects (legacy and modern).
    • Raw bytes: Uint8Array or Buffer containing transaction data.
    • Hex strings: "0x"-prefixed hex-encoded data.
    • Base64/Base64url: Already encoded transaction data.
  4. Security features of IndexedDbStamper

    main

    @phantom/indexed-db-stamper is designed for maximum security in browser environments using the following mechanisms:

    • Non-Extractable Keys: Uses Ed25519 keys with extractable: false. Private keys never exist in JavaScript memory and cannot be exported or accessed outside of the Web Crypto API signing operations.
    • Cryptographic Isolation: Keys are generated and stored within the browser's secure cryptographic context. Signing operations occur within Web Crypto API secure boundaries, utilizing hardware-backed isolation when available.
    • Signature Format: Uses Ed25519 raw signatures (64-byte format) for efficiency.
    • Origin Isolation: Leverages IndexedDB's origin-based security isolation.
  5. Implement a custom stamper for authentication

    main

    If you need custom authentication logic, you can implement the stamper interface by creating a class with an async stamp method. The stamp method receives an AxiosRequestConfig and should return the modified config (e.g., after adding custom headers).

    class CustomStamper {
      async stamp(config: AxiosRequestConfig): Promise<AxiosRequestConfig> {
        // Add your custom authentication logic here
        config.headers = config.headers || {};
        return config;
      }
    }
    
    const client = new PhantomClient(config, new CustomStamper());
  6. How EVM transaction signing works in Connect SDK

    main

    The Connect SDK signing APIs automatically bind every EVM transaction to its selected network before the transaction is sent to the signing service.

    To ensure security and prevent replay attacks, the SDK follows these rules:

    1. Chain ID Derivation: The SDK derives the expected chainId from a supported eip155 networkId.
    2. Automatic Filling: For structured legacy and typed transactions, if the chainId is omitted or set to zero, the SDK replaces it with the expected value derived from the selected network.
    3. Validation: If you provide a non-zero chainId, it must be valid, supported, and exactly match the selected network.
    4. Raw Transactions: Raw hex and byte inputs are decoded as unsigned EVM transactions and subjected to the same validation rules.

    Rejection Criteria: Transactions will be rejected before signing if they contain:

    • Malformed encodings
    • Already-signed transactions
    • Unsupported chain IDs
    • Network mismatches

    Chain ID Formats: Chain IDs must be provided as either a decimal string (e.g., "137") or a hexadecimal string (e.g., "0x89"). Other string formats are considered invalid.

  7. Manage Hyperliquid account transfers

    main

    The MCP server provides tools to move USDC between different Hyperliquid account types and external chains:

    • perps_transfer: Moves USDC from the Hyperliquid spot account to the perpetuals account. Use this if you already have USDC on Hyperliquid spot.
    • perps_withdraw: Moves USDC from the perpetuals account back to the Hyperliquid spot wallet. Check perps_account for your withdrawable balance first.
    • perps_withdraw-hl-spot: Withdraws USDC from the Hyperliquid spot account to an external destination chain (e.g., back to Solana or an EVM chain) using a destinationChainId (CAIP-2).
  8. Understand Dual Provider Support in Phantom React SDK

    main

    The @phantom/react-sdk supports two distinct provider models, allowing developers to choose between browser extension interaction and server-based wallet management.

    1. Injected Provider

    • Mechanism: Connects directly to the Phantom browser extension.
    • Use Case: Standard web3 applications where users interact via their installed wallet.
    • Network Support: Currently supports Solana network operations.

    2. Embedded Provider

    • Mechanism: Server-based wallet management.
    • Wallet Types:
      • User Wallet: Uses Google authentication to connect to an existing user identity.
      • App Wallet: Creates a fresh, new wallet for the application.
    • Network Support: Supports multiple networks including Solana, Ethereum, and other chains.
    • Requirement: Requires a backend server (e.g., at http://localhost:3000/api) to handle wallet management.
  9. Handle 402 Payment Required errors

    main

    When the API returns a 402 status, the client throws a PaymentRequiredError. You have two ways to handle this:

    Option A: Manual Handling

    Catch the error and inspect the payment object to get details like network, token, amount, preparedTx, and description.

    Option B: Automatic Payment Handling

    Provide a handler via setPaymentHandler(). When a 402 occurs, the client will execute this handler, and if it returns a signature, the client will automatically retry the original request. The signature is stored via setPaymentSignature() and sent as the X-Payment header on all subsequent requests.

    import { PaymentRequiredError } from "@phantom/phantom-api-client";
    
    // Option A — manual catch
    try {
      const data = await client.get("/swap/v2/quotes");
    } catch (err) {
      if (err instanceof PaymentRequiredError) {
        console.log(err.payment); // { network, token, amount, preparedTx, description }
      }
    }
    
    // Option B — automatic handler
    client.setPaymentHandler(async payment => {
      // Sign and broadcast the prepared transaction, return the signature
      const signature = await wallet.signAndSend(payment.preparedTx);
      return signature;
    });
    
    // Requests now auto-pay on 402 and retry transparently
    const data = await client.get("/swap/v2/quotes");
  10. Understand the Base64url format

    main

    The library implements the Base64url format as defined in RFC 4648. This variant is specifically designed to be safe for use in URLs, filenames, and HTTP headers by making the following adjustments to standard Base64:

    • Uses - (hyphen) instead of + (plus).
    • Uses _ (underscore) instead of / (slash).
    • Removes all padding (=) characters.
  11. Implement Dapp-Sponsored Transactions (Solana)

    main

    If your application needs to act as a fee payer (co-signing), use the presignTransaction option within signAndSendTransaction.

    Important Constraints:

    • This feature is only available for Solana transactions via the embedded provider.
    • EVM transactions are unaffected.
    • Phantom embedded wallets do not accept pre-signed transactions. The presignTransaction callback must be used so that Phantom can construct and validate the transaction before your app applies the second signature.

    Workflow:

    1. Phantom constructs/validates the transaction.
    2. The presignTransaction callback is triggered.
    3. Your app deserializes the transaction, adds its signature, and returns the serialized bytes.
    import { useSolana, base64urlDecode, base64urlEncode } from "@phantom/react-native-sdk";
    import { Keypair, VersionedTransaction } from "@solana/web3.js";
    
    const feePayerKeypair = Keypair.fromSecretKey(new Uint8Array([...]));
    
    function SendWithFeeSponsor() {
      const { solana } = useSolana();
    
      const sendSponsored = async () => {
        const result = await solana.signAndSendTransaction(transaction, {
          presignTransaction: async (tx, context) => {
            // 1. Decode the transaction bytes
            const txBytes = base64urlDecode(tx);
            const versionedTx = VersionedTransaction.deserialize(txBytes);
            
            // 2. Add the fee payer signature
            versionedTx.sign([feePayerKeypair]);
            
            // 3. Return the re-serialized transaction
            return base64urlEncode(versionedTx.serialize());
          },
        });
      };
    }
  12. Authenticate with @phantom/mcp-server

    main

    On first use, the server will prompt you to authenticate with your Phantom wallet via a browser. Sessions are persisted locally and refreshed automatically.

    Authentication Tools:

    • phantom_login: Authenticate with Phantom. Use this to log in for the first time, switch accounts, or refresh an expired session.
    • phantom_logout: Clear the stored session and credentials from disk. The next tool call will require re-authentication.