Slide p2p payments into Telegram DMs directly from MetaMask, powered by MetaMask Advanced Permissions.
Shoehorn (noun) a smooth, curved piece of plastic or metal that you hold in the back of your shoe when putting it on, to help your foot slide into it .
ShoehornFi is a Telegram bot that leverages MetaMask's Advanced Permissions (EIP-7702/ERC-7715) to enable seamless, delegated token transfers directly within Telegram conversations.
Users grant periodic transfer permissions to the bot account via MetaMask
Bot executes transfers on behalf of users without requiring repeated approvals
Supports both ERC20 tokens (USDC, EURC) and native ETH
User can update permissions with /permissions command, or revoke them via their MetaMask extension
Send tokens instantly in any Telegram chat (private or group) using inline queries
Simple syntax: @bot send 10 usdc or send 0.01 eth
Recipients receive a shareable redemption link via Telegram
Creates temporary, cryptographically-secured token deposits on the EphemeralNotes smart contract
Recipients can claim funds by signing with an ephemeral private key embedded in the Telegram bot link
Notes can be redeemed to any Ethereum address the recipient chooses
Users can reclaim their unclaimed ephemeral notes using the /reclaim command
Bot queries on-chain data via Envio indexer to find unredeemed notes
Batch reclaim functionality returns all unclaimed tokens to the original sender
EphemeralNotes.sol: an escrow contract that holds tokens in cryptographically-secured "notes" based on EphemeralNotes by daimo
Notes are identified by ephemeral addresses
Recipients redeem notes by providing a signature from the ephemeral private key
Contract tracks original sender for reclaim functionality
Built with OpenZeppelin libraries (ERC20, SafeERC20, ECDSA, Ownable)
Telegram Bot (Grammy framework) with conversational flows
EIP-7702 Session Accounts for delegated transaction execution
Account Abstraction (ERC-4337) using bundler clients and UserOperations
Envio Indexer for efficient on-chain data querying
Redis (Upstash) for storing user permissions and addresses
TanStack Start (React) for web-based permission granting interface
The project implements MetaMask's Advanced Permissions (ERC-7715) to allow the bot to transfer tokens from user wallets Metamask 7702 smart account allows executing multi-step transactions (wrap ETH, approve tokens, interact with contracts) while preserving contract deployer account address to authorize owner-only contract functions
Problem: We found the process of onboarding into the ERC-7710/7715 frameworks by MetaMask challenging due to the confusing naming (e.g., that "MetaMask Smart Accounts" aren't actually MetaMask accounts, they are what is known elsewhere as "embedded wallets") and found the intermixed documentation hard to use. Furthering the problem is the reliance of both frameworks on @metamask/smart-accounts-kit, with documentation not sufficiently clear on which examples apply to 7710 vs 7715.
Solution: Instead of searching for solutions in the documentation, we read Smart Account Kit and Delegation Framework codebases and reverse-engineered solutions as needed.
Problem: MetaMask's Advanced Permissions API does not currently support delegating smart contract interactions. Permissions are limited to token transfers. Solution: Implemented a three-step workaround flow:
Transfer tokens from user account → session account (using permissions)
Session account interacts with EphemeralNotes contract
Contract manages token escrow and redemption logic This added complexity but enabled advanced contract features while staying within permission constraints.
msg.sender TraceabilityProblem: When using session accounts as intermediaries, msg.sender in smart contracts becomes the session account address, not the original user's address. This breaks traditional Solidity patterns that rely on msg.sender for access control and user tracking. Impact: Standard contract patterns like "users can only claim their own deposits" became impossible without redesign Solution: Refactored contract architecture to:
Accept user address as an explicit function parameter (_sender)
Store original sender in the Note struct
Trade-off: Trust the calling infrastructure to provide accurate sender information This leads to the next challenge:
Problem: To enable users to reclaim their unclaimed notes, we needed a way to identify and return notes to the original sender. However, with session accounts calling the contract, we couldn't rely on msg.sender == note.sender checks. Solution: Implemented an Ownable pattern with special admin privileges:
Made EphemeralNotes contract Ownable (bot session account is the owner)
Added returnNoteToSender() function callable only by contract owner
Owner function reads note.sender from storage and transfers tokens to that address
This required trusting the bot infrastructure with ownership privileges
Trade-off: Introduced centralization (owner trust) to enable user-friendly reclaim functionality in a delegated execution model.
Problem: EphemeralNotes contract works with ERC20 tokens, but we wanted to support native ETH transfers for better UX. Solution: Implemented automatic ETH wrapping flow:
Transfer native ETH to session account (with permissions)
Wrap ETH → WETH using WETH deposit function
Approve WETH to EphemeralNotes contract
Create note with WETH token This 4-step atomic operation happens transparently in a single UserOperation.
Instant Crypto Gifting: Send tokens to anyone in Telegram without needing their wallet address upfront
Group Payments: Split bills or distribute funds in group chats
Promotional Campaigns: Distribute token airdrops through shareable Telegram links
Privacy-Preserving Transfers: Recipients claim to fresh addresses, not doxxing their main wallet
TanStack Start (SSR React framework)
Upstash Redis (permissions storage)
Envio (blockchain indexer)
Grammy (Telegram Bot framework)
Foundry (development framework)
OpenZeppelin Contracts
Sepolia testnet
This project demonstrates how delegated permissions can unlock seamless Web3 experiences within familiar Web2 interfaces like Telegram.
Supporting more complex permission types as MetaMask expands the API
Cross-chain ephemeral notes using bridges
Time-locked or conditional note redemption
Developed the bot from scratch.