Wallets and portfolio apps
What a wallet shows and calls: balances, income per asset, drops, claims, signed claims and x402 payments, and the token's mark.
On this page
A revenue token is a plain ERC-20 with 18 decimals and a fixed supply, so a wallet already shows its balance and sends it. What a wallet can add is the holder's income: what it can claim now, in each asset, and the claim itself.
Tell a revenue token apart
Ask the tokenizer: tokenizations(token) has a nonzero way only for a token it made. Any contract can answer tokenizer() with the tokenizer's address, so the token's own answer proves nothing on its own.
What to show
| What | Read it with | Note |
|---|---|---|
| Balance | balanceOf(account) | Income never changes a balance; it is claimed apart. |
| Whether it earns | earns(account) | False only for the Uniswap v4 PoolManager, 0xdead, the token's drop box and the token itself. Tokens in a Uniswap v4 position sit in the PoolManager, so they earn nothing while there. |
| Income to claim, per asset | claimable(account, i) for each i below assetCount() | Asset 0 is ETH; assetAt(i).currency names each other asset, shown in its own decimals. It grows every second while income is released. |
| Drops to claim | dropBox(), then on the box dropCount() and claimable(dropId, account) | Each drop is claimed once; one call claims many. |
| Release period | streamSeconds() | How long each arrival of income takes to release. |
| Streams and how they end | streamsOf(token) on the tokenizer | Show a revenue token turns each record into words. |
claimable counts income the token has already recognized. Income still waiting in a door is not in it: the next sync brings it in and releases it over the release period, so the number grows smoothly and never jumps at a sync.
Claims
claim(asset, to)pays one asset;claimAll(to)pays every asset with something due. If one asset's payout fails,claimAllreverts as a whole, so fall back toclaimasset by asset.tocan be any address but zero, the token and its drop box. An ETH payout to a contract that cannot take ETH reverts.- A claim that would pay nothing reverts with
NothingToClaim, so readclaimablefirst. - Drops are claimed from the drop box with
claim(dropIds, to), each drop once.
Signed actions
Every holder action can be signed by the holder and sent by anyone else, so a holder can act without ETH for gas as long as someone sends the signed call. The token's EIP-712 domain is its ERC-20 name(), version "1", chain 4663 and the token's address; eip712Domain() answers all of it. The drop box's domain is "Hookr Drop Box", version "1", chain 4663 and the box.
| Action | Call | Signed over |
|---|---|---|
| Approve | permit, with v, r, s or with the signature as bytes for a contract wallet | Permit(owner, spender, value, nonce, deadline), the nonce from nonces(owner) |
| Claim one asset | claimWithSig(holder, asset, to, nonce, deadline, signature) | Claim(holder, asset, to, nonce, deadline) |
| Claim every asset | claimAllWithSig(holder, to, nonce, deadline, signature) | ClaimAll(holder, to, nonce, deadline) |
| Claim drops | claimWithSig(holder, dropIds, to, nonce, deadline, signature) on the drop box | ClaimDrops(holder, dropIds, to, nonce, deadline) |
| Pay | transfer sent by anyone, or receive sent by the payee | Transfer or Receive (from, to, value, validAfter, validBefore, nonce) |
- Every nonce but the permit's is a random
bytes32the signer picks, used once.authorizationState(signer, nonce)says whether it is spent, andcancelAuthorization, signed by the same signer, spends an unused one. - A signed claim pays only the
tothe holder signed. One that would pay nothing reverts and leaves its nonce unused, so it can be sent again once income is due. - A signature can come from a key or, through ERC-1271, from a contract wallet.
- Hookr runs no relayer. The holder's wallet, your app or any relayer sends the signed call and pays its gas.
transferWithAuthorizationis the form x402's EVM "exact" scheme settles with: the payer signs under the token's domain above. A signed transfer settles income on both sides like any transfer.
The mark and the code
- The token's mark is an SVG at
https://hookr.fun/api/revenue-tokens/<address>/mark: its underlying token's logo in the tokenizer's ring, or the ring around its letters when there is no logo. A browser will not draw it on a page of another site, so fetch it on your server and serve your own copy. - Soon after each mint, Hookr submits the token, its drop box and the doors its own tokenizer and factories made to Sourcify, so a wallet can read their verified code there. Any other door is its builder's to verify.
- The token's page is
https://hookr.fun/revenue/<address>.
Before a holder sends revenue tokens
- A transfer never carries income with it: the sender keeps what was released while it held the tokens, and the receiver earns from the transfer on. How income accrues has the rule.
- A transfer to the token's own address reverts. Tokens sent to its drop box earn nothing and can never come back.
- A contract that cannot claim keeps its share of the income for good: Before you send revenue tokens anywhere.
Show a revenue token and Claim income from a script do all of this in code.