Skip to main content
@opaquecash/relayer-client submits a permissionless on-chain call (a PSR verifyReputation, a future pool withdrawal) through the relayer market so the submitting wallet is a staked relayer’s, not yours. See relayer-market.md for the protocol.

How it works

  1. You commit to a hidden payload and fund an escrow with the fee (createJob).
  2. You advertise the job to a relayer node’s HTTP gateway; nodes bid.
  3. You verify bids (signature, registered key, free stake) and pick a stake-weighted winner.
  4. You seal the payload to the winner’s x25519 key (NaCl crypto_box) and deliver it.
  5. The relayer accepts (bonding the fee) and submits. The escrow verifies the payload against the commitment and pays atomically with execution, so a relayer cannot take the fee without doing the work, and one that accepts then stalls is slashed.

submitGasPrivate

The one-call flow over an injected funding step and registry readers:
import { submitGasPrivate, type RegistryReaders } from "@opaquecash/relayer-client";
import { requireEvmDeployment } from "@opaquecash/deployments";

const registry = requireEvmDeployment(11155111).contracts.relayerRegistry;

const result = await submitGasPrivate({
  // The action: a permissionless call the relayer makes from the escrow.
  payload: { chain: 2, target: verifierAddress, calldata },
  fee: parseEther("0.0005"),
  deadline: Math.floor(Date.now() / 1000) + 1800,
  registry,
  gateway: { baseUrl: "http://localhost:8787" }, // any relayer node
  readers,                                        // freeStakeOf + registeredKey
  fundEscrow: async (job) => {
    // Submit job.evmCreateJob with a funding wallet ideally unlinked from your identity.
    const hash = await wallet.sendTransaction(job.evmCreateJob!);
    await publicClient.waitForTransactionReceipt({ hash });
  },
});
// result.winner.bid.operator accepted the job; watch RelayerRegistry.JobSubmitted.
readers supplies the on-chain truth used to verify bids:
const readers: RegistryReaders = {
  freeStakeOf: (op) => publicClient.readContract({ /* freeStakeOf(op) */ }),
  registeredKey: (op) => publicClient.readContract({ /* relayers(op).x25519PubKey */ }),
};
Runnable example: sdk/examples/gas-private-submit.ts.

Building blocks

For custom flows, the steps are exported individually:
ExportPurpose
prepareJob(payload, opts)Commitment + advert + the createJob artifact (EVM tx request or Solana instruction)
buildEvmCreateJob / buildSolanaCreateJobEscrow funding tx builders
postAdvert / collectBids / postPayloadHTTP gateway client
verifyEvmBidSignature / verifyBids / selectWinnerBid verification + stake-weighted selection
sealBox / openBoxNaCl crypto_box, byte-compatible with the relayer node
payloadHash / payloadBytesCommitment + box plaintext for either chain

Solana

Pass a SolanaJobPayload ({ chain: 1, instruction }) and opts.creator; the inner instruction’s accounts must not be signers (the escrow signs nothing on their behalf). prepareJob returns solanaCreateJob for you to send. Verify Solana bids with an ed25519 verifier passed as verifySig.
The payload becomes public when the relayer submits it on-chain; the market hides the submitter, not the action. Fund the escrow from an address unlinked to your primary wallet (fee-in-proof, which removes this, is deferred to a later version).