@loopprotocol/sdk-byoaa 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # @loopprotocol/sdk-byoaa changelog
2
+
3
+ ## 0.1.0-alpha.0 (2026-05-05) — unreleased
4
+
5
+ First alpha. Functionally complete spec-08 surface; on-chain rails are
6
+ devnet-live but not yet on mainnet (pending Bundle 2 deploy + the mainnet
7
+ ShoppingState bump repair).
8
+
9
+ ### Added
10
+
11
+ - `BankReceipt`, `deriveBankTxnId`, `normalizeMerchantName`,
12
+ `validateReceipt` — receipt construction primitives.
13
+ - `Network`, `LoopByoaaConfig`, `resolveConfig`, `getProgramIds`,
14
+ `defaultRpcUrl`, `isMainnet` — network-switchable config layer
15
+ (devnet ↔ mainnet via single field; sandbox fork support via
16
+ `shoppingProgramId` / `vaultProgramId` overrides).
17
+ - `deriveBankAttestedReceiptPda`, `deriveAgentSessionPda` — PDA helpers
18
+ matching the on-chain seed patterns.
19
+ - `instructionDiscriminator`, `encodeAttestedReceiptArgs`,
20
+ `encodeSubmitAttestedReceiptIxData` — hand-rolled Anchor wire encoding
21
+ (no IDL dep so the SDK ships independently of anchor-build cycles).
22
+ - `AttestedReceiptSubmitter`, `EnclaveSigner`, `PolicyInputs`,
23
+ `SubmitResult` — end-to-end submit flow: validate → derive PDA →
24
+ assemble ix → fetch blockhash → enclave-sign → verify → send → confirm.
25
+ Failures returned as discriminated unions; submit batch with
26
+ bounded concurrency + rate limit + per-receipt progress callback.
27
+ - `AttestedReceiptVerifier`, `VerifiedReceipt`, `decodeBankAttestedReceipt`,
28
+ `decodeRegistryPcr0Set` — fetch + decode + EnclaveImageRegistry
29
+ cross-check (caches the registry decode for 60s by default).
30
+ - `scripts/devnet-smoke.ts` — end-to-end submit + verify against the live
31
+ devnet `loop-shopping` program. Run via `tsx` with the documented env
32
+ vars (PAYER_KEYPAIR, VAULT_PUBKEY, SESSION_PUBKEY, SESSION_SECRET_KEY).
33
+
34
+ ### Tests
35
+
36
+ 71 tests across 6 vitest files covering: type validation; normalization
37
+ idempotence; hash determinism; PDA derivation across vault / txn /
38
+ program; full Anchor codec round-trip; submitter happy path with a
39
+ fake enclave (tweetnacl-backed) + RPC stubs; verifier decode + audit
40
+ both pass and fail paths; RPC failure → typed error; batch
41
+ fail-isolation + rate limiting.
42
+
43
+ ### Known limitations
44
+
45
+ - Mainnet `SHOPPING` program id in `MAINNET_PROGRAM_IDS` is a placeholder
46
+ (`11111…`). When Bundle 2 deploys, edit `src/config.ts` to flip to the
47
+ live id.
48
+ - The `EnclaveSigner` contract is duck-typed against the parent SDK's
49
+ `EnclaveClient` — both sides ship without a hard import to avoid a
50
+ circular package dependency.
51
+ - `forMerchant()` fetches every program account and filters client-side
52
+ because `merchant_name_raw` lives at variable offset on-chain. Use
53
+ the off-chain `attested_receipt_index` Supabase mirror
54
+ (loop-site-v2 PR #27) for production-scale merchant queries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OAR Technologies Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # @loopprotocol/sdk-byoaa
2
+
3
+ **Bring Your Own Attested Agent** — TypeScript SDK for submitting bank-attested receipts to Loop Protocol from inside an attested enclave.
4
+
5
+ > **Status:** alpha (`0.1.0-alpha.0`). 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.
6
+
7
+ ## What this is
8
+
9
+ 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:
10
+
11
+ 1. Logs into a bank (the agent has the credentials; **Loop never touches them**).
12
+ 2. Reads transactions.
13
+ 3. Constructs a `BankReceipt` and signs it with the enclave-bound session key.
14
+ 4. Submits the receipt to the on-chain `submit_attested_receipt` instruction.
15
+
16
+ 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`).
17
+
18
+ Spec: [`docs/roadmap/08-byoaa-sdk.md`](../docs/roadmap/08-byoaa-sdk.md).
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install @loopprotocol/sdk-byoaa @loopprotocol/sdk
24
+ # or
25
+ pnpm add @loopprotocol/sdk-byoaa @loopprotocol/sdk
26
+ ```
27
+
28
+ `@loopprotocol/sdk` is a peer-style dep — the BYOAA SDK relies on its `EnclaveClient` (from spec 07a) for vsock-relayed signing.
29
+
30
+ ## Quick start
31
+
32
+ ### Construct + validate a receipt (no on-chain interaction)
33
+
34
+ ```typescript
35
+ import {
36
+ deriveBankTxnId,
37
+ normalizeMerchantName,
38
+ validateReceipt,
39
+ type BankReceipt,
40
+ } from "@loopprotocol/sdk-byoaa";
41
+
42
+ const merchantNameRaw = normalizeMerchantName(
43
+ " starbucks #12345 SEATTLE WA "
44
+ ); // → "STARBUCKS #12345 SEATTLE WA"
45
+
46
+ const bankTxnId = deriveBankTxnId({
47
+ merchantNameRaw,
48
+ amountCents: 875n,
49
+ postedAt: 1714521600n, // 2024-05-01 00:00:00 UTC
50
+ accountLast4: 4242,
51
+ });
52
+
53
+ const receipt: BankReceipt = {
54
+ bankTxnId,
55
+ merchantNameRaw,
56
+ mcc: 5814,
57
+ amountCents: 875n,
58
+ postedAt: 1714521600n,
59
+ accountLast4: 4242,
60
+ };
61
+
62
+ const validation = validateReceipt(receipt);
63
+ if (!validation.ok) {
64
+ throw new Error(`Bad receipt: ${validation.error}`);
65
+ }
66
+ ```
67
+
68
+ ### Submit from inside an attested enclave
69
+
70
+ `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.
71
+
72
+ `AttestedReceiptVerifier` 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.
73
+
74
+ ## Package surface
75
+
76
+ | Export | Purpose |
77
+ |---|---|
78
+ | `BankReceipt` | In-memory shape of one bank transaction |
79
+ | `deriveBankTxnId(input)` | Stable 32-byte sha256 over normalized fields. Re-fetches collide on the same on-chain PDA. |
80
+ | `normalizeMerchantName(raw)` | Canonical form: trim → collapse whitespace → uppercase → strip non-ASCII |
81
+ | `validateReceipt(receipt, nowSeconds?)` | Front-runs the on-chain handler's bounds checks; cheap, no I/O |
82
+ | `MAX_RECEIPT_CENTS` | $100M cap (mirrors on-chain) |
83
+ | `MAX_MERCHANT_NAME_RAW_LEN` | 64 bytes (mirrors on-chain) |
84
+ | `MAX_RECEIPT_AGE_SECONDS` | 365 days (mirrors on-chain) |
85
+ | `AttestedReceiptSubmitter` | Builds/signs/sends `submit_attested_receipt` transactions for enclave-bound sessions |
86
+ | `AttestedReceiptVerifier` | Fetches and verifies recorded attested receipt PDAs against expected receipt/session fields |
87
+
88
+ ## What this does NOT do
89
+
90
+ - **Hold bank credentials** — that's the user's enclave's job.
91
+ - **Run the bank scraper** — that's the user's agent code.
92
+ - **Manage the enclave attestation** — see `@loopprotocol/sdk` `EnclaveClient` (spec 07a).
93
+ - **Pay receipt rent** — the session signer (the enclave) pays SOL fees + ~0.0018 SOL rent per receipt.
94
+ - **Honor receipts as merchant payouts** — that's spec 08a (`merchant_claim_attested_receipt`), shipped as a separate flow.
95
+
96
+ ## Trust model
97
+
98
+ 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".
99
+
100
+ ## Development
101
+
102
+ ```bash
103
+ npm install
104
+ npm run build
105
+ npm test
106
+ npm run typecheck
107
+ ```
108
+
109
+ 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`.
110
+
111
+ ## License
112
+
113
+ MIT