> ## Documentation Index
> Fetch the complete documentation index at: https://kamino.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Referral Code Setup

> Set up referrer state with a unique referral code

## How Referral Codes Work

Kamino's referral system allows referrers to earn commission from the borrowing activity of referred users. Each referrer creates a unique referral code that can be shared publicly without revealing a wallet address, providing a user-friendly way to distribute referral codes.
<Note>In the SDK, the `shortUrl` field represents the referral code.</Note>

<Tabs>
  <Tab title="TypeScript">
    <Steps>
      <Step>
        ### Import Dependencies

        Import the required packages for Solana RPC communication, Kamino SDK operations, and Kit transaction building.

        ```typescript theme={null}
        import {
          createSolanaRpc,
          createSolanaRpcSubscriptions,
          address,
          pipe,
          createTransactionMessage,
          setTransactionMessageFeePayerSigner,
          setTransactionMessageLifetimeUsingBlockhash,
          appendTransactionMessageInstructions,
          signTransactionMessageWithSigners,
          sendAndConfirmTransactionFactory,
          getSignatureFromTransaction,
        } from '@solana/kit';
        import {
          getInitReferrerStateAndShortUrlIxs,
          getReferrerForShortUrl,
          PROGRAM_ID,
        } from '@kamino-finance/klend-sdk';
        import { parseKeypairFile } from '@kamino-finance/klend-sdk/dist/utils/signer.js';
        ```
      </Step>

      <Step>
        ### Initialize RPC

        Load the keypair and initialize RPC connections.

        ```typescript theme={null}
        const KEYPAIR_FILE = '/path/to/your/keypair.json';
        const signer = await parseKeypairFile(KEYPAIR_FILE);

        const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
        const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');
        ```
      </Step>

      <Step>
        ### Create Referrer State with Short URL

        Generate a unique short URL and create the referrer state initialization instruction.

        ```typescript theme={null}
        const shortUrl = `ref-${Date.now()}`;

        const initReferrerIx = await getInitReferrerStateAndShortUrlIxs({
          referrer: signer,
          shortUrl,
          programId: PROGRAM_ID,
        });
        ```

        <Note>
          The short URL must be unique, contain a maximum of 32 characters, and use only ASCII alphanumeric characters plus underscore and hyphen.
        </Note>
      </Step>

      <Step>
        ### Send Referrer Setup Transaction

        Build and send the transaction to initialize the referrer state on-chain.

        ```typescript theme={null}
        const { value: setupBlockhash } = await rpc
          .getLatestBlockhash({ commitment: 'finalized' })
          .send();

        const setupTx = pipe(
          createTransactionMessage({ version: 0 }),
          (tx) => setTransactionMessageFeePayerSigner(signer, tx),
          (tx) => setTransactionMessageLifetimeUsingBlockhash(setupBlockhash, tx),
          (tx) => appendTransactionMessageInstructions([initReferrerIx], tx)
        );

        const setupSigned = await signTransactionMessageWithSigners(setupTx);
        const setupSignature = getSignatureFromTransaction(setupSigned);

        await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(setupSigned, {
          commitment: 'confirmed',
          skipPreflight: true,
        });

        console.log(`Referrer setup successful! Signature: ${setupSignature}`);
        ```
      </Step>

      <Step>
        ### Verify Short URL Resolution

        Confirm that the short URL correctly resolves to the referrer wallet address.

        ```typescript theme={null}
        const lookedUpReferrer = await getReferrerForShortUrl(rpc, shortUrl, PROGRAM_ID);

        console.log(`Short URL "${shortUrl}" resolves to: ${lookedUpReferrer}`);
        ```

        <Check>
          Referrer setup complete. The short URL is active and can be shared with users to establish referral relationships.
        </Check>
      </Step>
    </Steps>
  </Tab>

  <Tab title="Rust">
    <Info>
      `klend-interface` is a lightweight Rust instruction builder — it creates `Vec<Instruction>` with required refresh instructions prepended automatically. Use `ReserveInfo::from_account_data(pubkey, &data)` to construct reserve info from raw RPC account bytes. For obligation-based operations, `ObligationContext` is the recommended approach — it fetches the obligation and its associated reserves, then provides convenient `.deposit()`, `.borrow()`, `.repay()`, and `.withdraw()` methods.
    </Info>

    <Steps>
      <Step>
        ### Add Dependencies

        ```toml theme={null}
        [dependencies]
        klend-interface = "0.1.0"
        solana-pubkey = "2.1"
        solana-instruction = "2.1"
        solana-sdk = "~2.3"
        solana-client = "~2.3"
        spl-token = "7"
        spl-associated-token-account = "6"
        ```
      </Step>

      <Step>
        ### Set Up RPC Client

        ```rust theme={null}
        use solana_client::rpc_client::RpcClient;
        use solana_sdk::signer::keypair::read_keypair_file;
        use solana_sdk::signer::Signer;

        let rpc_client = RpcClient::new("https://api.mainnet-beta.solana.com");
        let signer = read_keypair_file("/path/to/your/keypair.json")
            .expect("Failed to read keypair file");
        let owner = signer.pubkey();
        ```
      </Step>

      <Step>
        ### Derive PDAs and Build Instruction

        ```rust theme={null}
        use klend_interface::instructions::referrer::{
            init_referrer_state_and_short_url,
            InitReferrerStateAndShortUrlAccounts,
        };
        use klend_interface::pda;
        use klend_interface::KLEND_PROGRAM_ID;
        use solana_pubkey::Pubkey;

        let referrer = signer.pubkey();
        let short_url = format!("ref-{}", std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH).unwrap().as_secs());

        // Derive required PDAs
        let (referrer_state, _) = pda::referrer_state(&KLEND_PROGRAM_ID, &referrer);
        let (referrer_short_url, _) = pda::referrer_short_url(&KLEND_PROGRAM_ID, &short_url);
        let (referrer_user_metadata, _) = pda::user_metadata(&KLEND_PROGRAM_ID, &referrer);

        let ix = init_referrer_state_and_short_url(
            InitReferrerStateAndShortUrlAccounts {
                referrer,
                referrer_state,
                referrer_short_url,
                referrer_user_metadata,
            },
            short_url.clone(),
        );
        ```

        <Note>
          The short URL must be unique, contain a maximum of 32 characters, and use only ASCII alphanumeric characters plus underscore and hyphen.
        </Note>
      </Step>

      <Step>
        ### Send Transaction

        ```rust theme={null}
        use solana_sdk::transaction::Transaction;
        use solana_sdk::message::Message;

        let message = Message::new(&[ix], Some(&referrer));
        let recent_blockhash = rpc_client.get_latest_blockhash()?;
        let tx = Transaction::new(&[&signer], message, recent_blockhash);
        let signature = rpc_client.send_and_confirm_transaction(&tx)?;
        println!("Referrer setup successful! Short URL: {short_url}");
        println!("Signature: {signature}");
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>
