Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions ROBINHOOD_TOKEN_SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ROBINHOOD_TOKEN_SUPPORT

Goal: support any token on the Robinhood chain by contract address.

Tasks:
1. Add Robinhood chain config (chainId, RPC endpoint, block explorer URL).
2. Implement token resolver:
- Given rpcUrl and contract address, call standard ERC-20 metadata: name(), symbol(), decimals().
- Return { name, symbol, decimals, address, logo? } and a status for non-ERC20 tokens.
3. Validate and checksum addresses; handle invalid contracts gracefully.
4. Add caching, rate-limiting and retries for RPC calls.
5. Integrate resolver into token lookup flows (backend and UI).
6. Add unit tests and an integration test against a public Robinhood RPC or testnet.
7. Docs: usage, environment variables for RPC, and security notes.

Notes:
- Use ethers.js (recommended) or web3.js.
- Fall back to tokenlist lookup or a metadata service if metadata calls fail.
- Add feature flag / UI input for manual contract address when chain = Robinhood.
6 changes: 6 additions & 0 deletions src/chains/robinhood.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const robinhoodChain = {
name: 'Robinhood',
chainId: 0x0, // TODO: replace with actual chainId (decimal or hex)
rpc: process.env.ROBINHOOD_RPC || 'https://rpc.robinhood.example', // TODO: real RPC
explorer: 'https://explorer.robinhood.example', // TODO
};
24 changes: 24 additions & 0 deletions src/tokens/resolveByContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ethers } from 'ethers';

const ERC20_ABI = [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
];

export async function resolveTokenByContract(rpcUrl: string, address: string) {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const contract = new ethers.Contract(address, ERC20_ABI, provider);

try {
const [name, symbol, decimals] = await Promise.all([
contract.name(),
contract.symbol(),
contract.decimals(),
]);
return { address, name, symbol, decimals: Number(decimals) };
} catch (err) {
// Non-ERC20 or call failure — return a structured error/status
return { address, error: 'metadata_unavailable', details: String(err) };
}
}
11 changes: 11 additions & 0 deletions tests/resolveByContract.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { resolveTokenByContract } from '../src/tokens/resolveByContract';

describe('resolveTokenByContract', () => {
it('returns token metadata for a valid ERC20 on Robinhood', async () => {
// TODO: use a real test RPC or a mocked provider
const rpc = process.env.ROBINHOOD_RPC || 'https://rpc.robinhood.example';
const result = await resolveTokenByContract(rpc, '0x0000000000000000000000000000000000000000');
// replace assertions once a real test token is selected
expect(result).toHaveProperty('address');
});
});