npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@loopprotocol/sdk-byoaa

v0.1.0-alpha.7

Published

Bring Your Own Attested Agent — TypeScript SDK for submitting bank-attested receipts to Loop Protocol from inside an attested enclave.

Readme

@loopprotocol/sdk-byoaa

Bring Your Own Attested Agent — TypeScript SDK for submitting bank-attested receipts to Loop Protocol from inside an attested enclave.

Status: alpha candidate (0.1.0-alpha.6). On-chain primitives are deployed on devnet (loop-shopping submit_attested_receipt + BankAttestedReceipt PDA). Mainnet deploy gated on Bundle 2 (loop-protocol PR #27 + #28 + #29) + the mainnet ShoppingState bump repair.

What this is

Loop Protocol's bank-data layer is built on the BYOAA model: users (or their hosted-agent provider — Anthropic Claude with Computer Use, OpenAI Operator, self-hosted Nitro Enclaves, etc.) run an agent inside an attested enclave that:

  1. Logs into a bank (the agent has the credentials; Loop never touches them).
  2. Reads transactions.
  3. Constructs a BankReceipt and signs it with the enclave-bound session key.
  4. Submits the receipt to the on-chain submit_attested_receipt instruction.

This package provides the TypeScript primitives for steps 3 and 4. The enclave + bank scraping is the user's responsibility (see the reference implementation at loop-byoaa-reference-agent).

Spec: docs/roadmap/08-byoaa-sdk.md.

Install

npm install @loopprotocol/sdk-byoaa
# peer deps required for Solana/on-chain helpers (Node 20+ runtime):
npm install @coral-xyz/anchor @solana/web3.js

@loopprotocol/sdk-byoaa has a dependency-light default install: production dependencies are limited to browser-safe hashing for receipt helpers. Solana/on-chain helpers require the peer packages above; REST-only and receipt-only consumers do not need to import those surfaces.

Runtime support

0.1.0-alpha.6 publishes explicit entry points:

  • @loopprotocol/sdk-byoaa/receipt — browser-safe receipt helpers only; no Solana, Anchor, or Node crypto imports. Node 18+ compatible.
  • @loopprotocol/sdk-byoaa/rest — REST/API-key client surface. Node 18+ and browser-safe.
  • @loopprotocol/sdk-byoaa/proof — browser-safe shape-only proof helpers; no Solana, Anchor, Buffer, or Node crypto imports. Current proof verification is explicitly shape_only; it is not full cryptographic authenticity verification. Node 18+ compatible.
  • @loopprotocol/sdk-byoaa/solana — Node 20+ only. Solana/on-chain helpers: network config, PDA derivation, instruction encoding, receipt submission, and on-chain receipt verifier/account decoders.
  • @loopprotocol/sdk-byoaa — browser-safe alpha aggregate root with receipt, REST, and shape-only proof helpers. Node 18+ compatible. Use /solana for chain/RPC helpers.

For browser/frontend code, prefer the smallest subpath. Do not ship REST SDK keys to browsers.

Mainnet and localnet fail closed in config resolution:

  • network: "mainnet-beta" throws until BYOAA mainnet shopping program ids are live. Controlled dry runs must pass explicit non-placeholder program ids plus dangerouslyAllowUnreleasedMainnet: true.
  • network: "localnet" requires explicit shoppingProgramId and vaultProgramId; the SDK will not silently reuse devnet ids for local transaction construction.

Security and API keys

LoopByoaaClient SDK keys are bearer credentials. Handle them like passwords:

  • keep SDK keys in server-side environment variables or a secret manager;
  • do not ship SDK keys to browser/frontend bundles;
  • do not log or serialize SDK keys, clients, headers, request objects, or errors containing request data;
  • rotate any key that appears in logs, snapshots, telemetry, or crash reports.

By default, the REST client derives the Loop API host from the key environment. If you pass a custom baseUrl, the SDK will send Authorization: Bearer <apiKey> to that host. Custom hosts are blocked unless you explicitly opt in:

import { LoopByoaaClient } from "@loopprotocol/sdk-byoaa";

const loop = new LoopByoaaClient({
  apiKey: process.env.LOOP_BYOAA_API_KEY!,
  baseUrl: "https://trusted-test-gateway.example.com",
  dangerouslyAllowCustomBaseUrl: true, // sends bearer credentials to this host
});

Only use dangerouslyAllowCustomBaseUrl for trusted test harnesses or approved federated deployments.

Quick start

Construct + validate a receipt (no on-chain interaction)

import {
  deriveBankTxnId,
  normalizeMerchantName,
  validateReceipt,
  type BankReceipt,
} from "@loopprotocol/sdk-byoaa/receipt";

const merchantNameRaw = normalizeMerchantName(
  "  starbucks #12345  SEATTLE WA  "
); // → "STARBUCKS #12345 SEATTLE WA"

const postedAt = BigInt(Math.floor(Date.now() / 1000));

const bankTxnId = deriveBankTxnId({
  merchantNameRaw,
  amountCents: 875n,
  postedAt,
  accountLast4: 4242,
});

const receipt: BankReceipt = {
  bankTxnId,
  merchantNameRaw,
  mcc: 5814,
  amountCents: 875n,
  postedAt,
  accountLast4: 4242,
};

const validation = validateReceipt(receipt);
if (!validation.ok) {
  throw new Error(`Bad receipt: ${validation.error}`);
}

Submit from inside an attested enclave

AttestedReceiptSubmitter signs and submits one or more AttestedReceipt payloads from an enclave-bound session signer. It validates receipt bounds client-side, derives the receipt PDA, builds the submit_attested_receipt instruction, and sends it through the configured Solana connection.

AttestedReceiptVerifier is exported from @loopprotocol/sdk-byoaa/solana. It fetches recorded receipt PDAs and verifies the on-chain fields against the expected bank transaction id, merchant, amount, timestamp, and PCR/session metadata. It is a read/verify helper; it does not trust off-chain scraper output by itself.

Package surface

| Export | Purpose | |---|---| | BankReceipt | In-memory shape of one bank transaction | | deriveBankTxnId(input) | Stable 32-byte sha256 over normalized fields. Re-fetches collide on the same on-chain PDA. | | normalizeMerchantName(raw) | Canonical form: trim → collapse whitespace → uppercase → strip non-ASCII | | validateReceipt(receipt, nowSeconds?) | Front-runs the on-chain handler's bounds checks; cheap, no I/O | | MAX_RECEIPT_CENTS | $100M cap (mirrors on-chain) | | MAX_MERCHANT_NAME_RAW_LEN | 64 bytes (mirrors on-chain) | | MAX_RECEIPT_AGE_SECONDS | 365 days (mirrors on-chain) | | AttestedReceiptSubmitter | Builds/signs/sends submit_attested_receipt transactions for enclave-bound sessions | | AttestedReceiptVerifier | Fetches and verifies recorded attested receipt PDAs against expected receipt/session fields |

What this does NOT do

  • Hold bank credentials — that's the user's enclave's job.
  • Run the bank scraper — that's the user's agent code.
  • Manage the enclave attestation — see @loopprotocol/sdk EnclaveClient (spec 07a).
  • Pay receipt rent — the session signer (the enclave) pays SOL fees + ~0.0018 SOL rent per receipt.
  • Honor receipts as merchant payouts — that's spec 08a (merchant_claim_attested_receipt), shipped as a separate flow.

Trust model

The receipt's on-chain pcr0 field is copied at submit time from the registered session, which was bound to the enclave's image at registration. To submit a forged receipt, an attacker would need an enclave whose PCRs match an audited image AND would be admin-approved in EnclaveImageRegistry — same trust assumption as the entire spec 07a system. See spec 08 § "Threat model".

Proof helper semantics

verifyAttestedReceiptProofShape() is a shape/fail-closed helper, not a cryptographic authenticity verifier. For the current cose_sign1_x509 arm it checks that signature and cert_chain are byte-shaped and returns:

{
  ok: true,
  proof_type: "cose_sign1_x509",
  verification_level: "shape_only",
  cryptographic_authenticity_verified: false,
}

It does not validate the COSE signature, X.509 trust chain, enclave attestation root, audited-image binding, or bank/source authenticity. Reserved ZK proof arms fail closed with UnsupportedProofTypeError. The legacy verifyAttestedReceiptProof() export is a deprecated alias with the same shape-only semantics.

Development

npm install
npm run build
npm test
npm run typecheck

Tests are vitest, no on-chain dependency. End-to-end devnet rehearsal lives in loop-protocol/scripts/devnet-rehearsal/test-spec08-09-flow-devnet.ts.

License

MIT