Bridging Stellar and Ethereum: Lessons from a Blockchain Abstraction Layer
RAHAT settles across both Stellar and Ethereum, and honestly the reason is simple: they're good at different things. Stellar gives us fast, cheap settlement, which matters a lot when you're processing high volumes of small value humanitarian transfers and every fee adds up. Ethereum and other EVM chains give us programmability and the tooling ecosystem that some partner integrations already expect. Neither one was going to cover every case by itself.
The trap of building two integrations that pretend to be one
The naive version of "support two chains" is an if (chain === 'stellar') scattered through the payout code. That works fine for a demo and turns into a mess within a quarter. Every new feature needs implementing twice, every bug needs fixing twice, and the actual business logic, who gets paid, how much, under what conditions, gets tangled up with chain specific plumbing like Stellar's operation objects versus Ethereum's transaction and gas model.
The fix was to stop treating "which chain" as a branch inside application code and start treating it as an implementation detail behind a single interface: submit a payment, check a balance, provision a wallet. Everything above that interface, the saga orchestration, the beneficiary logic, the audit trail, doesn't need to know or care which chain it's actually talking to.
interface ChainAdapter { provisionWallet(beneficiaryId: string): Promise<WalletHandle>; submitPayment(from: WalletHandle, to: WalletHandle, amount: Amount): Promise<TxReceipt>; getBalance(wallet: WalletHandle): Promise<Amount>; }
Stellar and Ethereum each get their own adapter implementing that interface, and all the chain specific detail, sequence numbers and trustlines on one side, gas estimation and nonce management on the other, lives entirely inside the adapter instead of leaking out.
Sponsored wallets were the part the docs didn't really prepare me for
Beneficiaries shouldn't need to hold native tokens just to pay transaction fees for receiving aid. That's a real onboarding barrier when the whole point is getting cash to someone quickly. Both chains support some version of fee sponsorship, Stellar has fee bump transactions and the EVM side has relayer and paymaster patterns, but they work differently enough that "sponsored wallet" had to become its own concept inside the abstraction layer rather than something each adapter quietly figured out on its own. Getting this consistent across both chains ended up being most of the actual engineering effort. The happy path payment call was the easy part.
What I'd tell someone starting this from scratch
Design the interface around your own domain, not around either chain's SDK. If your interface has a Stellar shaped method and an Ethereum shaped method, you haven't really abstracted anything yet. Decide early what "confirmed" means per chain, since finality looks nothing alike between Stellar and an EVM chain waiting on block confirmations, and your orchestration layer needs one consistent notion of "this payment is done." And treat sponsored or fee abstracted flows as a first class feature from day one if your users shouldn't need to understand gas just to receive money.
The payoff is that adding a third chain later, if we ever need to, becomes an adapter to write instead of a rewrite to plan for.