Class: Solrengine::Sdp::Faucet

Inherits:
Object
  • Object
show all
Defined in:
lib/solrengine/sdp/faucet.rb

Overview

DEVNET-ONLY faucet client: POSTs JSON-RPC requestAirdrop straight to a Solana devnet RPC for a wallet’s public key. Mainnet has no faucet —pointing this at a mainnet RPC just yields Unavailable errors. Picking a devnet/localnet RPC URL is the caller’s responsibility (the default is the public devnet endpoint).

One attempt, NEVER retried — an airdrop that timed out may still land, and retrying just burns the per-address faucet allowance. Callers decide what to do on failure (e.g. fall back to a treasury transfer).

Defined Under Namespace

Classes: Error, RateLimited, TimedOut, Unavailable

Constant Summary collapse

DEFAULT_RPC_URL =
"https://api.devnet.solana.com"
OPEN_TIMEOUT =

seconds — fail fast, funding flows are user-facing

2
READ_TIMEOUT =

seconds

5
RATE_LIMIT_PATTERN =

The faucet reports rate limiting either as HTTP 429 or as a JSON-RPC error whose message mentions the airdrop/rate limit.

/rate.?limit|too many requests|airdrop limit|limit reached|429/i

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rpc_url: ENV.fetch("SOLANA_RPC_URL", DEFAULT_RPC_URL), open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT) ⇒ Faucet

Returns a new instance of Faucet.



45
46
47
48
49
50
51
# File 'lib/solrengine/sdp/faucet.rb', line 45

def initialize(rpc_url: ENV.fetch("SOLANA_RPC_URL", DEFAULT_RPC_URL),
               open_timeout: OPEN_TIMEOUT,
               read_timeout: READ_TIMEOUT)
  @rpc_url = rpc_url
  @open_timeout = open_timeout
  @read_timeout = read_timeout
end

Instance Attribute Details

#rpc_urlObject (readonly)

Returns the value of attribute rpc_url.



43
44
45
# File 'lib/solrengine/sdp/faucet.rb', line 43

def rpc_url
  @rpc_url
end

Instance Method Details

#request_airdrop(address, lamports) ⇒ Object

Requests ‘lamports` for `address`. Returns the airdrop transaction signature on success; raises RateLimited, TimedOut, or Unavailable otherwise.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/solrengine/sdp/faucet.rb', line 56

def request_airdrop(address, lamports)
  uri = URI.parse(@rpc_url)
  request = Net::HTTP::Post.new(uri)
  request["Content-Type"] = "application/json"
  request.body = JSON.generate(
    jsonrpc: "2.0", id: 1, method: "requestAirdrop", params: [ address, lamports ]
  )

  response = Net::HTTP.start(
    uri.host, uri.port,
    use_ssl: uri.scheme == "https",
    open_timeout: @open_timeout,
    read_timeout: @read_timeout
  ) { |http| http.request(request) }

  handle(response)
rescue Net::OpenTimeout => e
  # Connection never opened — the airdrop request was definitely not
  # sent. Unavailable (not TimedOut) so a funding fallback may run
  # without any double-funding risk.
  raise Unavailable, "Faucet unreachable (connect timeout): #{e.message}"
rescue Net::ReadTimeout => e
  raise TimedOut, "Faucet timed out: #{e.message}"
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH, SocketError, EOFError => e
  raise Unavailable, "Faucet unreachable: #{e.message}"
end