Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Mpp Mobula

v1.0.6

Pay-as-you-go Mobula API access — fetch crypto prices, wallet positions, and market data using a Tempo wallet that pays per call (~$0.0004) in USDC.e. No sub...

0· 149·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for flotapponnier/mpp-mobula.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Mpp Mobula" (flotapponnier/mpp-mobula) from ClawHub.
Skill page: https://clawhub.ai/flotapponnier/mpp-mobula
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install mpp-mobula

ClawHub CLI

Package manager switcher

npx clawhub@latest install mpp-mobula
Security Scan
Capability signals
CryptoRequires walletCan make purchasesRequires sensitive credentials
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
Name/description align with the code and SKILL.md: it implements MPP payments to mpp.mobula.io via Tempo (USDC.e) and provides CLI and per-user wallet helpers. The requested capabilities (signing transferWithMemo, broadcasting txs, retrying requests with payment credentials) are coherent with the stated purpose.
!
Instruction Scope
Runtime instructions and code instruct the agent to generate wallets, sign transactions, and write private keys to disk. They also reference a TEMPO_PRIVATE_KEY env var in an example (process.env.TEMPO_PRIVATE_KEY) which is not declared in the skill metadata. The skill creates/reads files (.mpp-skill in the home directory and a .claude/claudeclaw directory under process.cwd()) and will auto-generate a wallet.secret. These file reads/writes are necessary for operation but are sensitive and may be surprising in certain agent environments.
!
Install Mechanism
There is no formal install spec in the registry, but SKILL.md and README instruct users to run 'bun install' and 'bun run ...'. The package.json declares Bun as a peer dependency. The registry metadata does not list Bun as a required binary. This mismatch (no declared required binary, but Bun-specific code and Bun APIs used) is inconsistent and could lead to runtime surprises or implicit privilege/context assumptions.
!
Credentials
The skill declares no required environment variables, yet the docs show examples using process.env.TEMPO_PRIVATE_KEY. The code auto-generates and persists a WALLET_SECRET at a path under process.cwd() and stores per-user encrypted wallets there; CLI wallet private keys are stored in plaintext at ~/.mpp-skill/wallet.json. These are reasonable for a wallet client, but the locations (especially using process.cwd() for secrets) and the lack of explicit metadata about these files / any env vars is disproportionate and may expose secrets unexpectedly in some agent deployments.
Persistence & Privilege
The skill writes files to disk (wallet files and a generated wallet.secret) and creates a hot CLI wallet by design; 'always' is false and it does not request elevated platform privileges. Writing persistent secret material is expected for a wallet client, but the chosen storage locations (project working directory for .claude) could result in secrets being placed inside an agent workspace or repository. This is a privacy/configuration risk rather than an immediate privilege escalation.
What to consider before installing
This skill implements pay-per-call payments and will create and store private keys and an encryption secret on disk. Before installing: (1) Confirm the runtime—the code needs Bun (bun install / bun run); the registry metadata doesn't declare Bun as a required binary. (2) Understand where secret material will be stored: per-user encrypted wallets and wallet.secret are created under process.cwd()/.claude/claudeclaw by default (this could place secrets inside your agent project directory); the CLI hot wallet is stored unencrypted at ~/.mpp-skill/wallet.json. If you run agents in shared/sourced workspaces, move storage to a dedicated secure directory or run in an isolated sandbox. (3) Review the code (it is included) and test in a safe environment before granting it network/file access. (4) Be cautious with multi-tenant deployments (Telegram bots): ensure you accept the model where each user's wallet private key is stored (encrypted) and that the WALLET_SECRET file is protected. (5) If you prefer not to have keys on disk, consider using an external signing key (hardware or remote signer) or supply TEMPO_PRIVATE_KEY explicitly and verify that it is not set to a shared credential. If the author can clarify/adjust storage paths (use $HOME or a configurable secure path), declare Bun as a required binary, and document any optional environment vars, that would reduce the concerns.
src/wallet.ts:34
Shell command execution detected (child_process).
Patterns worth reviewing
These patterns may indicate risky behavior. Check the VirusTotal and OpenClaw results above for context-aware analysis before installing.

Like a lobster shell, security has layers — review code before you run it.

latestvk970abf3jv7wjrwrstw2kgtk2185n99x
149downloads
0stars
7versions
Updated 12h ago
v1.0.6
MIT-0

MPP (Machine Payments Protocol) Skill

Mobula's MPP API is pay-per-call : every request is settled on-chain from your own wallet using USDC.e on the Tempo chain (chainId 4217). No signup, no API key — just a funded wallet.

This skill gives you (the agent) everything needed to:

  1. Generate a Tempo wallet,
  2. Top it up via the public bridge,
  3. Make Mobula API calls and pay per-call automatically.

Setup (one-time, ~2 min)

# 1. Clone the skill (skip if already installed in your skills dir)
git clone https://github.com/Flotapponnier/mpp-skill.git
cd mpp-skill
bun install

# 2. Create a hot wallet (stored at ~/.mpp-skill/wallet.json, chmod 600)
bun run start wallet-create
# → prints address + bridge link

# 3. Fund the wallet with USDC.e on Tempo
#    Open: https://relay.link/bridge/tempo?toAddress=<your-address>
#    Bridge a few dollars of USDC from any chain (Base, Ethereum, …).
#    Tempo's gas token IS USDC, so $1 of USDC.e is enough to make ~2,500 calls.

# 4. Verify the balance
bun run start balance

Once funded, every subsequent call is automatic — no manual signing.

CLI commands

