Skip to content

Wallet & on-chain identity

FrameWorks supports wallet-based identity and on-chain payments alongside traditional email login and card / Mollie billing. This page covers the GraphQL surface; for the agent-facing flows see agents/wallet-auth and agents/payments.

A tenant can link one or more wallets. Linking requires a signed challenge from the wallet to prove ownership.

mutation LinkWallet {
linkWallet(input: { address: "0x...", signature: "0x...", message: "<challenge>" }) {
__typename
... on WalletIdentity {
id
address
createdAt
lastAuthAt
}
... on ValidationError {
field
message
}
}
}

To remove a wallet:

mutation UnlinkWallet {
unlinkWallet(walletId: "<wallet global id>") {
__typename
... on DeleteSuccess {
success
deletedId
pending
}
... on NotFoundError {
message
}
... on AuthError {
message
}
}
}

walletLogin exchanges a signed challenge for a developer/session token. Use it to bootstrap a fresh tenant from an agent or wallet-only client.

First request the single-use message from POST /auth/wallet-challenge with {"address":"0x...","chain_id":1}. Sign the returned message verbatim; client-generated nonces and replayed challenges are rejected.

mutation WalletLogin {
walletLogin(input: { address: "0x...", signature: "0x...", message: "<challenge>" }) {
__typename
... on WalletLoginPayload {
token
expiresAt
isNewAccount
user {
id
email
role
}
}
... on ValidationError {
field
message
}
}
}

If the wallet isn’t yet linked to a tenant, the mutation creates one. To bind an email address to an existing wallet-only tenant later, use GraphQL linkEmail or MCP link_email. After verification, GraphQL promoteToPaid with the Free tier or MCP activate_free_tier enables Free without billing details or a payment provider. Paid postpaid tiers still require confirmed provider collection.

x402 (HTTP 402 Payment Required) is an authenticated prepaid top-up protocol on FrameWorks. The platform issues a tenant-bound 402 response; the caller submits a signed payment proof; the server waits for confirmation, credits the balance, and reevaluates the original request. It is not a login method.

An authenticated tenant member may settle a viewer:// playback requirement; the payment credits the tenant that owns the resolved playback resource. An unauthenticated viewer may also settle a viewer:// requirement on the public playback path; that payment credits the content owner and establishes no identity for the viewer. Direct top-ups and non-viewer resources require billing:write and tenant owner/admin authority. Demo mode never bypasses settlement authorization.

The user-facing entry point is submitX402Payment:

mutation Pay {
submitX402Payment(payment: "<base64 PAYMENT-SIGNATURE>", resource: "graphql://createStream") {
__typename
... on X402PaymentResult {
success
tenantId
walletAddress
creditedCents
newBalanceCents
txHash
message
}
... on ValidationError {
field
message
}
... on NotFoundError {
message
}
... on AuthError {
message
}
}
}

Use this payment-recovery mutation (or MCP submit_payment) before a side-effecting rated mutation. Direct inline x402 mutation execution is rejected until the owning service has durable idempotency. See agents/payments.

Wallet-funded crypto top-ups follow the standard prepaid-balance model. Initiate one via createCryptoTopup, then poll cryptoTopupStatus for confirmation count and the credited balance: Billing details are not required for an anonymous top-up of at most €100. A payment over €100, or any VAT-number claim, requires legal name, billing email, and postal address before instructions are issued.

mutation Topup {
createCryptoTopup(input: { amountCents: 10000, asset: USDC }) {
topupId
depositAddress
asset
expectedAmountBaseUnits
expectedAmountToken
quotedPriceUsd
quoteSource
quotedAt
expiresAt
network
conversion {
originalAmountCents
originalCurrency
eurAmountCents
unitsPerEur
referenceDate
}
}
}
mutation CheckStatus {
cryptoTopupStatus(topupId: "<topup id>") {
id
status
txHash
confirmations
receivedAmountBaseUnits
receivedAmountToken
creditedAmountCents
creditedAmountCurrency
}
}

amountCents is in the tenant’s presentment currency (see billing); conversion shows the EUR credit it converts to at the ECB rate locked with the quote. Once credited, the funds appear in your EUR prepaid balance (prepaidBalance query) and are spent against usage like any other top-up. The confirmed credit is the VAT tax point and creates the retained top-up invoice; later usage only consumes that already-invoiced balance.