ai-startup-skills
AI 제품을 만드는 스타트업을 위한 7단계 에이전트 스킬: 검증 → 비즈플랜 → 정책 → 로드쇼 → 고객 확보 → 가격 책정 → 등록
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Arrange the deal anywhere. Verify the funds. Pay at the handover.
Built for HackMeridian 2026 · Genesis · Stellar Composed
Implementation reviewed against the local source on 26 October 2026. Hosted features depend on deployment configuration.
Launch SHAKE · Built on Stellar · Judge walkthrough · Marketplace extension · Features · Safety · Architecture · Run locally · On-chain proof
You find a second-hand phone, agree on a price, and arrange to meet. Then comes the uncomfortable part: who goes first? The buyer does not want to pay before seeing the item. The seller does not want to hand it over on the strength of a payment screenshot.
SHAKE gives both people something they can verify. The buyer locks test funds in a Stellar smart contract. The seller checks the actual contract state. At the meetup, the buyer inspects the item, scans the seller's one-time QR, and confirms payment. If the deal falls through, the contract provides a refund path.
SHAKE is a payment companion for deals arranged on OLX, Vinted, Facebook Marketplace, WhatsApp, or any other channel. A shareable link connects the conversation to the payment; no marketplace integration is required. Buyers can meet in person or choose shipping, with a QR inside the package and a dispute window after delivery. Before committing, either person can check suspicious messages, inspect public deal activity, and find nearby public meetup places.
Live on Stellar Testnet · Test mode. Wallet creation, currency conversion, locking, settlement, refunds, and transaction proofs run against the live test network. Test assets have no cash value. The bank withdrawal integration submits a real testnet transfer to the anchor; its final bank payout runs in a sandbox and does not credit a bank account.
SHAKE is a Stellar Composed project. One payment runs through our own Soroban contract and eight other parts of the Stellar ecosystem. Each one does a job the user can feel; none is there just to be listed.
| # | Stellar piece (official name) | Kind | What it does in SHAKE | Where |
|---|---|---|---|---|
| 1 | Soroban smart contract, written by us | Stellar protocol | Holds the money. Pays the seller only with the secret from their one-time QR (a hash-lock), or with both halves of the key when there is no signal. Refunds the buyer otherwise. | contracts/escrow |
| 2 | OpenZeppelin Smart Accounts with passkeys, through Nido | OpenZeppelin · ecosystem wallet | The buyer approves SHAKE once with Face ID or Touch ID in Nido; after that, locks and releases need no prompt, within on-chain limits. Nothing to write down, no app to install. | nido.ts, passkey.ts |
| 3 | Stellar Asset Contracts (SAC) | Stellar protocol | tEUR, tUSD, tGBP and tBRL are classic Stellar assets, wrapped so the contract moves them as Soroban tokens. | scripts/setup.mjs |
| 4 | Path Payments + Liquidity Pools on the Stellar DEX | Stellar protocol | Pay in your own currency. A Brazilian buyer pays in reais and the deal locks euros: one pathPaymentStrictReceive converts on the way in. | payInOp in stellar.ts, scripts/fx.mjs |
| 5 | Reflector FX oracle (SEP-40) | Ecosystem oracle |
Around them: an MCP server, so Claude, ChatGPT or Cursor can prepare and verify SHAKE payments but never move money, and a browser extension for 16 marketplaces.
A deal locks in one currency, but the buyer doesn't need to hold it. In the pay sheet, the buyer picks Pay in € · $ · £ · R$:
CCSSOHTB…NV4W) and asks Horizon for the cheapest path: "You pay 1 133,14 R$. Stellar converts it to 200 € on the way in."On testnet: a new account pays in reais and receives exactly 200 €, at Reflector's rate plus the pool's 0.3% fee. Two-hop paths work too: reais to dollars route through euros.
scripts/fx.mjs opens three pools (tEUR against tUSD, tGBP and tBRL) at Reflector's rate. Each is 5 million euros deep, so a 2 000 € deal moves the rate by about 0.04%. Run it again at any time to re-peg the pools to the latest rate.
It works with Face ID too. A Nido smart account is a contract address, and classic path payments can't credit one. So for Face ID buyers the conversion lands at the FX desk that provides the pools' liquidity, and the desk forwards the converted money to the smart account through the asset's SAC: two public transactions. Here a Nido account is paid in reais and receives 1 €.
The rates are real; the liquidity is our own test liquidity.
A listing becomes a SHAKE payment. The desktop Chrome/Edge extension adds Pay safely with SHAKE to listing pages on Vinted, OLX, Wallapop, Depop, eBay, Etsy, Gumtree, Leboncoin, Marktplaats, Kleinanzeigen, Facebook Marketplace, Mercari, Poshmark, OfferUp, Craigslist, and Carousell. Its isolated panel reads the title, price, and currency, lets the buyer review or edit them, then opens a prefilled SHAKE payment with a link to the original listing.
Install SHAKE for marketplaces · Extension source and installation guide
For the judge walkthrough, load the repository's extension folder through chrome://extensions → Developer mode → Load unpacked, refresh a supported listing, select Pay safely with SHAKE, and continue into the payment form. For other shops, the pinned toolbar action reads the current product page on demand. No money moves until the buyer explicitly locks funds in SHAKE. The seller still needs to agree to use SHAKE and join the shared deal.
Extraction uses Product JSON-LD, Open Graph metadata, and visible listing fields. Marketplace layouts, regional domains, and prices vary; users confirm imported details. EUR, USD, GBP, and BRL test settlement assets are supported, and the buyer can pay in any of the four (see Pay in your own currency). Other currencies require an explicit agreed amount. The extension is independent of these marketplaces and does not verify sellers or inherit their buyer protection. Local unpacked installation is required; there is no Web Store release yet. Chromium fixtures verify the implementation; fixture coverage does not guarantee every live listing.
| Step | Buyer | Seller |
|---|---|---|
| Lock | Enter the item and amount. Lock funds for a deal with a 24-hour expiry. | Receive the deal link in the chat you already use. |
| Verify | Keep the funds committed while arranging the handover. | Verify the amount and live on-chain status. Join to generate a handshake QR. |
| Meet | Inspect the item and scan the QR, or enter the code underneath it. | Show the QR on your own phone. |
| Shake | Hold to confirm, or use the supported phone-bump gesture after code verification. | Wait for your own screen to confirm release before handing over the item. |
| Keep the proof | Open a public receipt with transaction links. | See the same settlement and optionally try testnet cash-out. |
For meetup deals, before a seller joins, the buyer can cancel. After acceptance, the seller can cancel and refund the buyer. Once the expiry passes, anyone can submit a refund returning the funds to the buyer. Expiry makes a refund available; a transaction must still be submitted. Shipping has a separate lifecycle: once marked shipped, funds can only be released or settled through the dispute process described below.
Meetups happen in garages, basements, car parks and metro stations. So each phone holds half of the key: the seller's QR secret, and a buyer secret whose SHA-256 hash lock commits on-chain. If the buyer's phone has no signal when they hold to pay, it shows its half as a QR instead of submitting. The seller taps No signal? Scan the buyer's phone; their phone checks both halves against the deal it loaded earlier, without any network, and shows Paid. settle(deal_id, secret, half) needs no signature, so whichever phone gets signal first submits it through OpenZeppelin Channels. The final screen shows when the deal was shaken and when it landed on Stellar.
Why the seller can hand over the item: once a seller has joined, only that seller can cancel before expiry, and settle can only pay the bound seller. Limits: both phones must open the deal online once beforehand (there is no service worker), the seller must get signal before the deal expires, and the buyer's half is derived from the browser key on the phone that locked the deal.
Open the live SHAKE application.
The introduction is a working transaction flow. The judge participates in the product before reaching its explanation.
/try./r/<deal-id> for the receipt.Use separate browser profiles because wallets are stored on each device. For phone testing, serve the app over HTTPS for camera and passkey access. Localhost also works for desktop testing. Confirmation time depends on testnet and relayer conditions; the project's build notes record roughly 6–10 seconds per transaction step.
/deal/new and select It's shipped. The app sets a 14-day pre-shipment expiry and assigns the SHAKE team address as resolver.node scripts/resolve.mjs <deal-id> <amount-to-buyer>. The amount is in the deal's own test currency, not a currency conversion. The script signs with TEAM_SECRET; the contract sends the chosen amount to the buyer and the remainder to the seller.Before shipment, the usual cancellation permissions apply: the buyer can cancel before acceptance, the bound seller can cancel after acceptance, and anyone can refund after expiry. After shipment, expiry does not unlock a refund. A shipped deal needs buyer release, delivery followed by a claim, or a dispute resolved by the assigned resolver.
SHAKE is an MCP server at https://shake-lake.vercel.app/api/mcp (Streamable HTTP, no auth). Add it as a custom connector in Claude or ChatGPT, or in Cursor ({"mcpServers":{"shake":{"url":"https://shake-lake.vercel.app/api/mcp"}}}). Step-by-step setup for each assistant is at shake-lake.vercel.app/ai.
| Tool | What it does |
|---|---|
protect_purchase | Returns a prefilled deal link the buyer opens to lock the money; optionally scans the seller's message. |
check_seller_message | Flags known scam patterns (MB WAY request-money, fake payment links, SMS codes, look-alike domains) in a pasted chat message. |
verify_payment | "Did they really pay me?", answered from the contract's state on testnet, not a screenshot. |
deal_status | Status, parties, and every transaction with Stellar Expert links. |
find_safe_spot | Public meeting places near an address (Nominatim + Overpass). |
create_payment_request | A reusable request link for a seller or small business. |
release_payment | Always refuses, and explains why. |
Agents can create links and read state; they can never move money. The endpoint holds no user keys and signs nothing. Release still needs the buyer's passkey or browser key plus the seller's one-time QR secret, in person. Try: "Someone on Vinted wants €60 for a jacket, here's his message, is it safe?", then "Release the money."
settle (no signature required) is submitted when either phone reconnects. See No signal? The shake still works./u/[address]): deals locked, released, and attributed cancellations counted from recent contract events, for classic and smart-account addresses. The window is three days.smart-account-kit and authorize with a passkey, including Face ID or Touch ID where supported.Payment protection: the seller checks the contract's amount and status; the current QR flow requires buyer authorization and the seller's matching secret. Codes for another deal and old or incorrect codes are rejected by the scanner or contract. Once accepted, another seller cannot replace the bound seller; that seller can rotate the QR before shipment or settlement. Shipping disputes stop QR release and the timed claim. The contract restricts a resolution to the original buyer and seller, so the resolver cannot redirect the funds to itself. Deposit and approval methods are described below.
Public track records describe recent address activity, not a verified person's identity. Cancellation attribution follows the implementation: the accepted seller, or the buyer if nobody accepted, is counted as having walked away even when a refund was submitted after expiry. Meetup suggestions come from map categories; the app does not verify opening hours, cameras, or the safety of a particular location. Nearby-place lookup sends coordinates to Overpass only after requesting the user's location.
Meetup payments, shipping/disputes, public activity, listing-title import, nearby-place lookup, four test currencies with cross-currency pay-in (Reflector and path payments), passkey accounts, and the test anchor are implemented in this repository.
Planned work includes routing Face ID conversions through a Soroban DEX such as Soroswap (today they go through the FX desk), confidential tokens, Circle USDC/EURC, PWA push notifications, and a Portuguese/English interface switch. The current region picker changes monetary formatting and payment currency; it does not translate the interface. The offline shake needs the deal page opened online once; the app has no service worker for loading pages without signal. Carrier-confirmed delivery and automated refund/claim scheduling are not implemented.
The new-deal form starts with what the payment is for: buying in person, buying shipped, a rental deposit (caução), a job or service, or a booking/hire deposit. Kinds only change wording and defaults (src/lib/kinds.ts); each maps to one of three contract rules: Meet (QR release), Ship (QR or approval, timed claim, disputes) and Hold (a deposit with an end date). Jobs use Ship mode: the professional marks the work started and done, and the client approves and pays (approve) or the timed claim applies. Deposits use Hold mode: the holder confirms, can return the deposit early or claim damage before the end date, and the payer can accept the claim with one tap. These methods are deployed and allowed by the server's contract-call allowlist:
| Method | Implemented contract behavior |
|---|---|
lock_hold(…, resolver) | Locks a deposit with an end date and a resolver distinct from the payer and eventual holder. |
claim_damage(deal_id, amount) | The bound holder claims a positive amount up to the deposit before expiry; the accepted deposit becomes disputed. |
agree(deal_id) | The payer accepts a disputed deduction; the claimed amount goes to the holder and the remainder returns to the payer. |
refund(deal_id) in Hold mode | An undisputed deposit can be returned by anyone after expiry. Before expiry, normal cancellation permissions apply. A holder can also withdraw a disputed claim and return the full deposit. |
resolve(deal_id, to_buyer) | The assigned resolver splits a disputed deposit between payer and holder. |
approve(deal_id) | Buyer-authorized full payment without a QR in non-Meet modes, including disputed status. Meet mode rejects it. The web app offers it for jobs. |
Expiry makes a deposit refund callable; it does not submit a transaction by itself. Contract tests for deposit returns, claims, agreed deductions, resolver splits, and deadline/mode restrictions accompany this work.
The payment fits the handover. The buyer commits funds before meeting but authorizes release after inspecting the item. The seller can verify that commitment before making the trip.
The proof is inspectable. Receipts link to public transactions. SHAKE translates contract state into a consumer interface while leaving the evidence accessible.
Distribution starts with a link. People keep their existing listings and conversations. The proposed commercial model is a fee on protected deals; the MVP does not implement a production fee model or claim marketplace partnerships.
Stellar components serve one user journey. Soroban controls settlement, Stellar Asset Contracts carry test currencies, path payments and Reflector let buyers pay in their own currency, passkeys authorize smart accounts, sponsorship removes manual network funding, and an anchor flow demonstrates withdrawal.
The integration artwork uses the Stellar and OpenZeppelin brand marks from Simple Icons. Passkeys, test assets, SEP-24, and receipts use custom capability icons.
flowchart TD
Buyer[Buyer browser] -->|Create and authorize| App[Next.js application]
Seller[Seller browser] -->|Verify funds and show QR| App
Buyer -->|Scan QR and confirm| Auth[Browser keypair or passkey authorization]
Auth --> API[Server API: simulate and submit]
App --> API
API -->|Sponsored calls| Channels[OpenZeppelin Channels]
API -->|Fallback and classic transactions| Pool[SHAKE channel account pool]
Channels --> Contract[Soroban deal contract]
Pool --> Contract
Contract --> Assets[Stellar Asset Contracts]
API -->|FX rate| Reflector[Reflector FX oracle, SEP-40]
API -->|Find path| Horizon[Horizon path finding]
API -->|Pay in another currency| DEX[Path payment through Stellar DEX liquidity pools]
DEX --> Assets
Buyer -->|Open shipping dispute| App
Resolver[Assigned resolver] -->|Authorize buyer/seller split| Contract
App -->|Read state and events| RPC[Stellar Testnet RPC]
RPC --> Contract
App -->|Listing metadata| Listings[Marketplace pages]
App -->|Location permission and nearby query| Maps[OpenStreetMap Overpass]
Agent[AI assistant via MCP] -->|Create links, read state; never signs| App
Seller -->|Cash-out| Anchor[SHAKE test anchor: SEP-1, SEP-10, SEP-24]
Anchor --> Payment[Signed classic testnet payment]
Payment --> Bank[Simulated bank payout]
| Layer | Implementation | Responsibility |
|---|---|---|
| Web application | Next.js 15, React 19, TypeScript | Meetup/shipping deals, scanner, settlement, disputes, receipts, public profiles, and interactive introduction. |
| Interface | Tailwind CSS 4, Motion, custom components | Responsive layouts, glass surfaces, transitions, and confirmation interactions. |
| Authorization | Stellar SDK 16.3.x; smart-account-kit 0.8.x | Sign with a browser keypair or optional passkey smart account. |
| Server orchestration | Next.js route handlers; Stellar SDK | Sponsor onboarding, simulate calls, relay authorizations, and read state and events. |
| Settlement | Rust; soroban-sdk 29.0.1 | Hold tokens, bind the seller, verify the secret, enforce shipping/dispute windows, and settle release/refund/resolution. |
| Assets | Classic test assets wrapped as Stellar Asset Contracts | Transfer test currency through the contract's token interface. |
| Sponsorship | OpenZeppelin Channels; 24 derived channel accounts | Submit transactions and pay fees without user-held XLM. |
| Currency conversion | Reflector FX oracle (SEP-40); Horizon path finding; pathPaymentStrictReceive; three constant-product liquidity pools | Quote and convert the buyer's currency into the deal's currency before the lock. |
| Test anchor | Application-owned SEP endpoints | Discover services, authenticate a classic account, and demonstrate withdrawals. |
| Deal preparation | Listing metadata fetch; OpenStreetMap Overpass | Import item titles and suggest nearby public meeting places. |
| Activity | RPC contract-event index with a short-lived memory cache | Per-asset totals, recent activity, and three-day address track records. |
The MVP uses on-chain deal storage, browser-local wallet/session data, signed withdrawal tokens, and an in-memory event cache. It requires no external application database. Stellar Testnet RPC serves contract reads, oracle reads, and submissions; Horizon supports path finding and the anchor's transaction lookup.
| Route | Purpose |
|---|---|
/ | One-device live payment flow, product explanation, live proof panel, and reveal. |
/try | Two-device entry point: buy or open a seller deal code. |
/deal/new | Item, amount, region/currency preferences, passkey choice, and meetup/shipping selection. |
/deal/[id] | Buyer/seller views, verified funds, sharing, QR rotation, refunds, shipping, claims, and disputes. |
/scan/[id] | QR/manual-code verification and deliberate buyer release. |
/r/[id] | Public status, amount, participants, and core payment transaction timeline without signing in. |
/u/[address] | Public three-day activity summary for an address. |
/anchor/withdraw | Interactive test-anchor bank-details flow. |
GET /api/deal/[id] | Contract state and available deal events. |
POST /api/call | Prepare a contract call or submit its signed authorizations. |
POST /api/wallet, /api/passkey, /api/pitch | Sponsored onboarding/funding, passkey funding, and team seller operations for the guided payment flow. |
GET /api/fx?from=BRL&to=EUR&amount=200 | What the buyer pays in their own currency (Stellar DEX path), with Reflector's rate. |
GET /api/listing?url=… | Supported marketplace title and available price extraction. |
POST /api/mcp | MCP server for AI assistants: deal links, message check, on-chain verification, safe spots. No signing. |
GET /api/stats, /api/reputation/[address] | Recent contract activity, per-currency totals, and address counts. |
/.well-known/stellar.toml, /api/anchor/*, /api/wallet/pay | Anchor discovery, authentication, withdrawal details/status, and signed payment preparation/submission. |
The public receipt displays all current status labels, including shipping and disputes, but its visual timeline currently focuses on lock, acceptance, release, and refund. Shipment, delivery, dispute, and resolution events are available from the contract/API; a complete shipping timeline is not yet rendered there.
stateDiagram-v2
[*] --> Locked: buyer authorizes lock
Locked --> Accepted: seller commits secret hash
Accepted --> Accepted: bound seller rotates hash
Accepted --> Released: buyer authorization and matching secret
Locked --> Refunded: buyer cancels or expiry refund
Accepted --> Refunded: seller cancels or expiry refund
Accepted --> Shipped: ship mode, seller marks shipped
Shipped --> Delivered: seller marks delivered (3-day window starts)
Shipped --> Released: buyer scans the QR in the box
Delivered --> Released: buyer scans, or claim after 3 days
Shipped --> Disputed: buyer opens a problem
Delivered --> Disputed: buyer opens a problem within 3 days
Disputed --> Resolved: resolver splits between buyer and seller
Released --> [*]
Refunded --> [*]
Resolved --> [*]
The escrow implementation is in contracts/escrow/src/lib.rs.
| Method | Contract behavior |
|---|---|
lock(buyer, token, amount, deal_id, expiry, memo, key) | Requires buyer authorization, positive amount, future expiry, unused ID, and a memo of at most 64 bytes. Transfers tokens into the contract. key is optional: the SHA-256 of the buyer's half, which enables settle. |
accept(deal_id, seller, hash) | Requires seller authorization, an open unexpired deal, and a seller distinct from the buyer. Binds the seller; only that seller can rotate the hash. |
release(deal_id, secret) | Requires buyer authorization and a matching SHA-256 preimage while accepted, or while shipped/delivered in Ship mode. Transfers funds to the bound seller. |
settle(deal_id, secret, half) | No signature. Needs a key from lock, the deal accepted, the seller's matching secret, and the buyer's half matching key. Pays the bound seller only; anyone may submit it. |
refund(deal_id) | Only while locked or accepted. Before expiry, requires the buyer if unaccepted or the seller if accepted; after expiry, anyone may submit it. Returns funds to the buyer. |
lock_ship(…, resolver) | Same as lock, in Ship mode, naming the resolver. Rejects the buyer as resolver; acceptance rejects a seller who is the resolver. The app supplies NEXT_PUBLIC_TEAM_ADDRESS. |
mark_shipped(deal_id, tracking) / mark_delivered(deal_id) | Bound seller only, Ship mode. After shipping the buyer can no longer refund. Delivery sets release_after = now + 3 days. |
claim(deal_id) | Anyone, once a delivered deal passes release_after. Pays the seller. |
dispute(deal_id) | Buyer only, while shipped or within 3 days of delivery. Freezes the deal. |
resolve(deal_id, to_buyer) | Resolver only, on a disputed deal, with 0 <= to_buyer <= amount. Sends to_buyer back and the rest to the seller. Use node scripts/resolve.mjs <id> <amount-to-buyer> in the deal's currency. |
get(deal_id) | Returns participants, token, amount, expiry, memo, hash, status, mode, resolver, tracking, and release deadline. |
State-changing operations emit events. Deal records use persistent storage with TTL extension on writes. Released, refunded, and resolved deals cannot settle again.
The contract verifies buyer authorization plus knowledge of the seller's committed secret, or, for settle, both committed secrets (the seller's QR secret and the buyer's half), which the buyer's app reveals only after the seller's code checks out and the buyer holds to pay. This supports a face-to-face handover flow, but a QR or code can be shared remotely; it is not an independent proof of physical proximity. Phone motion is a confirmation gesture, not an on-chain security input.
The contract does not inspect the item, confirm delivery with a carrier, decide disputes itself (the resolver splits them), or reverse a completed release. Currently, release does not check expiry: an accepted deal can still be released after expiry, competing with an eligible refund until one settles. Shipping refunds are unavailable after shipment. Seller-declared delivery starts the three-day claim window; a buyer must dispute before it ends. There is no background refund or claim scheduler in this repository.
The browser-keypair path stores its signing key in local storage. Passkeys provide a separate smart-account authorization path. Server-held issuer, sponsor, and team keys support test funding, sponsorship, and the single-device payment experience. This is a hackathon implementation, not an audited production payment service.
Public deployment identifiers from the repository's local configuration at the time of this README update:
| Component | Stellar Testnet identifier |
|---|---|
| Deal contract | CAQ6KAVIUSXSO2A6T44TC6USH3WP67R7YYORMLMLVTRG6ZDBHGQIZ2JW |
| tEUR contract | CCFUCVE7557QSF3HPM26D6CNBNZINFGHH7LERSZXVBCAV6KYRYIVPTAR |
| tUSD contract | CB2566JZPAWMJJ7M3HQONF5S7F7PKSNTAO46KCUTEPS6OSLKPV4LQT5K |
| tGBP contract | CDE7CPLXT5RXLQAOXQ6HHVFYBZKNSWJ2IRKAON5VQFWIEJ4BE32HKD7M |
| tBRL contract | CD7MJRLVFP3HOUX2YNI2DYOWU4QFZJ3ON5JVLFE3C3LOZVIGCOH7PGBT |
| Test asset issuer | GD2U4G7UTP2356O4HAVWMICIOHJZYNBKPLQNXJ4HUBRBDYRXWSR552QJ |
| Pitch seller | GANMRJYUDGU4UJBDPV2JOMEOIXFG2TIM2WC7EV5ZDQFWBLQZ5OVULLQX |
| Reflector FX oracle (run by Reflector) | CCSSOHTBL3LEWUCBBEB5NJFC2OKFRC74OWEIJIZLRJBGAAU4VMU5NV4W |
| tEUR/tUSD liquidity pool |
The build log records an earlier deployment's smoke-test sequence: lock, seller acceptance, and release. These are historical evidence, not a fresh verification against the current contract.
No-signal shake on the current contract (25 Oct 2026, node scripts/offline-e2e.mjs): lock with the buyer's half committed → seller joins → settle through OpenZeppelin Channels with zero signatures. A CLI run also showed a stranger's account submitting a settle that could only pay the seller, and a wrong half rejected with contract error #18. For a new run, follow the transaction links in its live receipt.
Pay in your own currency (26 Oct 2026, the app's server code against testnet): pools opened at Reflector's rate (tEUR/tUSD, tEUR/tGBP, tBRL/tEUR) → a new sponsored account pays 1 133,14 R$ and receives 200 € → a top-up paid in pounds arrives as 50 € → a Face ID (Nido) smart account paid in reais. A real Face ID lock from a Nido account, with both of its approved rules and the daily spending cap enforced on-chain: lock of 200 €.
Testnet resets and redeployments can invalidate older identifiers.
git clone https://github.com/franciscogfsm/shake.git
cd shake
npm install
npm run dev
Open localhost:3000. Use localhost, not 127.0.0.1: browsers refuse passkeys on an IP address.
The first npm run dev runs scripts/setup.mjs, which makes your own private testnet setup and writes it to .env.local (git-ignored): three Friendbot-funded accounts, tEUR/tUSD/tGBP/tBRL issued by you, and 24 channel accounts that pay fees. It uses the public SHAKE deal contract, which has no admin. No Rust, no Stellar CLI, no API keys. Later runs start immediately.
To pay with Face ID, SHAKE uses a Nido passkey smart account: tap Lock with Face ID, create or pick your Nido, and approve SHAKE's limits once in Nido's window (lock and release SHAKE payments, and move up to 2,000 a day of each test currency only into the SHAKE contract, for 7 days). Allow pop-ups for the site. SHAKE signs for the account with its own P-256 key, a non-extractable WebCrypto key kept in the browser, which the account checks with OpenZeppelin's WebAuthn verifier under those rules, so later payments need no Face ID. Set NEXT_PUBLIC_NIDO_SIGNER=passkey to use a passkey instead (Face ID on every payment).
The steps below deploy everything yourself, including the contract.
wasm32v1-none target, and a Stellar CLI compatible with the contract SDK. The project's recorded CLI is 28.1.0.git clone https://github.com/franciscogfsm/shake.git
cd shake
npm ci
cp .env.example .env.local # optional: npm run dev fills it for you
rustup target add wasm32v1-none
bash scripts/deploy.sh
bash scripts/currencies.sh
node scripts/channels.mjs
node scripts/fx.mjs
Run these in order. The deployment script creates and funds issuer, sponsor, and team accounts, deploys tEUR and the deal contract, and writes IDs and secret keys to .env.local. The currency script deploys the other assets and adds the team's trustlines. The channels script creates the 24 channel accounts required by onboarding and fallback submissions. The FX script opens the liquidity pools for paying in another currency, priced from Reflector; re-run it before a demo to re-peg them.
Re-running the full deployment creates fresh identities and replaces generated configuration. To redeploy only the deal contract while retaining accounts and assets:
CONTRACT_ONLY=1 bash scripts/deploy.sh
npm run dev -- --port 3100
Open localhost:3100 for the introduction or localhost:3100/try for the two-device flow.
Public variables are embedded in the client bundle by Next.js. Set them before building and restart the development server after changing them. Generated values come from the scripts above; another deployment's public addresses alone are insufficient to configure its server operations.
| Variable | Purpose | Supplied by |
|---|---|---|
NEXT_PUBLIC_NETWORK | Deployment label (testnet); passphrase and endpoints are fixed in code. | deploy.sh |
NEXT_PUBLIC_DEAL_CONTRACT_ID | Deal contract address. | deploy.sh |
NEXT_PUBLIC_TOKEN_CONTRACT_ID | Default tEUR contract; also used by legacy scripts. | deploy.sh |
NEXT_PUBLIC_TOKEN_EUR | Explicit tEUR contract; falls back to NEXT_PUBLIC_TOKEN_CONTRACT_ID. | currencies.sh |
NEXT_PUBLIC_TOKEN_USD | tUSD contract. | currencies.sh |
NEXT_PUBLIC_TOKEN_GBP | tGBP contract. | currencies.sh |
NEXT_PUBLIC_TOKEN_BRL | tBRL contract. | currencies.sh |
NEXT_PUBLIC_TOKEN_ISSUER | Public issuer of test assets. | deploy.sh |
NEXT_PUBLIC_TEAM_ADDRESS | Public seller for the introduction and resolver assigned to new shipping deals. | deploy.sh |
ISSUER_SECRET | Server-only key for issuing test funds. | deploy.sh |
SPONSOR_SECRET | Server-only reserve sponsor; derives channels and anchor signing material. | deploy.sh |
TEAM_SECRET | Server-only seller key for pitch acceptance/cancellation; resolver signing key for scripts/resolve.mjs. | deploy.sh |
CHANNELS_API_KEY | Optional OpenZeppelin Channels sponsorship key. | Developer configuration |
NEXT_PUBLIC_SITE_URL | Optional canonical origin for metadata and social previews. | Developer configuration |
NEXT_PUBLIC_NIDO_BASE | Optional Nido wallet origin for Face ID payments; defaults to https://test.nido.fyi. |
Keep .env.local private. The passkey account WASM hash and WebAuthn verifier address are public constants in src/lib/config.ts. Changing NEXT_PUBLIC_NETWORK alone does not switch networks.
The nearby-place finder requires browser geolocation permission and access to Overpass, with no map API key. Listing import fetches supported marketplace pages from the server and may fall back to a title derived from the URL when fetching fails. These optional services are independent of the core testnet payment flow.
npm run build
npm run start -- --port 3100
For Vercel, configure the same public IDs and server-only variables before building, and set NEXT_PUBLIC_SITE_URL to the public HTTPS origin. A hosted production build still uses Stellar Testnet and does not enable real-money payments.
| Command | Scope |
|---|---|
npm run lint | ESLint checks. |
npm run build | Next.js production compilation and build checks. |
cargo test --manifest-path contracts/escrow/Cargo.toml | Contract unit tests. |
node scripts/scam-check.test.mjs | Local scam rules: MB WAY, payment links, SMS codes, screenshot claims, urgency, look-alike/official domains, and a benign message. |
node --test scripts/localization.test.cjs | Amount parsing, precision, regions, currency handling, and separate asset totals. |
node --test scripts/pitch-session.test.cjs | Saved payment recovery, settlement retries/reconciliation, and currency persistence. |
npm run e2e -- http://localhost:3100 | Testnet onboarding, buyer/seller settlement, wrong-secret rejection, and pitch release. |
node scripts/offline-e2e.mjs | No-signal shake on the live contract: lock with the buyer's half, seller joins, settle through OpenZeppelin Channels with no signatures. Needs .env.local, no running app. |
node scripts/fx.mjs | Opens the tEUR/tUSD, tEUR/tGBP and tBRL/tEUR pools at Reflector's rate, or re-pegs them. Submits testnet transactions. |
node scripts/anchor-e2e.mjs http://localhost:3100 | Anchor discovery, authentication, IBAN validation, payment, and withdrawal completion. |
node scripts/ui-flow.cjs http://localhost:3100 <existing-output-directory> | Playwright two-browser walkthrough with a virtual passkey authenticator and screenshots. Requires Playwright Chromium. |
node scripts/load.mjs http://localhost:3100 10 | Concurrent test-wallet onboarding; submits testnet transactions. |
npm run commits | Refresh the commit-history data used to document development progress. |
The contract suite covers custody, authorized release, the no-signal settle (no signature, both halves required, wrong halves rejected, no key no settle), wrong secrets, QR rotation, repeated settlement, cancellation permissions, post-expiry refunds, expired acceptance, seller binding, self-dealing, invalid inputs, and memo bounds. Shipping tests cover QR release, blocked refunds after shipment, timed claims, frozen disputes, resolver split limits, the dispute deadline, stage/mode restrictions, and cancellation before acceptance. Testnet and UI scripts require a running, fully configured application and submit actual testnet transactions. These are available checks, not a claim that every check was rerun for this documentation update.
contracts/escrow/ Rust deal contract and unit tests
src/app/ Meetup/shipping screens, profiles, metadata, APIs
src/app/api/anchor/ Authentication and withdrawal endpoints
src/components/ Payment controls, QR scanner, receipts, and visual system
src/lib/client/ Wallets, passkeys, handshake codes, polling, and pitch session
src/lib/server/ Stellar orchestration, event index, and test anchor
src/lib/scamCheck.ts Portuguese/English scam patterns used by the MCP `check_seller_message` tool
src/lib/amount.ts Locale-aware amount parsing and cent-precision validation
src/lib/regions.ts Worldwide regions, locale detection, and currency preferences
src/lib/totals.ts Activity totals kept separate for each test asset
src/lib/config.ts Network constants, assets, currencies, and explorer links
scripts/ Deployment, channels, currencies, FX pools, and end-to-end checks
docs/ Build context, design system, research, and integration notes
design/reference.html Graphite Glacier visual reference
Useful entry points: design system, technical research, pitch integration, and build plan. The plan contains historical milestones; source code is the reference for the implementation described here.
SHAKE is developed by Francisco and Pedro for HackMeridian 2026 in Lisbon, targeting the Genesis builder track and Stellar Composed thematic track.
The project combines its own Soroban settlement contract with eight other Stellar pieces: OpenZeppelin Smart Accounts with passkeys (Nido), Stellar Asset Contracts, path payments through Stellar DEX liquidity pools, the Reflector FX oracle, OpenZeppelin Channels, sponsored reserves, a SEP-1/10/24 anchor, and Stellar RPC with Horizon. The goal is to make these components feel like one straightforward payment experience.
Prior work disclosure: the team's project context records ideation and planning documents before the event, with implementation intended for the hackathon. Git history is the evidence for implementation timing; npm run commits refreshes the in-app history.
Never trust a screenshot again. Shake on it.
| Live fiat exchange rates for €, $, £ and R$, read on-chain. The pay sheet shows the rate, and the pools are pegged to it. |
quoteFx in stellar.ts, /api/fx |
| 6 | OpenZeppelin Channels (OpenZeppelin Relayer) | OpenZeppelin | Submits every Soroban call and pays its fee. Users never hold XLM. | submitCall in stellar.ts |
| 7 | Sponsored Reserves | Stellar protocol | One transaction opens the buyer's account and every trustline, paid for by SHAKE. A wallet in one tap. | buildOnboardTx in stellar.ts |
| 8 | Stellar Anchor: SEP-1, SEP-10, SEP-24 | Stellar standards | Shake to Bank: the seller cashes out through an interactive withdrawal (testnet, simulated bank payout). | src/app/api/anchor, stellar.toml |
| 9 | Stellar RPC + Horizon, proof on Stellar Expert | Stellar infrastructure | Live contract reads and events keep both phones in sync. Horizon finds conversion paths. Every receipt links each step on Stellar Expert. | ledger.ts, /r/[id] |
2af4d4b9…f6dd6d39| tEUR/tGBP liquidity pool | 9b3deaef…9ee807db0 |
| tBRL/tEUR liquidity pool | 3d9d1ed8…866427172 |
| FX desk (pool liquidity provider) | GBP2MWN6UROZB3L22MVK6BQ6WYE4GC42YMC5LEMDBHOJZDNFNENDDCFL |
| Developer configuration |
NEXT_PUBLIC_NIDO_SIGNER | Optional. passkey makes SHAKE's Nido session key a passkey (Face ID on every payment); by default it is a browser key (Face ID only when approving in Nido). | Developer configuration |