Inspiration
Solana can interface with the outside world through oracles, but building custom integrations is still a significant undertaking. If a developer wants their smart contract to call an API that isn't already served by an existing oracle, they have to build the entire pipeline themselves: an on-chain program, an off-chain listener, event decoding, transaction signing, and retry logic. We wanted to abstract that challenge away so that developers are now able to create integrations from their smart contract using a few lines from our SDK.
What it does
Damhchuire is a programmable oracle for Solana. Developers define actions, which are reusable templates for external API calls like weather lookups, crypto prices, LLM prompts, Slack messages, Discord webhooks, or anything with a REST endpoint, through a Rails dashboard or API. They then use our generated Rust SDK in their Anchor smart contracts to call those actions on-chain. The oracle listens for those on-chain events in real time, executes the HTTP request off-chain, validates the response against a JSON Schema, and writes the result back to the blockchain via a signed callback transaction. We already have working examples: a smart contract that asks for Dublin's temperature and gets back structured weather data from wttr.in, a contract that queries CoinGecko for live token prices, one that fetches a random quote from ZenQuotes, an AI chat action that sends a prompt to OpenRouter and gets an LLM response back on-chain, and a Discord connector for posting messages to webhooks.
How we built it
We split the work across four people building bottom-up from the chain outward. We started with the Solana program itself, an Anchor-based contract with initialize, on_call, and callback instructions that emit ActionRequested and ActionCompleted events. Next we scaffolded the Rails 8.1 API backend that would become the oracle's brain. From there we built a WebSocket event listener in Ruby that subscribes to Solana program logs via logsSubscribe, decodes Anchor events using discriminator-based Borsh deserialization, and routes them through a pub-sub event handler. We then built the Rails-Solana bridge, a Ruby service called DaTaskEmitter that constructs Solana transactions from scratch, handling Ed25519 signing, PDA derivation via SHA256, Borsh serialization of instruction data, and RPC submission with retry and backoff logic. In parallel we wrote a code generation script in Ruby that fetches the action catalog from the Rails API and produces typed Rust structs and an OracleClient with builder methods for each action. We wired the full end-to-end event loop so that when the listener catches an ActionRequested event, the handler triggers processing, the oracle executes the HTTP call to the external service, and a callback transaction carries the result back to the chain. On top of that we built a web dashboard with a quickstart guide, an actions management page, and a connector creation form with live preview. The largest piece was the action system itself: the Action and ActionInvocation models, a custom JSON Schema validator, the RestExecutor with template rendering for both URL parameters and credential injection, SSRF protection that blocks private IPs by default, retry logic for transient failures, and a full state machine tracking each invocation from received through running to succeeded or failed and finally callback_sent. We rounded it out with two example Anchor programs showing how to use the SDK, an SDK catalog endpoint, and an encrypted credential store built on Active Record Encryption with full test coverage.
Challenges we ran into
The biggest challenge was Borsh serialization in Ruby. Solana's binary format has no Ruby library, so we had to write a custom serializer and deserializer from scratch to encode instruction data and decode Anchor events, covering u64 and u32 little-endian encoding, length-prefixed strings, and byte arrays. WebSocket stability was another persistent issue: the Solana RPC node silently drops idle connections, and we went through multiple iterations to solve it, starting with JSON-RPC getHealth pings every 20 seconds, then switching to protocol-level WebSocket pings, and finally adding close-event reason capture for better diagnostics. We also had to solve event deduplication since the same event can arrive multiple times through WebSocket subscriptions, which we handled with an in-memory cache capped at 5,000 entries keyed on transaction signature and log index. PDA derivation from Ruby required reimplementing Solana's SHA256-based Program Derived Address algorithm with careful byte-level matching to produce the same addresses the Anchor program expects. Decoding Anchor events meant computing SHA256("event:EventName") discriminators and matching them against raw log data, and getting the encoding to align exactly across Rust and Ruby took several rounds of debugging.
Accomplishments that we're proud of
The accomplishment we're most proud of is the full end-to-end loop working: a Solana smart contract emits an event, our Ruby backend picks it up over WebSocket in real time, calls an external API, and writes the response back on-chain via a signed callback transaction. The entire cycle runs without manual intervention. With the generated SDK, a developer can call any external API from their smart contract in about five to six lines of Rust, with the SDK handling serialization, type safety, and request building. The SDK itself is auto-generated from the live action catalog in the Rails database, so types are always in sync. Change an action's schema, regenerate, and the Rust compiler catches any mismatches. Our encrypted credential store ensures API keys are encrypted at rest, never exposed through the API, and injected into templates only at execution time, making the system secure by default. We built production-grade reliability patterns throughout: exponential backoff retry on both HTTP calls and Solana transaction submission, JSON Schema validation on both request and response, a full audit trail of every invocation with a status state machine, and duplicate request prevention. All of this was done by four people across ten cleanly structured pull requests, with clear separation between the Solana layer, the event system, the action execution engine, and the credential store.
What we learned
We learned that Solana's runtime constraints are stricter than they first appear. Programs cannot make HTTP calls, cannot access external state, and have tight compute budgets, which forced us into a clean event-driven architecture where the chain only emits requests and receives callbacks. We proved that Ruby can talk to Solana even without an official SDK: transaction construction, Ed25519 signing, Borsh serialization, and RPC communication are all feasible to build from scratch. We discovered that template rendering needs guardrails. Allowing user-defined URL and header templates opens up SSRF risks, so we learned to block private IPs by default, validate schemas on both input and output, and keep credentials out of logs and API responses. We found that WebSocket connections to blockchain nodes are fragile; keepalive strategies, reconnection logic, and event deduplication are essential for reliability, and this is poorly documented in the Solana ecosystem. Finally, we learned that code generation bridges the trust gap between on-chain and off-chain systems. Auto-generating typed Rust code from the action catalog means the compiler enforces correctness at the boundary, which turned out to be more valuable than any amount of hand-written documentation.
What's next for Damhchuire
The infrastructure is built. The next step is to start building with it. We want to see smart contracts issuing virtual cards through payment APIs, pay-per-token models where Solana handles micropayments and our oracle triggers the service, and native integrations that let any web service become accessible from the chain. The action template system is generic enough that any REST API is a potential connector, and we want to push that as far as it goes. On the product side, the focus is on making Damhchuire nicer to use: improving the developer experience, polishing the dashboard, expanding the pre-built action library, and deploying to Solana devnet and mainnet so developers can start shipping real applications on top of it.
Built With
- anchor
- borsh
- css
- docker
- erb
- kamal
- puma
- rpc
- ruby-on-rails
- rubygems
- rust
- solana
- sqlite
- typescript
- web3
- websockets
Log in or sign up for Devpost to join the conversation.