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

# 4. Onchain Integration

> Update your offchain code to submit attestations to your contract

After deploying your contract and adding it to the dashboard, update your offchain integration to target your contract address and pass attestations onchain.

<Steps>
  <Step title="Update API requests">
    Replace `verification_hash` with `to` (your contract address).
  </Step>

  <Step title="Pass attestations to your contract">
    Include the attestation struct when calling predicated functions.
  </Step>
</Steps>

***

<Tabs>
  <Tab title="EVM">
    ## Backend Changes

    Replace `verification_hash` with your contract address in the `to` field.

    ```typescript theme={null}
    app.post('/api/predicate/attestation', async (req, res) => {
      const { userAddress, contractAddress } = req.body;

      const response = await fetch('https://api.predicate.io/v2/attestation', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': process.env.PREDICATE_API_KEY,
        },
        body: JSON.stringify({
          to: contractAddress,
          from: userAddress,
          chain: 'base',
        }),
      });

      const result = await response.json();

      if (!result.is_compliant) {
        return res.status(403).json({ error: 'Not compliant' });
      }

      res.json({ attestation: result.attestation });
    });
    ```

    ### Request Parameters

    | Field   | Description                                       |
    | ------- | ------------------------------------------------- |
    | `to`    | Your deployed contract address                    |
    | `from`  | The user's wallet address                         |
    | `chain` | Chain name (e.g., `base`, `ethereum`, `arbitrum`) |

    ***

    ## Frontend Changes

    Fetch the attestation and pass it to your contract function.

    ```typescript theme={null}
    // 1) Fetch attestation from your backend
    const { attestation } = await fetch('/api/predicate/attestation', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        userAddress: account,
        contractAddress: VAULT_ADDRESS,
      }),
    }).then(r => r.json());

    // 2) Call your contract with the attestation
    const tx = await vault.deposit(
      {
        uuid: attestation.uuid,
        expiration: attestation.expiration,
        attester: attestation.attester,
        signature: attestation.signature,
      },
      { value: depositAmount }
    );
    ```

    ### Attestation Struct

    | Field        | Type      | Description                                   |
    | ------------ | --------- | --------------------------------------------- |
    | `uuid`       | `bytes16` | Unique identifier for replay protection       |
    | `expiration` | `uint256` | Unix timestamp when the attestation expires   |
    | `attester`   | `address` | Address of the Predicate attester that signed |
    | `signature`  | `bytes`   | ECDSA signature over the attestation          |
  </Tab>

  <Tab title="SVM">
    ## Backend Changes

    Update your API calls to target your program address.

    ```typescript theme={null}
    app.post('/api/predicate/attestation', async (req, res) => {
      const { userPubkey, programId, data } = req.body;

      const response = await fetch('https://api.predicate.io/v2/attestation', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': process.env.PREDICATE_API_KEY,
        },
        body: JSON.stringify({
          to: programId,
          from: userPubkey,
          data,
          msg_value: '0',
          chain: 'solana',
        }),
      });

      const result = await response.json();

      if (!result.is_compliant) {
        return res.status(403).json({ error: 'Not compliant' });
      }

      res.json({ attestation: result.attestation });
    });
    ```

    ***

    ## Frontend Changes

    Include an Ed25519 verification instruction before your program instruction, then call your method.

    ```typescript theme={null}
    const { attestation } = await fetch('/api/predicate/attestation', { /* ... */ })
      .then(r => r.json());

    // 1) Verify Ed25519 signature (must precede your program instruction)
    const ed25519Instruction = Ed25519Program.createInstructionWithPublicKey({
      publicKey: attesterPubkey.toBytes(),
      message: messageHash,
      signature: signatureBytes,
    });

    // 2) Create your program instruction
    const clientInstruction = await program.methods
      .yourMethod(attestation)
      .accounts({
        // ... your accounts
        predicateRegistry: registryPda,
        attesterAccount: attesterPda,
        policyAccount: policyPda,
        usedUuidAccount: usedUuidPda,
        instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
      })
      .instruction();

    // 3) Build and send (Ed25519 instruction MUST come first)
    const transaction = new Transaction();
    transaction.add(ed25519Instruction);
    transaction.add(clientInstruction);
    await provider.sendAndConfirm(transaction, [userKeypair]);
    ```
  </Tab>
</Tabs>
