# استدعِ Solana من EVM

يتيح لك الـ CPI precompile في Rome أن تستدعي عقود Solidity أي برنامج Solana مباشرةً. يشرح هذا الدليل الآلية.

## المتطلبات الأساسية

* تم تثبيت Rome Solidity SDK: `npm install @rome-protocol/solidity-sdk`
* عقد Rome مُنشر (انظر [نشر Solidity](/ar/adlh-almtwryn/deploy-solidity.md))

## الـ CPI Precompile

الـ CPI precompile عند `0xFF00000000000000000000000000000000000008` يوفّر وظيفتين:

```solidity
import {CpiProgram} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";

// استدعاء برنامج Solana
CpiProgram.invoke(programId, accounts, instructionData);

// الاستدعاء مع توقيع PDA (عقدك يوقّع بصفته PDA)
CpiProgram.invoke_signed(programId, accounts, data, seeds);
```

## مثال أساسي: تحويل SOL

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {SystemProgram, CpiProgram} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";
import {RomeEVMAccount} from "@rome-protocol/solidity-sdk/contracts/core/RomeEVMAccount.sol";

contract SolTransfer {
    function transferSol(bytes32 recipient, uint64 lamports) external {
        // الحصول على PDA للمرسِل
        bytes32 senderPda = RomeEVMAccount.pda(msg.sender);

        // بناء تعليمات التحويل لبرنامج النظام
        ICrossProgramInvocation.AccountMeta[] memory accounts = new ICrossProgramInvocation.AccountMeta[](2);
        accounts[0] = ICrossProgramInvocation.AccountMeta(senderPda, true, true);   // المرسِل (موقّع، قابل للكتابة)
        accounts[1] = ICrossProgramInvocation.AccountMeta(recipient, false, true);   // المستلم (قابل للكتابة)

        // تعليمات التحويل لبرنامج النظام (النوع 2، كمية u64 بترتيب little-endian)
        bytes memory data = abi.encodePacked(uint32(2), lamports);

        CpiProgram.invoke(SystemProgram.program_id(), accounts, data);
    }
}
```

## قراءة بيانات الحساب

يتيح لك الـ CPI precompile أيضًا قراءة بيانات أي حساب Solana:

```solidity
(
    uint64 lamports,
    bytes32 owner,
    bool isSigner,
    bool isWritable,
    bool executable,
    bytes memory data
) = CpiProgram.account_info(accountPubkey);
```

## العمل مع رموز SPL

استخدم الـ SPL Token precompile لعمليات الرموز الشائعة:

```solidity
import {SplToken, AssociatedSplToken} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";

contract TokenOperations {
    // قراءة رصيد حساب توكن
    function getBalance(bytes32 tokenAccount) external view returns (uint64) {
        ISplToken.Account memory acc = SplToken.account_state(tokenAccount);
        return acc.amount;
    }

    // تحويل رموز SPL
    function transferTokens(bytes32 recipientAta, bytes32 mint, uint256 amount) external {
        SplToken.transfer(recipientAta, mint, amount);
    }

    // إنشاء حساب توكن مرتبط
    function createAta(bytes32 wallet, bytes32 mint) external {
        AssociatedSplToken.create_associated_token_account(wallet, mint);
    }
}
```

## اشتقاق PDA

العثور على عناوين مشتقة من البرنامج من Solidity:

```solidity
import {SystemProgram} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";

// اشتقاق PDA
ISystemProgram.Seed[] memory seeds = new ISystemProgram.Seed[](2);
seeds[0] = ISystemProgram.Seed("my-program-seed");
seeds[1] = ISystemProgram.Seed(abi.encodePacked(someValue));

(bytes32 pda, uint8 bump) = SystemProgram.find_program_address(targetProgramId, seeds);
```

## التحويل إلى Base58

التحويل بين bytes32 وbase58 (صيغة عناوين Solana):

```solidity
// bytes32 → سلسلة base58
bytes memory base58Str = SystemProgram.bytes32_to_base58(pubkey);

// سلسلة base58 → bytes32
bytes32 pubkey = SystemProgram.base58_to_bytes32(base58Bytes);
```

## استدعاء برامج Solana المخصّصة

لاستدعاء أي برنامج Solana عشوائي:

```solidity
contract CustomCPI {
    bytes32 constant MY_PROGRAM = 0x...; // معرّف برنامج Solana الخاص بك

    function callMyProgram(bytes32 account1, bytes32 account2, bytes calldata ixData) external {
        ICrossProgramInvocation.AccountMeta[] memory accounts = new ICrossProgramInvocation.AccountMeta[](2);
        accounts[0] = ICrossProgramInvocation.AccountMeta(account1, false, true);
        accounts[1] = ICrossProgramInvocation.AccountMeta(account2, false, false);

        CpiProgram.invoke(MY_PROGRAM, accounts, ixData);
    }
}
```

## القيود الرئيسية

1. **يجب التصريح عن جميع الحسابات مسبقًا.** يجب أن تتضمن معاملة Solana كل حساب سيلامسه CPI. لا يمكن اكتشاف الحسابات ديناميكيًا داخل CPI.
2. **الحد الأقصى لعمق CPI: 4 مستويات.** Rome EVM → الهدف الخاص بك → استدعاء الهدف → مستوى آخر. خطّط لعمق الاستدعاء بعناية.
3. **مفاتيح Solana العامة هي bytes32.** جميع العناوين هي مفاتيح Solana عامة بطول 32 بايت، وليست عناوين Ethereum بطول 20 بايت.
4. **بيانات التعليمات هي bytes خام.** تحتاج إلى ترميز بيانات التعليمات بالصيغة التي يتوقعها البرنامج المستهدف (عادةً Borsh-encoded وبترتيب little-endian).

## ما التالي

* [تغليف الرموز](https://github.com/rome-protocol/docs/blob/main/developer-guides/token-wrapping.md) — نشر أغلفة ERC-20 لرموز SPL
* [بناء Transfer Hook](https://github.com/rome-protocol/docs/blob/main/developer-guides/build-transfer-hook.md) — إنشاء hooks نقل مدعومة بـ EVM
* [تحسين CU](https://github.com/rome-protocol/docs/blob/main/developer-guides/cu-optimization.md) — تقليل استهلاك وحدات الحوسبة لاستدعاءات CPI


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.rome.builders/ar/adlh-almtwryn/call-solana-from-evm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
