Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
솔라나 기반 코-사인 신용(엘 피아도)으로 가게와 이웃이 각각 휴대폰으로 서명해 상환 이력을 구축
Corner store credit (el fiado) co-signed on Solana: store and neighbor each sign from their own phone, building a repayment history the neighbor can take anywhere.
금융TypeScript · JavaScriptGitHub @devOr05온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기La "Libreta de Almacén On-Chain" (Score Crediticio Descentralizado)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
🛒 Tefi.app — Digital Neighborhood Credit Ledger on Solana
Turning informal corner store credit ("el fiado") into a verifiable, portable on-chain repayment history, co-signed by store and neighbor.
Built for the Colosseum Crypto World's Fair Hackathon & Superteam Argentina Track.README 전문 보기 ↗Turning informal corner store credit ("el fiado") into a verifiable, portable on-chain repayment history, co-signed by store and neighbor.
Built for the Colosseum Crypto World's Fair Hackathon & Superteam Argentina Track.
9UmX9z1Cr2FCidUBgoMJzDCRp5aeTs7xz4umKRnEGnJQIn Argentina and throughout Latin America, corner grocery stores (almacenes de barrio) sell on "el fiado": informal credit written in a paper notebook.
Tefi is a mobile-first Progressive Web App (PWA) that replaces the paper notebook with a ledger on Solana where every fiado and every repayment is a transaction signed by both the store and the neighbor, each from their own phone.
dolarapi.com exchange rate), takes a photo of the receipt and signs first. The request, carrying the store's signature, is shown as a QR code. The neighbor scans it with their own phone, reviews what the transaction says, adds the second signature and submits it.repay_fiado; the neighbor co-signs the same way. Neither party can record or settle a debt alone.Tefi records the debt and its repayment; the money itself keeps moving off-chain between neighbor and store. Amounts are stored in USDC units as a stable unit of account, not as token transfers.
STORE PHONE (holds only the store key) NEIGHBOR PHONE (holds only the neighbor key)
────────────────────────────────────── ────────────────────────────────────────────
0. Shows "My Tefi QR": public key and name only
1. Scans it once: neighbor saved in the store's list
2. Builds issue_fiado, feePayer = store
3. tx.partialSign(storeKey)
4. Shows a QR / link with its signature and
the fields of the request ─────────────────► 5. Rebuilds the same transaction with its own key
6. Verifies the store signature over it and rejects
anything that is not exactly a Tefi fiado/repayment
for its own key (no hidden instructions)
7. Checks that the receipt shown matches the
receipt_hash the store signed
8. tx.partialSign(neighborKey) and sends it
9. Follows the transaction by its own signature
and shows it on Solana Explorer ◄─────────── 9. Shows the transaction on Solana Explorer
src/solana/cosign.ts.src/services/qrDecoder.ts).| Layer | Technology | Status & Purpose |
|---|---|---|
| Blockchain L1 | Solana Devnet (api.devnet.solana.com, configurable) | Low fees and fast confirmation make co-signing a US$2–4 purchase at the counter viable. |
| Smart Contract | Anchor Framework (Rust) v0.29.0 | PDAs for stores, neighbors and fiados. 14 integration tests against solana-test-validator in CI. |
| Web3 Client SDK | @solana/web3.js 1.x & @coral-xyz/anchor 0.29 | Instruction building from the IDL, partial signing, transaction (de)serialization and account decoding. |
| Co-signature transport | qrcode & jsQR (plus the phone's own barcode detector where the browser has one) | The store's signature and the fields of the request travel from the store phone to the neighbor phone as a QR code or link. |
| Fee sponsorship | Store as fee payer | The store pays the network fee and account rent of every fiado and repayment, so neighbors never need SOL. |
| Frontend / PWA | React 18, TypeScript, Tailwind CSS, Vite | Mobile-first Progressive Web App (PWA) with precached assets. |
| Exchange rate | dolarapi.com REST API | Argentine Peso (ARS) to USD crypto rate, with a fixed reference rate as offline fallback. It is an off-chain REST feed, not an on-chain oracle. |
Not part of this build (see the Roadmap below): attestations, embedded wallets, payment rails, insurance or savings products, on-chain price oracles and decentralized identity.
Daily grocery purchases of US$1.50 to US$10 (bread, milk, deli items) cannot carry a meaningful per-transaction cost:
This is a hypothesis: it has not been validated with a paying lender yet. Validating it is one of the goals of the pilot.
The Anchor program (contracts/tefi_program/programs/tefi_program/src/lib.rs) enforces bilateral agreements through Program Derived Addresses (PDAs):
┌────────────────────────────────────────────────────────────────────────┐
│ Solana Devnet State │
├────────────────────────────────┬───────────────────────────────────────┤
│ Merchant Profile PDA │ Customer Profile PDA │
│ seeds = ["merchant", pubkey] │ seeds = ["customer", pubkey] │
│ • Business name & category │ • On-chain Credit Score (0-100) │
│ • Total sales & default stats │ • Credit limit (USDC units) │
│ • Sequential fiado nonce │ • Active debt & total repaid │
├────────────────────────────────┴───────────────────────────────────────┤
│ Fiado Record PDA │
│ seeds = ["fiado", merchant_pubkey, customer_pubkey, nonce] │
│ • Amount (USDC units), due date, status (Active / Paid) │
│ • receipt_hash: SHA-256 of the receipt, never the purchase details │
└────────────────────────────────────────────────────────────────────────┘
| Instruction | Required signers | Who pays fee & rent | What it does |
|---|---|---|---|
initialize_merchant | Store | Store | Creates the store profile PDA. |
initialize_customer | Payer (store) + Neighbor | Store | Creates the neighbor profile PDA (score 65, limit 50 USDC). Sent in the same transaction as the neighbor's first fiado. |
issue_fiado | Store + Neighbor | Store | Creates the fiado PDA and adds the debt, within the neighbor's on-chain limit. Rejects any receipt_hash that is not a 64-character hex SHA-256. |
repay_fiado | Store + Neighbor | Store | Marks the fiado as paid. If repaid on or before the due date: score +5 (max 100) and limit +5 USDC. |
claim_insurance | Store | Store | Program-level default marking after a mandatory 30-day grace period (lowers the neighbor's score). Not exposed in the PWA: there is no insurance fund. |
The program is deployed on devnet under its own id. Open any link below and check the Signers of the transaction on Solana Explorer.
| What | Where | What to look at |
|---|---|---|
| Program | 9UmX9z1C…EGnJQ | Executable, owned by the upgradeable BPF loader. |
| Deployment (10 Oct 2026) | 5AJEhGf3…XjuiR | The deployed bytes are the tefi_program-sbf artifact built by CI (282,728 bytes, SHA-256 d34303c5…6ca2e7). |
Live Demo issue_fiado (2 devices in video) | 2r5x9T9p…bGnn | Laptop store EUHTPsts… (fee payer) and phone neighbor 5DJf3uo3… (0 SOL). Receipt hash is SHA-256. |
Live Demo repay_fiado (2 devices in video) | 3aFeMRvV…vYjG | Co-signed repayment: store confirms received payment, neighbor score updates to 70 (Gold Tier), limit to 55 USDC. |
Co-signed issue_fiado (automated e2e) | 4niTarxJ…KYBzy | 2 signatures: store E3MsTtDE… (fee payer) and neighbor 2j17nfLJ…. Instructions InitializeCustomer + . |
How these transactions were produced. Two complementary verification suites:
e2e/two-phones-devnet.mjs on 10 Oct 2026: four isolated browser profiles driving the built PWA across two stores and two neighbors, verified directly on-chain after every step.Reading that neighbor's history as a lender would (npm run read:history -- 2j17nfLJU1CETKKDvKpmJTxy43cnh3sNbRSFCE8GrCLE):
Credit score: 75 / 100
Credit limit: 60.00 USDC
Active debt: 0.00 USDC
Repaid to date: 2.44 USDC
Fiados co-signed with stores: 2
PAID 0.94 USDC due 2026-10-25 store E3MsTtDEG2v8V29Y7pfDbp66sSjJudVYZ7iKFjmbZVc5 account 22WAajsdMZu7AfrUhPGeTuP6dE8M7oaqApah8h5XZcak
PAID 1.50 USDC due 2026-10-25 store HXU7bxpntV9KtziSmtKJbaiqkzBiGSmoGNin8yoCjeJY account DNSSGwp7i4d7rMmQ2UqZpUjSziaiaT39UpukCxVv6sX7
The 06/10 deployment (3bs3SLqe…) is superseded: it does not include the bilateral repay_fiado and cannot be upgraded.
A lender only needs the neighbor's public key and an RPC endpoint. No Tefi server is involved:
import { Connection, PublicKey } from '@solana/web3.js';
import { BorshAccountsCoder, Idl } from '@coral-xyz/anchor';
import idl from './src/solana/idl.json';
const PROGRAM_ID = new PublicKey('9UmX9z1Cr2FCidUBgoMJzDCRp5aeTs7xz4umKRnEGnJQ');
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
const coder = new BorshAccountsCoder(idl as Idl);
const neighbor = new PublicKey('<neighbor public key>');
const [profilePda] = PublicKey.findProgramAddressSync([Buffer.from('customer'), neighbor.toBuffer()], PROGRAM_ID);
// Credit profile: one account per neighbor
const profile = coder.decode('CustomerProfile', (await connection.getAccountInfo(profilePda))!.data);
console.log('Credit score:', profile.creditScore); // 0-100
console.log('Credit limit (USDC):', profile.creditLimitUsdc.toNumber() / 1_000_000);
console.log('Active debt (USDC):', profile.activeDebtUsdc.toNumber() / 1_000_000);
console.log('Repaid to date (USDC):', profile.totalRepaidUsdc.toNumber() / 1_000_000);
// Every fiado of that neighbor, across all stores (customer is at byte offset 40 of FiadoRecord)
const fiados = await connection.getProgramAccounts(PROGRAM_ID, {
filters: [{ memcmp: { offset: 40, bytes: neighbor.toBase58() } }]
});
for (const { account } of fiados) {
const fiado = coder.decode('FiadoRecord', account.data);
console.log(fiado.merchant.toBase58(), fiado.amountUsdc.toNumber() / 1_000_000, fiado.status === 2 ? 'PAID' : 'ACTIVE');
}
The same read is available as a script: npm run read:history -- <neighbor public key> (scripts/read-neighbor-history.mjs).
receipt_hash.localStorage without account recovery. Clearing browser storage loses the key. Embedded wallets (e.g., Privy/Turnkey) and social recovery are planned for the production roadmap before any pilot with real funds.InitializeMerchant is permissionless). In the prototype, small repeated self-transactions (1 micro-USDC) could technically increment a customer's score. Production mitigation requires merchant whitelisting, physical verification, or volume/reputation weighting.receipt_hash is a SHA-256 hash without salt; the purchase line items travel off-chain in the QR code or direct messaging link.| Command | What it runs | Tests |
|---|---|---|
npm test | Vitest suites that import the real modules: the co-signature protocol (cosign.test.ts), instruction building and account decoding (program.test.ts), RPC error classification (anchorClient.test.ts), request pacing under the RPC rate limit (rpcRetry.test.ts), QR decoding at camera resolution (qrDecoder.test.ts), the debt ledger (financialLedger.test.ts), the passbook view (libreta.test.ts), Spanish/English completeness (translations.test.ts), the version label (version.test.ts) and what the site publishes for search engines and AI assistants (site.test.ts). | 107 |
anchor test (CI) | Mocha tests against the compiled program on solana-test-validator: both signatures required, credit limit, double repayment, unauthorized store, grace period, hashed receipts and a two-device partial-signing round trip with a 0 SOL neighbor (). |
All four run in GitHub Actions on every pull request and on every push to main: .github/workflows/anchor.yml (PWA build, npm test and the site check against the built PWA) and .github/workflows/contract-ci.yml (SBF build, Anchor tests and then the end-to-end run, with the PWA pointed at the same local validator). To run the end-to-end test against devnet yourself:
npm run build && npx vite preview --port 4173 & # serve the built PWA
npm install --prefix e2e # Playwright driver + QR decoder; drives your installed Chrome
npm run e2e:devnet -- <keypair.json holding ~0.1 devnet SOL>
It funds two throwaway store wallets from that keypair (0.03 SOL each) and writes screenshots and a report.json with every transaction to e2e/shots/. Set TEFI_BROWSER_CHANNEL=msedge to drive Edge instead of Chrome.
Version 2.1.0 · 687581d · 2026-10-10 13:28: the version of package.json, the commit the app was built from (the line links to that commit on GitHub) and the date of that commit in the phone's own time. The same data is published at /version.json. Two phones run the same build only if they show the same line; a phone showing an older one has to reopen the app (src/version.ts)./es/ opens the app in Spanish for a first-time visitor and has its link preview in Spanish; the root address is the English one. A language chosen with the flags wins over the address.scripts/make-og-images.mjs.hreflang links, schema.org WebApplication data and, inside <noscript>, the text of what Tefi is, how it works and where the code and the on-chain program are. The site also publishes robots.txt, sitemap.xml and llms.txt. All of it is generated at build time from src/site/; nothing is hand-written into dist.The app only shows what runs on-chain today. Everything below is not built yet:
# Clone the repository
git clone https://github.com/devOr05/tefi-app.git
cd tefi-app
# Install dependencies
npm install
# Start development server
npm run dev
# Run the tests
npm test
With a single device, use the Store / Neighbor switch in the header: the app labels it as a single-device demo.
npm run build
The pages declare the address they are published at (canonical link, sitemap, link previews). It defaults to https://tef-iapp.vercel.app; to publish under another domain, build with VITE_SITE_URL=https://<your domain>.
The app talks to the public devnet node, which accepts roughly 40 requests per 10 seconds per IP address (measured on 10 Oct 2026). Every phone behind the same Wi-Fi shares that budget, and rejected requests count against it too. When the node answers 429, the app repeats the request and spaces out all the requests of that phone until the node accepts them again (src/solana/rpcRetry.ts), so a busy network shows up as a few seconds of waiting.
For an event with many phones on one network, point the build at your own devnet endpoint:
VITE_SOLANA_DEVNET_RPC_URL=https://<your devnet rpc> npm run build
The program id is declared in lib.rs, Anchor.toml, src/solana/idl.json and src/solana/program.ts (CI and npm test check that they match). The SBF binary is built by the Anchor Contract Compilation & Localnet Tests workflow and published as the tefi_program-sbf artifact.
solana program deploy tefi_program.so --program-id <program keypair or id> --keypair <upgrade authority keypair> --url devnet
Keep the upgrade authority keypair outside the repository.
Mario Orostizaga — Founder & Full-Stack Developer
Technical Collaboration & Attributions
9UmX9z1C…), implementing the real two-phone cryptographic co-signing flow (store as fee payer, zero SOL needed for neighbors), building the Vitest test suite and automated Devnet E2E checks, and cleaning up mocked modules to strictly reflect verified on-chain functionality.IssueFiadoCo-signed repay_fiado (automated e2e) | 5SZ1BdpU…odrSR | The same 2 signers. The neighbor never held SOL. |
| Second store, same neighbor | 5RKrusTT…RvB35 | issue_fiado signed by another store (HXU7bxpn…) and the same neighbor, with no profile setup: the history is portable. |
| Two counters at the same time | 2kmS3rBj…S5pPz · BjAZwHt3…ZnBeJ | A fiado for a second neighbor at the first store while the second store collected its fiado, in parallel. |
| Neighbor credit profile (PDA) | 3j5MWAHo…XiRmK | After two on-time repayments at two different stores: score 75, limit 60 USDC, debt 0. |
| Settled fiado (PDA) | 22WAajsd…XZcak · ACmAxLDy…M5Do | Status Paid; receipt_hash is a SHA-256, not the purchase details. |
| 14 |
npm run e2e:devnet | The built PWA against Solana Devnet with four isolated browser profiles (two stores, two neighbors) that exchange only QR codes, scanned through a simulated camera or opened as links: fiado, repayment, a second store reading the portable score, two counters at the same time, plus the controls (QR for another neighbor, tampered receipt, QR used twice). Every step is verified on-chain from outside the app (two-phones-devnet.mjs). | 46 checks |
npm run check:site | The published site read the way a search engine or an AI assistant reads it, without running JavaScript: both language pages (title, description, canonical, hreflang, link preview, structured data, readable text) and robots.txt, sitemap.xml, llms.txt, version.json (check-site.mjs). | 34 checks |