CommandWhat it does
bun run start wallet-createGenerate a new Tempo wallet (won't overwrite an existing one)
bun run start balanceShow wallet address, USDC.e balance, bridge link
bun run start price <asset>Token price — accepts name, symbol, or contract address
bun run start wallet <addr>Wallet portfolio positions
bun run start lighthouseTrending tokens
bun run start call <path> k=v…Generic call to any /api/2/* endpoint

Examples:

bun run start price bitcoin
bun run start price 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
bun run start wallet 0xd04b77bb40944110ec9c9e3165f67dadf9d52f21
bun run start lighthouse
bun run start call /api/2/wallet/activity wallet=0xabc...

Programmatic use (inside an agent)

Import directly from your TypeScript code — useful when each end-user has their own wallet (e.g. a Telegram bot where each Telegram ID gets a per-user encrypted wallet).

Per-user wallets (multi-tenant agents)

import { createUserWallet, getUserWalletAddress } from "mpp-skill/src/wallet";
import { userMobulaCall, getUserTempoBalance } from "mpp-skill/src/mpp/user-mpp";

// On first interaction with a Telegram user
const userId = 1162998296;  // Telegram numeric ID
let address = await getUserWalletAddress(userId);
if (!address) {
  const w = await createUserWallet(userId);
  address = w.address;
  // Tell the user to fund it:
  // https://relay.link/bridge/tempo?toAddress=${address}
}

// Check funds
const bal = await getUserTempoBalance(userId);
console.log(`User has $${bal?.usd ?? 0} USDC.e on Tempo`);

// Make an API call (paid from the user's own wallet)
const price = await userMobulaCall(userId, "/api/2/token/price", { asset: "bitcoin" });

Per-user wallets are stored at .claude/claudeclaw/wallets/{userId}.json, AES-256-GCM encrypted with a key derived from HMAC-SHA256(WALLET_SECRET, userId). The secret is auto-generated once at .claude/claudeclaw/wallet.secret (chmod 600). Different users cannot decrypt each other's keys.

Direct low-level call

If you already have a private key and want full control:

import { tempoFetch } from "mpp-skill/src/mpp/tempo-client";
import type { Hex } from "viem";

const data = await tempoFetch(
  "/api/2/token/price",
  { asset: "ethereum" },
  process.env.TEMPO_PRIVATE_KEY as Hex,
);

How the payment works (under the hood)

  1. Agent calls GET https://mpp.mobula.io/api/2/token/price?asset=bitcoin with no auth.
  2. Server returns HTTP 402 with WWW-Authenticate: Payment id="…", realm="mpp.mobula.io", method="tempo", request="<base64-json>". The decoded request specifies amount (in USDC.e atoms), currency: USDC.e, recipient, methodDetails.chainId: 4217, and optionally methodDetails.memo if the server pre-computes it.
  3. Skill signs and broadcasts transferWithMemo(recipient, amount, attributionMemo) on USDC.e (0x20c000000000000000000000b9537d11c60e8b50) on Tempo. attributionMemo is NOT the raw challenge id — it's a structured 32-byte memo (see "Memo layout" below) that the server's mppx lib uses to recognize and bind the payment to the challenge.
  4. Skill retries the same request with Authorization: Payment <base64url(credential)>, where credential references the tx hash.
  5. Server validates the tx (memo layout + tx hash + amount + recipient) and returns the data.

The skill does steps 2–4 automatically — agents only see the data response.

Memo layout (32 bytes)

Mobula uses the official mppx lib server-side. The bytes32 memo passed to transferWithMemo must follow the MPP attribution format, otherwise the server rejects with memo is not bound to this challenge:

BytesSizeFieldSource
0..44MPP tagkeccak256("mpp")[0..4] (constant 0xef1ed712)
4..51version0x01
5..1510server fingerprintkeccak256(realm)[0..10] (realm from WWW-Authenticate)
15..2510client fingerprintzeros for anonymous, else keccak256(clientId)[0..10]
25..327noncerandom 7 bytes, or keccak256(challengeId)[0..7] for a deterministic challenge-bound nonce

Common mistakes that produce a "memo is not bound" error: passing the raw challengeId (UTF-8 padded to 32), the base64url-decoded challengeId, keccak256(challengeId), or any value that doesn't start with the 4-byte MPP tag.

If methodDetails.memo is present in the challenge JSON, use that hex value directly (server pre-computed it) and skip the layout build.

Key facts

  • Chain: Tempo (chainId 4217, RPC https://rpc.tempo.xyz)
  • Token: USDC.e (0x20c000000000000000000000b9537d11c60e8b50)
  • Gas: paid in USDC (Tempo uses USDC as native gas token — no separate ETH needed)
  • Cost per call: ~$0.0004 typical, never above the amount specified in the 402 challenge
  • Bridge: https://relay.link/bridge/tempo — bridges from Base, Ethereum, Arbitrum, etc.

Common errors

ErrorCauseFix
No wallet foundFirst-time setup not donebun run start wallet-create
Insufficient Tempo balance: you have $0.0000…Wallet not funded yetBridge USDC.e via the printed link
Could not parse challenge from: …Server didn't return a Tempo WWW-Authenticate headerLikely an upstream issue — retry or report
Tempo tx failed: …RPC error or revert on-chainCheck balance and https://explorer.tempo.xyz for the address

When to use this vs a subscription

Mobula's subscription endpoints (/agent/x402/subscribe, etc.) are not currently configured in production. Until they are, this pay-per-call flow is the only way to call MPP API endpoints from an agent. The CLI returns a clear error if you try the legacy subscribe / status / topup / key-create commands.

Comments

Loading comments...