Opening launches on Ripples
Opening launches on Ripples
Integration
There are two ways in and they answer the same markets. Read the chain: on Robinhood a Ripples launch is a Uniswap v4 pool from its first block, on the same pool manager as every other v4 pool, so anything already watching that contract sees a launch the moment it opens. Or read our feed, which answers the DEX Screener and GeckoTerminal specifications from the same store our own pages read.
Everything below is read from our deployment records and the compiled contracts. A machine-readable manifest is at /integrate/manifest.json.
The feed
DEX Screener Adapter Specs v1.1 and GeckoTerminal Integration API Standards v0.1, answered by one body. The routes are open: no key and no origin header.
| Network | Base URL | Venue key |
|---|---|---|
| robinhood | https://api.ripples.run/v1/dex/robinhood | ripples |
| Endpoint | Query | Answers |
|---|---|---|
/latest-block | none | { block } |
/asset | id | { asset } |
/pair | id | { pair } |
/events | fromBlock, toBlock | { events } |
fromBlock=10&toBlock=15 covers blocks 10 through 15.400 invalid_request with a message naming the cap. Set your chunk size at or below it./latest-block is the indexer's own cursor, never the chain. The head is the lowest indexed cursor across every source writing the chain, and /events stops at it, so a block is never served twice and never skipped. Stop at the head and you will never meet the cut.Four calls. The head first, then a window of trades, then the market and its two assets. Every URL below is the real one for the Robinhood feed.
# Ask how far the feed has indexed. Never read past this block. https://api.ripples.run/v1/dex/robinhood/latest-block # block.blockNumber is the head. Everything below stops there. # Read a window of trades. Both bounds are inclusive. https://api.ripples.run/v1/dex/robinhood/events?fromBlock=57699981&toBlock=57700000 # Each event carries pairId, the legs, priceNative and reserves. # Look up the market an event names. Its record is fixed at creation, so read it once. https://api.ripples.run/v1/dex/robinhood/pair?id=0x…poolId # asset0Id is the launch token and asset1Id is what it is priced in. # Look up each side of the market, for decimals and supply. https://api.ripples.run/v1/dex/robinhood/asset?id=0x…token # decimals is always present. Supplies are exact decimal strings.
A market that has reached its target keeps answering on /pair. On Robinhood it keeps trading in the same pool under permanent liquidity, so its trades keep arriving on /events.
For wallets
Every Ripples market on Robinhood that the board shows, in the standard token list format: address, name, symbol, decimals and logo. Add the URL to any wallet or app that reads token lists, and Ripples tokens appear with their names and images.
https://api.ripples.run/v1/tokenlist/robinhood.json
Launches the board leaves out are left out here too, and only the real $RIPPLES carries its name. When an entry is removed, the list’s major version goes up, so apps that follow the list drop it as well.
Addresses
Every Ripples market is a Uniswap v4 pool keyed to one of the Ripples hooks, and the hook is the only thing separating it from any other v4 pool. Filter the pool manager's Initialize on its hooks field against the hooks listed for a chain and you have every Ripples market on it. Each hook is one generation of the launch contracts, and a market keeps trading on the hook it opened on.
Every Ripples pool carries the same key: fee = 0 and tickSpacing = 200, on every hook and for every launch. Both are constants of the hooks, so a deployment cannot change them and they are safe to hard code. The pool itself charges nothing; the hook charges everything.
| Contract | Address |
|---|---|
| Uniswap v4 pool manager | 0x8366a39CC670B4001A1121B8F6A443A643e40951 |
| Token factory for new launches | 0x8C43801Fe498B9C400F1D376198727Ecf8AfCAC6 |
| Collection factory for new drops | 0xF4e4DD5A1587a32982Fc33898ACD1dF676a3ad7D |
| Read-only RPC | https://rpc.mainnet.chain.robinhood.com |
A token launched from the site opens on FeeLiquidityHook, through the token factory above. The other hooks below keep the markets that opened on them.
| Hook | Address | Markets settle in |
|---|---|---|
| FeeLiquidityHook | 0xBA7401628167fbcd8f9db9F6ad2dDA72aB41EAcc | ETH |
| QuoteFeeHook | 0x6172fD469E900F74eD04b1763daB4D2c2BFB6AcC | ETH or an approved token |
| CreatorTaxShareHook | 0xC759358c6b68085b2D7Ed71DE137f47766F36AcC | ETH or an approved token |
| Standard LP hook | 0x237268690BD24EAaf06AceF14b2b58f75Ac52aCc | ETH or an approved token |
| Standard LP hook | 0xfE6538c38b099eEEAADceB870cd5BA253231Aacc | ETH or an approved token |
| QuoteFeeHook (first release) | 0x5Df831cbb133191E06a9088AEb98b0C5Fa1beacC | An approved token |
| LaunchHook | 0xaF59944A7d03B914567cb0272b7E588A7aE7AAC4 | An approved token |
| Hook | Lens | Router |
|---|---|---|
| FeeLiquidityHook | 0xfb984da29687958d18b5E4B42b2831356D08Da8b | 0xB4404fA2Ed7fa9bB512fD2EFEb234EE32fFBFBf9 |
| QuoteFeeHook | 0x1Aaa54Fe42ac0d2942bE2c651FE0C23c169d5b1F | 0xd53b4a6d3076e7ceF2BbD713f035d2aADC29FD5D0x0e558e1e65BD1850730A3B4a89654c066fC035B7 |
| CreatorTaxShareHook | 0x7fe9c0799C15cB782C44639053C6dDdeA48dF4Fc | 0xE4487977DfFcf58455f351377F62ced4a2f28a1e |
| Standard LP hook | none | none |
| Standard LP hook | none | none |
| QuoteFeeHook (first release) | 0x7752b56994E5800b9A2AD61420EC0Bb1173f0fC0 | 0x2bF8081c38bF6Edc904D02550cfAF142740c0F73 |
| LaunchHook | 0x5E16EA0A8910053c333383CF8eb13369eFb5c0b8 | 0x22DB9B2c6C6DB56ABC3fc196E4bC1FBb9c4338a6 |
Pool key: fee = 0, tickSpacing = 200, and hooks set to the market's hook. The two currencies are sorted numeric ascending, as Uniswap v4 requires. A market priced in ETH pairs native ETH with its token, and v4 writes native ETH as the zero address, so it is always currency0. A market priced in a token pairs two ERC-20s. The pool id is keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks)).
A hook's permissions are the low fourteen bits of its own address:
0x2ACC on FeeLiquidityHook, QuoteFeeHook, CreatorTaxShareHook, Standard LP hook, QuoteFeeHook (first release): beforeInitialize beforeAddLiquidity beforeRemoveLiquidity beforeSwap afterSwap beforeSwapReturnsDelta afterSwapReturnsDelta 0x2AC4 on LaunchHook: beforeInitialize beforeAddLiquidity beforeRemoveLiquidity beforeSwap afterSwap afterSwapReturnsDelta | Contract | Address |
|---|---|
| Uniswap v4 pool manager | 0x8366a39CC670B4001A1121B8F6A443A643e40951 |
| Token factory for new launches | 0xF73ecF1Ef71B3a0C7996b90382Da31599d32e5eD |
| Collection factory for new drops | 0x3A632Ce9B54C499abD837c1809a5369f0A224cDc |
| Read-only RPC | https://rpc.testnet.chain.robinhood.com |
| Hook | Address | Markets settle in |
|---|---|---|
| QuoteFeeHook | 0xffefa09413cC7E742817F155e8448E1c4313eacC | An approved token |
| QuoteFeeHook (first release) | 0x92A91F2b5A6B6A8fD16225f9F036e7Ff1b1D6AcC | An approved token |
| LaunchHook | 0xaF59944A7d03B914567cb0272b7E588A7aE7AAC4 | An approved token |
| Hook | Lens | Router |
|---|---|---|
| QuoteFeeHook | 0xfF9Ec6475F158Af763Ea12B7b789996014fF811D | 0x9e94250C252E1Df2CF65D5AFC7463eD38e2b20d2 |
| QuoteFeeHook (first release) | 0xCbC90E4167F3e62E80B837C69389C2b0a2f44573 | 0x8d8df28aA0C3DCece9a8e0c1574816f11d3BcA34 |
| LaunchHook | 0x2BD4aB15858d35cedF837f236C51cD3901Eed372 | 0xEAF81A528b516bEE07161943C87c91aDf71C51Aa |
Pool key: fee = 0, tickSpacing = 200, and hooks set to the market's hook. The two currencies are sorted numeric ascending, as Uniswap v4 requires. A market priced in ETH pairs native ETH with its token, and v4 writes native ETH as the zero address, so it is always currency0. A market priced in a token pairs two ERC-20s. The pool id is keccak256(abi.encode(currency0, currency1, fee, tickSpacing, hooks)).
A hook's permissions are the low fourteen bits of its own address:
0x2ACC on QuoteFeeHook, QuoteFeeHook (first release): beforeInitialize beforeAddLiquidity beforeRemoveLiquidity beforeSwap afterSwap beforeSwapReturnsDelta afterSwapReturnsDelta 0x2AC4 on LaunchHook: beforeInitialize beforeAddLiquidity beforeRemoveLiquidity beforeSwap afterSwap afterSwapReturnsDelta Events
Price and volume come from the pool manager, not from us. The hook's own events say what the pool manager cannot: which pool is a Ripples launch, what the hook took out of a swap and in which currency, and where the launch is in its life.
| Event | topic0 | Indexed |
|---|---|---|
Initialize(bytes32,address,address,uint24,int24,address,uint160,int24) | 0xdd466e674ea557f56295e2d0218a125ea4b4f0f6f3307b95f85e6110838d6438 | id, currency0, currency1 |
ModifyLiquidity(bytes32,address,int24,int24,int256,bytes32) | 0xf208f4912782fd25c7f114ca3723a2d5dd6f3bcc3ac8db5af63baa85f711d5ec | id, sender |
Swap(bytes32,address,int128,int128,uint160,uint128,int24,uint24) | 0x40e9cecb9f5f1f1c5b9c97dec2917b7ee92e57ba5563708daca94dd84ad7112f | id, sender |
The hook takes its fee inside the swap, so the pool manager's Swap amounts differ from what the trader paid or received by exactly what the hook charged. Every hook newer than LaunchHook charges its fee in the asset the market is priced in, whichever way the trade goes: before the swap when the trader named the amount in that asset, after it otherwise. LaunchHook charges in the swap's unspecified currency: on an exact-input buy that is the launch token, on an exact-input sell it is the asset the market is priced in, and on an exact-output swap it is whatever the swapper pays in, on top of the amount they named. Take the currency from the event. Read TradeFeeCharged, CreatorTaxCharged and, inside the opening window, SnipeTaxCharged from the same transaction and account for all of them. Each carries the amount and the currency. None of them moves a token during the swap: each is a balance the hook holds inside the pool manager for its payee, paid out when that payee claims it.
TradeFeeCharged is emitted once for each payee, so one trade can land several, and the fee is their sum. On FeeLiquidityHook one of them credits the market's own locker, which adds it to the market's locked liquidity. CreatorTaxCharged is a different charge at a different rate: the trade fee is split between its payees, and the creator's tax goes to the launch's creator income. A trader on a launch that sets one pays both.
Every hook emits these events from the same interface. CreatorTaxShareHook adds CreatorTaxSharingSet and HolderTaxCharged for the part of a creator's tax it passes to the token's holders.
| Event | topic0 | Indexed |
|---|---|---|
Claimed(address,address,uint256) | 0xf7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683 | token, account |
ContributionRecorded(bytes32,address,uint256,uint256) | 0x3b848fcbc1d1d0f19a4a9f30e3990d2ca028a1972bf282879a6fde3e4b28dcba | poolId, from |
CreatorFeeRecipientSet(bytes32,address,address) | 0xe98b751fcb6b01f7da48fff9556bd647d42ca4105dc6220341437f98853c6090 | poolId, previous, recipient |
CreatorTaxCharged(bytes32,address,address,uint256) | 0x2876f994f3ad04672af9d383779387ed0d3bac89871b923c9f9eef41cd6db318 | poolId, currency, recipient |
Credited(address,address,uint256) | 0x4e45da441832cf53bdaa69235704fc0575e68210f459ee1562911024b12967d5 | token, account |
Graduated(bytes32,uint256,uint256) | 0xc1eaf6441a62895ddec3612cee606bd971cf6b1b38dd700f103e7b6b94167d0c | poolId |
GraduationRaiseSettled(bytes32,uint256) | 0xd83e1ca0da2f9ec27f30bfc1a0e691a966ad11db495309f9ba21e5c51bf3ad83 | poolId |
GraduationSettled(bytes32,uint128) | 0x0ee67cdb506e34995a59d35b93c370999743c9c5f4237b1b7f61fa3629cae904 | poolId |
LaunchRegistered(bytes32,address,address,address,address,uint256,uint160,int24,int24,uint128) | 0xc072459bb9c7ab9120cc03eec0a7110f7a20df41ccb3610b0c54814b3aaff318 | poolId, token, quote |
LaunchSeeded(bytes32,uint128,int24,int24) | 0x56a662ac2d06fd82f68115bc8aae74e0d9a11dc119aed160f41a5d4def5a5445 | poolId |
LaunchpadSet(address,bool) | 0x6bce717262ad8d508f67dc3376d3a257125260f8a426f2afef7296415f64850a | launchpad |
OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | previousOwner, newOwner |
OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | previousOwner, newOwner |
PositionManagerConfigured(address) | 0x4e707227e66a64d0a1563ff08548a1e23e88544de6e5a5f0f7adbeb177ee5c7a | positionManager |
SnipeTaxCharged(bytes32,address,address,uint256,uint256) | 0x5b35e3889fff69d0365744fa6d7a696f04c94a77c6200b004fda6320ea34606e | poolId, currency, recipient |
TradeFeeCharged(bytes32,address,address,uint256) | 0x2285eb140ea82ca28170f503bd29870d3ff46c2cea01b0d3bf42deed0d8da500 | poolId, currency, recipient |
Filter on the emitting address as well as the topic. Several token and collection factories are deployed side by side, and 15 of their administrative events are byte-identical signatures. A reader keying on the topic alone attributes one factory's administration to another.
| Signature | topic0 | Emitted by |
|---|---|---|
AssetOriginSet(string) | 0x73b3415953bb883c64e683859b3e778e2ffbee212a395f92fe8b7a2784381407 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
FeePassCollectionSet(address) | 0x23631d31dc72ddf493ae1a8e4578e58a5b375a1c6a5daae27c73c01278c072d2 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
FeePassConsumed(uint256,address) | 0x2575cb7be131797b2b269f251e7bcc8713b9c113ab30a4df1c90f384365def77 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
FeesWithdrawn(address,uint256) | 0xc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
LaunchFeeSet(uint256) | 0x9c14cfb9531fb93979e22b461eaa41216ae6de79984d69ee4b411726defedeba | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
LaunchHookSet(address) | 0x4cce86045ee56e14b861f315f9bbfd9d15354e2b7546aa36b0b6c0d637caaa22 | TokenLaunchFactory, FeeLiquidityClaimsLaunchFactory |
LinkedLaunchCreated(address,address,address,address,address) | 0x12279582cbf91e478c8256e79366d189bc65274e22711012d134561b98fcdb79 | TokenLaunchFactory, FeeLiquidityClaimsLaunchFactory |
NftProtocolFeeSet(uint96) | 0xac2a075822a6a2a357f96fc654b9ebe49d686520b38aacb2d6f0c378d7deab1b | TokenLaunchFactory, FeeLiquidityClaimsLaunchFactory |
OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
PlatformSignerSet(address) | 0xf1589df78975fe5494fa74969b25e6930dd0785c88cce9fb712c07e39aceedd9 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
QuoteRegistrySet(address) | 0xc70b5b06e2432adbb407847681d30654be86cd6573a21454d58858ff7ec05db5 | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
TokenWithdrawn(address,address,uint256) | 0x8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620 | TokenLaunchFactory, FeeLiquidityClaimsLaunchFactory |
TreasurySet(address) | 0x3c864541ef71378c6229510ed90f376565ee42d9c5e0904a984a9e863e6db44f | TokenLaunchFactory, LaunchpadFactory, FeeLiquidityClaimsLaunchFactory |
WaveCreated(address,address,address,uint256,uint96) | 0x9f1af47c78a2baeaaca67ab23f33a8b692892145caf22a42ec2c21f3550182ee | TokenLaunchFactory, FeeLiquidityClaimsLaunchFactory |
LaunchCreated carries the launch's whole tuple, so its topic changes with the tuple. The fee-liquidity factories, which the site creates on, append the creator's share of the trade fee and emit LaunchCreated(address,address,bytes32,address,address,(string,string,uint256,uint256,uint256,uint256,uint256,uint64,uint96,address,string,string,string,string,string,string,string,uint96)), topic0 0xd38b2b35d1a2a62304b3b1faa3406e344473ccae48dc7c15a55092cb2f540f7b. Decode each factory's events with its own tuple.
| Event | topic0 | Indexed |
|---|---|---|
AssetOriginSet(string) | 0x73b3415953bb883c64e683859b3e778e2ffbee212a395f92fe8b7a2784381407 | none |
FeePassCollectionSet(address) | 0x23631d31dc72ddf493ae1a8e4578e58a5b375a1c6a5daae27c73c01278c072d2 | collection |
FeePassConsumed(uint256,address) | 0x2575cb7be131797b2b269f251e7bcc8713b9c113ab30a4df1c90f384365def77 | passTokenId, creator |
FeesWithdrawn(address,uint256) | 0xc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a | to |
LaunchCreated(address,address,bytes32,address,address,(string,string,uint256,uint256,uint256,uint256,uint256,uint64,uint96,address,string,string,string,string,string,string,string)) | 0xe6b9a7f89a54ef27b5f1a729370db18a53da3bcedf25a9cce395d3a7151c9d15 | creator, token, poolId |
LaunchFeeSet(uint256) | 0x9c14cfb9531fb93979e22b461eaa41216ae6de79984d69ee4b411726defedeba | none |
LaunchHookSet(address) | 0x4cce86045ee56e14b861f315f9bbfd9d15354e2b7546aa36b0b6c0d637caaa22 | hook |
LinkedLaunchCreated(address,address,address,address,address) | 0x12279582cbf91e478c8256e79366d189bc65274e22711012d134561b98fcdb79 | creator, token |
NftProtocolFeeSet(uint96) | 0xac2a075822a6a2a357f96fc654b9ebe49d686520b38aacb2d6f0c378d7deab1b | none |
OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | previousOwner, newOwner |
OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | previousOwner, newOwner |
PlatformSignerSet(address) | 0xf1589df78975fe5494fa74969b25e6930dd0785c88cce9fb712c07e39aceedd9 | signer |
QuoteRegistrySet(address) | 0xc70b5b06e2432adbb407847681d30654be86cd6573a21454d58858ff7ec05db5 | registry |
TokenWithdrawn(address,address,uint256) | 0x8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620 | token, to |
TreasurySet(address) | 0x3c864541ef71378c6229510ed90f376565ee42d9c5e0904a984a9e863e6db44f | treasury |
WaveCreated(address,address,address,uint256,uint96) | 0x9f1af47c78a2baeaaca67ab23f33a8b692892145caf22a42ec2c21f3550182ee | creator, locker |
| Event | topic0 | Indexed |
|---|---|---|
AssetOriginSet(string) | 0x73b3415953bb883c64e683859b3e778e2ffbee212a395f92fe8b7a2784381407 | none |
CollectionCreated(address,address,(string,string,uint256,uint256,uint256,uint64,uint64,uint8,string,string,uint96,address)) | 0x97cb7b021a2c09bd07f0519545e6cb005ae3c7bd3dc6d434a64c0308f7f833b2 | creator, collection |
DefaultProtocolFeeSet(uint96) | 0x95465226ac2117c565282226e964ccd12d2c9aa47cc47869f27d19ef1de07c33 | none |
FeePassCollectionSet(address) | 0x23631d31dc72ddf493ae1a8e4578e58a5b375a1c6a5daae27c73c01278c072d2 | collection |
FeePassConsumed(uint256,address) | 0x2575cb7be131797b2b269f251e7bcc8713b9c113ab30a4df1c90f384365def77 | passTokenId, creator |
FeesWithdrawn(address,uint256) | 0xc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a | to |
LaunchFeeSet(uint256) | 0x9c14cfb9531fb93979e22b461eaa41216ae6de79984d69ee4b411726defedeba | none |
OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | previousOwner, newOwner |
OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | previousOwner, newOwner |
PassIssuerSet(string) | 0x072945fd8a1b7cb17668df61f736f4ef095fee948bae421566134f9f89f7e271 | none |
PassOriginSet(string) | 0x57c0921b54bb14c85fb26b74a158f988ced7382dc31e7b91d4d698fc4fc47249 | none |
PlatformSignerSet(address) | 0xf1589df78975fe5494fa74969b25e6930dd0785c88cce9fb712c07e39aceedd9 | signer |
QuoteRegistrySet(address) | 0xc70b5b06e2432adbb407847681d30654be86cd6573a21454d58858ff7ec05db5 | registry |
TokenFeesWithdrawn(address,address,uint256) | 0x6241d2d4228642a412963629be2a38b8fea3c68fc02692659f2afb536393e3af | token, to |
TreasurySet(address) | 0x3c864541ef71378c6229510ed90f376565ee42d9c5e0904a984a9e863e6db44f | treasury |
Reads
Two calls list every launch a factory has created, a third says whether an address came from it, and the hook answers everything about the market behind a pool id. launchesOf takes a batch and returns zeroes for an id it does not know rather than reverting, so one bad id does not lose the other answers.
| Call | Selector | Returns |
|---|---|---|
launchCount() | 0x27cca59f | uint256 |
launches(uint256,uint256) | 0x90166851 | (address,address,address,address)[] |
isFromFactory(address) | 0x2e2ecd8d | bool |
| Call | Selector | Returns |
|---|---|---|
collectionCount() | 0xd57f966b | uint256 |
collections(uint256,uint256) | 0x7697c512 | address[] |
isFromFactory(address) | 0x2e2ecd8d | bool |
| Call | Selector | Returns |
|---|---|---|
poolKeyFor(address,address) | 0x8f15ae9b | (address,address,uint24,int24,address) |
poolIdOfToken(address) | 0x65d7b483 | bytes32 |
configOf(bytes32) | 0x6ef61607 | (address,address,address,address,address,address,address,uint96,uint96,uint96,uint64,uint64,uint64,uint96,address,uint256) |
stateOf(bytes32) | 0x64482ac4 | (uint8,uint128,uint256,uint256) |
planOf(bytes32) | 0xff798040 | (uint160,int24,int24,uint128,uint256) |
realQuote(bytes32) | 0x05ca6842 | uint256 |
graduationQuote(bytes32) | 0x4ce1c4a2 | uint256 |
graduationReady(bytes32) | 0x5315769b | bool |
snipeTaxBps(bytes32) | 0x7da3dafe | uint256 |
launchesOf is answered by a separate contract, listed beside each hook above. It holds no state, no money, and no permission: every field it returns it reads back out of the five hook views above and the pool manager, so a reader who does not want to trust it can reproduce the answer from those two addresses. Every chain the record publishes carries one. A chain listed without a lens has no batch read: enumerate its launches through the factory calls above and read each market from the hook views.
| Call | Selector | Returns |
|---|---|---|
HOOK() | 0xa54eb242 | address |
POOL_MANAGER() | 0x62308e85 | address |
launchesOf(bytes32[]) | 0x52c17af4 | (bytes32,(address,address,address,address,address,address,address,uint96,uint96,uint96,uint64,uint64,uint64,uint96,address,uint256),(uint160,int24,int24,uint128,uint256),(uint8,uint128,uint256,uint256),uint256,uint160,uint256)[] |
A Ripples market is an ordinary Uniswap v4 pool, so any router that speaks v4 trades one. There is one size that needs ours. A launch's liquidity is a single position over a single bounded price range, and the hook refuses any swap that would end outside it, so a router that places its swap with a wide price limit walks a buy larger than the market has left straight into that refusal. The order reverts whole rather than taking what was there.
Each hook has its own router, listed beside it above: a v4 pool's hook is part of its key, so a router built for one hook refuses another's pools. LaunchHook's is LaunchRouter at 0x22DB9B2c6C6DB56ABC3fc196E4bC1FBb9c4338a6, and every router takes the same call. swapExactIn(key, zeroForOne, amountIn, minAmountOut, recipient, deadline) places the swap with the range end as its price limit, so the pool fills to the end of the curve and stops, and returns (spent, amountOut). It pulls only spent from the caller through Permit2, so the part of the order the market could not take never moves. A buy on a market priced in ETH is paid as the call's value instead, exactly amountIn, and the router sends back what the market could not take in the same transaction. minAmountOut is a price rather than a quantity: the router holds spent * minAmountOut <= amountIn * amountOut, which is amountOut >= minAmountOut on an order that spends in full and the same rate on the part of one that does not.
Read the fill from Filled(poolId, sender, recipient, zeroForOne, amountIn, spent, amountOut). spent below amountIn is a partial fill and the market is at the end of its curve. The pool manager's Swap reports the part that filled and says nothing about the part that did not, so a reader that wants the difference has to take it from here. CurveEndReached is the revert on a market with nothing left to sell, and it is the answer to "this launch is ready to graduate" rather than a fault.
Solana
Two kinds of Solana launch share the feed above, and the engine on each record says which it is. A launch on Meteora's Dynamic Bonding Curve (dbc) is a Meteora DBC pool from its first trade, which the terminals list as they do any Meteora pool, and it moves into a Meteora DAMM v2 pool once its curve fills. A launch on the Ripples program (ripples, or no engine) is a program-owned account with virtual reserves rather than a pool, and a Raydium CPMM pool exists only once it reaches its target. Before that there is no pool to read: take the market from the feed above, or decode the launch account with the interface definition below.
| What | Value |
|---|---|
| Program | RippcKjgg9pkjHY7RKp6R1K8jPGwq2BRSJcgbErufjF |
Curve program, dbc launches | dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN |
Pool program after graduation, dbc launches | cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG |
| Curve configs | 6opv6HHth5Diu89wq9V7wiMUUZj2oVd97SRF17kf5Sn9 (standard)CYMBTFb6p8jfXLeMMT6ebzvrJXh2C5ebGq5FrjrFB7Tm (combined-spark)6coc8Ys3a9gZNAdUpMPLRPf2M3s22uCTKsTpES9Tq7Zf (combined-wave)9Vp4xBXqUeukFxBqHrT21ow2dZcirtoN9XRrF5jASv97 (combined-tide) |
| Interface definition | solana/idl/ripples.json at 34c39a9e2b40, version 0.1.0 |
| Instructions | 57 |
| Events | AssetMinted, AssetRevealed, AuthorityAccepted, AuthorityProposed, BeneficiaryFinalized, Bought, BuybackSwept, CollectionCreated, CollectionCreatorSet, CollectionLinked, ConfigUpdated, ContributionRecorded, CreatorPayoutSet, DbcCollectionLinked, DbcLeftoverBurned, DbcLinkSettled, DbcPieceClaimed, DbcRoutedBuy, EscrowClaimed, ExternalLaunchControllerSet, ExternalLaunchCreated, GraduationBegun, GraduationCancelled, GraduationFinalized, HolderRewardClaimed, HolderRewardEpochPublished, HolderRewardsInitialized, HolderShareSet, LaunchCreated, LiquidityLocked, LockedFeesClaimed, LockedFeesCollected, LockedFeesCredited, MetadataUpdated, PoolCreated, QuoteAssetSet, RevenueWithdrawn, Sold, UnattributedRecovered, VestingClaimed |
Crosscurrent
A Crosscurrent opens a token on Solana and on Robinhood Chain from one saved record. Each side's opening buy fills in a contract on its own chain, and nothing moves between the chains. Anyone holding the record can recompute its key and find both contracts from chain state alone. A Crosscurrent factory creates the Robinhood Chain contract. The Solana contract is an account of dual_fill_dbc for a Crosscurrent that opens its Solana token on Meteora's Dynamic Bonding Curve, and of dual_fill for an earlier one on the Ripples program's own curve. The record's terms say which: solana.venue is dbc on Meteora and absent otherwise.
| Contract or program | Mainnet (4663, mainnet-beta) | Test networks (46630, devnet) |
|---|---|---|
| Token launch factory | 0xE89C1b33B6C2505414667bE7E5084774a72150e1 | 0x0338754d997967402896c9D45dFd5352E68606ba |
| Factory for Crosscurrents | 0xF589ED06C61f00B31AD2F15699375cA3305E61ab | 0xAF790e6AfE2981af31593cBF531a67C284841C65 |
| Factory for Crosscurrents with a collection | 0x84Cf592edbd6950CefF482ca62b0B66033d1b42C | 0xe74cf6C2419353f477643612B4fbf3D2692D9a6F |
| Factory for Crosscurrents run by an agent | Not deployed yet | 0x0560333e52D843Ad8DCf0E02a6f5c0f2f60744FA |
| Keeper that opens filled sides | 0xB8F0B600D2b6b60364337742efA6592EF7E2d971 | 0xaB8C25d68B728f7665d6D6627D8017B0A2422C25 |
| Ripples program | RippcKjgg9pkjHY7RKp6R1K8jPGwq2BRSJcgbErufjF | RippcKjgg9pkjHY7RKp6R1K8jPGwq2BRSJcgbErufjF |
| dual_fill_dbc program | 4Be56GxQpJXdjFU8BVGRLVK5ttUdvWEotQzEWs5JKu15 | 4Be56GxQpJXdjFU8BVGRLVK5ttUdvWEotQzEWs5JKu15 |
| dual_fill_dbc upgrade authority | Bz3ovxtMncmF48SYam8hQpB3qB4CGeTV4HEY1E3HRHup | GL6b9QJAimMYaHf68q1BGUy3xcm61RoM8J8ZxupperEe |
| dual_fill_dbc IDL | dual_fill_dbc | dual_fill_dbc |
| dual_fill program | 98pdDLeZS9qJxz8e5TubnNyVh4YT5rsA2Vm8X7NbpNRT | 98pdDLeZS9qJxz8e5TubnNyVh4YT5rsA2Vm8X7NbpNRT |
| dual_fill upgrade authority | Bz3ovxtMncmF48SYam8hQpB3qB4CGeTV4HEY1E3HRHup | GL6b9QJAimMYaHf68q1BGUy3xcm61RoM8J8ZxupperEe |
| dual_fill IDL | dual_fill | dual_fill |
| Earlier dual_fill programs | Cros7xBrWN2ty4BZs1fmugFvsXTQKweBqFEqcCtTWRVq (dual_fill.Cros7xBrWN2ty4BZs1fmugFvsXTQKweBqFEqcCtTWRVq), DuaLwpVYtkyuRLPFDF9BcJx2YiDCXQ3n5PsQ4C8en1wj (dual_fill.mainnet-beta) | Cros7xBrWN2ty4BZs1fmugFvsXTQKweBqFEqcCtTWRVq (dual_fill.Cros7xBrWN2ty4BZs1fmugFvsXTQKweBqFEqcCtTWRVq), DuaLwpVYtkyuRLPFDF9BcJx2YiDCXQ3n5PsQ4C8en1wj (dual_fill.devnet) |
| agent_vault program | R467NctqAyhF21QV2BAVRUW8D9iT6bXuWAUYxJWmKb9 | R467NctqAyhF21QV2BAVRUW8D9iT6bXuWAUYxJWmKb9 |
| agent_vault upgrade authority | Bz3ovxtMncmF48SYam8hQpB3qB4CGeTV4HEY1E3HRHup | GL6b9QJAimMYaHf68q1BGUy3xcm61RoM8J8ZxupperEe |
| agent_vault IDL | agent_vault.mainnet-beta | agent_vault.devnet |
A program with an upgrade authority can still have its code replaced by that key. The manifest carries each program's binary and IDL sha256 from its deployment record, and the IDL row names the file under Interfaces that describes the program on that cluster. An earlier dual_fill program keeps the Crosscurrents it opened, and each is listed with the IDL it runs.
dualFillKey = sha256(utf8(domain) || 0x00 || utf8(canonicalJson(core))), where the domain is ripples-dual-fill-v1 and canonical JSON has keys sorted, integers above 2^53 as decimal strings, no whitespace. The id in a Crosscurrent's URL is base64url(dualFillKey[0..16]), no padding, 22 characters. The core is the record both chains commit to, and @ripplesdotrun/agent-sdk recomputes the key from it before it signs.
core {"deadline":1790000000,"dualFillFactory":"0x00000000000000000000000000000000000071f1","dualFillProgram":"EmuBkApiTEXxPG9JrsZ6xeHdVvP7tYpRQVemrjRdz8Wu","evmChainId":46630,"identitySha256":"311a1911fcf4321fda99a8280f03d5e81df594a7e162f599e8d438e5aad1dc16","mode":"fill-first","nonce":"12345678901234567890","openAlone":false,"publicUntil":1789980000,"rhCreator":"0xd065914767ba406e17ff69dfa63d979eb3d7c0d9","rhTokenFactory":"0x0338754d997967402896c9d45dfd5352e68606ba","solanaCluster":"devnet","solanaCreator":"257dxMGYQNp7bb2BMXhDhqfj4fZkGAN2bkuM8cdHSpoU","solanaProgram":"RippcKjgg9pkjHY7RKp6R1K8jPGwq2BRSJcgbErufjF","termsSha256":"c1d53b286cd40bcf5d9e396a740890774bcd504714ccd70fda5a17a023cb5867","v":1}
key 0x7d706417a3d20dcafcc371f8f131876442711f88975490baefb4b3c38a3e9d78
id fXBkF6PSDcr8w3H48TGHZAV20 has none of these optional core keys, so its key hashes the core as printed:
agent: present only when an agent is the creator.collectionSha256: present only for a Crosscurrent with a collection.fillOf(rhCreator, dualFillKey) on the factory the core names in dualFillFactory. For an agent side, first read treasuryOf(rhCreator, dualFillKey) on agent.robinhood.factory: the treasury is the fill's creator.["fill", solanaCreator, dualFillKey] under dualFillProgram, which names dual_fill_dbc or a dual_fill program; both derive it from the same seeds. For an agent side, derive the agent from solanaCreator under agent.solana.program, then its vault, and use the vault as the fill's creator. An Open now Crosscurrent on Meteora has no fill and names no dualFillProgram: its Meteora config is the program address of ["dbc_config", solanaCreator, dualFillKey] under dual_fill_dbc, and the launchConfig account below names its pool.| Account | Program | Seeds | Bytes | Filter offsets |
|---|---|---|---|---|
| dbcFill | dual_fill_dbc | ["fill", creator, dualFillKey] | 564 | config at 104 |
| dbcVault | dual_fill_dbc | ["vault", fill] | system account | none |
| dbcReceipt | dual_fill_dbc | ["receipt", fill, contributor] | 81 | fill at 8, contributor at 40 |
| dbcLinkedTerms | dual_fill_dbc | ["linked", fill] | 498 | none |
| launchConfig | dual_fill_dbc | ["launch_config", config] | 171 | config at 72, pool at 136 |
| fill | dual_fill | ["fill", creator, dualFillKey] | 611 | none |
| vault | dual_fill | ["vault", fill] | system account | none |
| receipt | dual_fill | ["receipt", fill, contributor] | 81 | fill at 8, contributor at 40 |
| linkedTerms | dual_fill | ["linked", fill] | 497 | none |
| agent | agent_vault | ["agent", sponsor, dualFillKey] | 537 | sponsor at 8 |
| agentVault | agent_vault | ["vault", agent] | system account | none |
Filter on the fills a factory created as well as the topic. A fill emits the same events whichever factory made it, and 12 signatures are shared this way. Take fill addresses from each factory's FillCreated, whose signatures differ, and treasury addresses from AgentDualFillCreated.
| Event | topic0 | Indexed |
|---|---|---|
FillCreated(address,address,bytes32,uint256,uint64,uint64,bool,uint256,bytes32,(string,string,uint256,uint256,uint256,uint256,uint256,uint64,uint96,address,string,string,string,string,string,string,string)) | 0x00a4d22a91b6b8283c2b127728ec8deeda1a3ae5cb1c462f802b4cf6f0733ce4 | fill, creator, dualFillKey |
| Event | topic0 | Indexed |
|---|---|---|
Aborted(address) | 0x13c3922f06c44c3cac6a2c721f8ec8db793360b0180d5e560ca2028de2037eaa | opener |
Cancelled() | 0x63b958841f79ab97cb5456da181454b9932c0e15a3b17f1cbd27e2a8bc610437 | none |
Claimed(address,uint256,uint256) | 0x987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a | account |
CreatorFeesForwarded(uint256,uint256) | 0xaa330b55610f73593b7470d1932f2523ccc17286e023c6ec532d595cc6a2acd5 | none |
Deposited(address,uint256,uint256,bool) | 0x65e6f89b6907d6277741ee4ccbc4ae260163a17f16bbb55b5344dff064867c40 | account |
FeeBudgetRefundAccrued(uint256) | 0x2ff4007c553800f47b5814a443a995df77f266ec4126f362fb2c07cf25a41571 | none |
FeeBudgetReturned(uint256) | 0xc721e23deda263c544f0b77b4fbc995baa8253a1443e8c5b4b64b1d7568596a6 | none |
FeesHandedOver(address) | 0xbb1a6597846990220fd35033701ecd7153257e500949af585ec78e5e27cfebe3 | creator |
Filled(uint256) | 0xd14df08fabc3175c71c9c6b212bd0fd290d0e78a5f809c5f28deb5ba6f029b91 | none |
Opened(address,address,bytes32,address,uint256,uint256,uint256) | 0xf849d2586cabd9983f79f1db336a8684e1489b070cefc38d37db4d37858eff0e | token, locker, poolId |
Refunded(address,uint256) | 0xd7dee2702d63ad89917b6a4da9981c90c4d24f8c2bdfd64c604ecae57d8d0651 | account |
Withdrawn(address,uint256,uint256) | 0x92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6 | account |
| Event | topic0 | Indexed |
|---|---|---|
FillCreated(address,address,bytes32,uint256,uint64,uint64,bool,uint256,bytes32,(string,string,uint256,uint256,uint256,uint256,uint256,uint64,uint96,address,string,string,string,string,string,string,string),(string,string,uint256,uint256,uint256,uint64,uint64,uint8,string,string,uint96,address),(uint96,uint96,uint64,uint64,bool,bool)) | 0x3f5bfa35fd1339f5fb34156fdedbd6866ad2474437afb17b271e113136c28ccf | fill, creator, dualFillKey |
| Event | topic0 | Indexed |
|---|---|---|
Aborted(address) | 0x13c3922f06c44c3cac6a2c721f8ec8db793360b0180d5e560ca2028de2037eaa | opener |
AssetForwarded(address,uint256) | 0x05c47bff5ba0a5fce90c1fa237cb294e2be5093759e575a4c5f46b1e60201875 | asset |
Cancelled() | 0x63b958841f79ab97cb5456da181454b9932c0e15a3b17f1cbd27e2a8bc610437 | none |
Claimed(address,uint256,uint256) | 0x987d620f307ff6b94d58743cb7a7509f24071586a77759b77c2d4e29f75a2f9a | account |
CollectionOpened(address,address) | 0x2b23f7c6fc26148cee31ca8edf5b8e65c5d38af84c2e194d0366d330db459a7c | collection, vesting |
CreatorFeesForwarded(uint256,uint256) | 0xaa330b55610f73593b7470d1932f2523ccc17286e023c6ec532d595cc6a2acd5 | none |
Deposited(address,uint256,uint256,bool) | 0x65e6f89b6907d6277741ee4ccbc4ae260163a17f16bbb55b5344dff064867c40 | account |
FeeBudgetRefundAccrued(uint256) | 0x2ff4007c553800f47b5814a443a995df77f266ec4126f362fb2c07cf25a41571 | none |
FeeBudgetReturned(uint256) | 0xc721e23deda263c544f0b77b4fbc995baa8253a1443e8c5b4b64b1d7568596a6 | none |
FeesHandedOver(address) | 0xbb1a6597846990220fd35033701ecd7153257e500949af585ec78e5e27cfebe3 | creator |
Filled(uint256) | 0xd14df08fabc3175c71c9c6b212bd0fd290d0e78a5f809c5f28deb5ba6f029b91 | none |
Opened(address,address,bytes32,address,uint256,uint256,uint256) | 0xf849d2586cabd9983f79f1db336a8684e1489b070cefc38d37db4d37858eff0e | token, locker, poolId |
Refunded(address,uint256) | 0xd7dee2702d63ad89917b6a4da9981c90c4d24f8c2bdfd64c604ecae57d8d0651 | account |
Withdrawn(address,uint256,uint256) | 0x92ccf450a286a957af52509bc1c9939d1a6a481783e142e41e2499f0bb66ebc6 | account |
| Event | topic0 | Indexed |
|---|---|---|
AgentDualFillCreated(address,address,address,address,bytes32,uint256) | 0xebe6fc7218fc60683b8bbe69d8e4e6b14dcd8ce8b6c1379426f7fc07e0425bd9 | creator, treasury, operator |
| Event | topic0 | Indexed |
|---|---|---|
BondReturned(address,uint256) | 0x9347cad0e396dd77ea84d092d0e565cf227a1672e5981022e22c07d8d09e12bc | to |
Bought(uint256,uint256) | 0x3ccb2ab6980b218b1dd4974b07365cd90a191e170c611da46262fecc208bd661 | none |
Bound(address,address) | 0x0d128562eaa47ab89086803e64a0f96847c0ed3cc63c26251f29ba1aede09d4e | token, locker |
FeesClaimed(uint256,uint256) | 0xa1f87f32d0f17fab0242ca800d736293de8988c14b27747e218cf13d5c249f53 | none |
FillCancelled(address) | 0x5924e8f5c663cbf9d94e93dabad9ac7323f82cfe85069dc40c4ac75df47cf2a4 | fill |
FillStarted(address,bytes32,uint256) | 0x033bda7bf11fdf18549a1f433edc81b9d5822672d5b69dc6e6c4e057a4251640 | fill, dualFillKey |
Noted(bytes32,string) | 0xd4d08a94163d1e1ffbf270c31a57b5f1502d91abcd6ac037e0b62cc5af7e4aef | digest |
OperatorRetired() | 0xa68770f5e7c6c8b6662c89b74137de3ebddabd56f9d487ce9d8ea60e0bab4a8a | none |
Paid(address,uint256) | 0x737c69225d647e5994eab1a6c301bf6d9232beb2759ae1e27a8966b4732bc489 | to |
RunwayReturned(address,uint256) | 0x796a3a10564d81bea438b8ea0d5c4f97140ef425a506ccfc6366d57b3a46e93d | to |
Sold(uint256,uint256) | 0x7ea63cabf285309a7f2750def3e745dd81fc85e39926c5b47f0bd45938e1a412 | none |
| Call | Selector | Returns |
|---|---|---|
fillCount() | 0x6051e4dc | uint256 |
fills(uint256,uint256) | 0x7dca72b7 | address[] |
fillOf(address,bytes32) | 0x08d2ffc7 | address |
isFill(address) | 0x3b52525a | bool |
| Call | Selector | Returns |
|---|---|---|
DUAL_FILL_KEY() | 0x0e8ceacc | bytes32 |
CREATOR() | 0xe4fbb609 | address |
PARAMS_HASH() | 0x1411a9ef | bytes32 |
terms() | 0xd5025625 | (address,bytes32,uint256,uint64,uint64,bool,uint256,bytes32,address,address,address,bool,address) |
snapshot() | 0x9711715a | (uint8,uint256,uint256,uint256,uint64,address,address,bytes32,uint256,uint256,uint256,bool,bool,bool) |
status() | 0x200d2ed2 | uint8 |
depositOf(address) | 0x23e3fbd5 | uint256 |
claimable(address) | 0x402914f5 | uint256, uint256 |
refundable() | 0xbf89662d | bool |
token() | 0xfc0c546a | address |
poolId() | 0x3e0dc34e | bytes32 |
openedAt() | 0x38930203 | uint64 |
| Call | Selector | Returns |
|---|---|---|
fillCount() | 0x6051e4dc | uint256 |
fills(uint256,uint256) | 0x7dca72b7 | address[] |
fillOf(address,bytes32) | 0x08d2ffc7 | address |
isFill(address) | 0x3b52525a | bool |
curveSupplyFor(uint96) | 0xdb7bc409 | uint256 |
| Call | Selector | Returns |
|---|---|---|
collection() | 0x7de1e536 | address |
vesting() | 0x44c63eec | address |
| Call | Selector | Returns |
|---|---|---|
treasuryOf(address,bytes32) | 0x9edb32bd | address |
treasuryCount() | 0xc0d10bd3 | uint256 |
treasuries(uint256,uint256) | 0x36169483 | address[] |
isFromFactory(address) | 0x2e2ecd8d | bool |
| Call | Selector | Returns |
|---|---|---|
CREATOR() | 0xe4fbb609 | address |
OPERATOR() | 0x983d2737 | address |
fill() | 0xd9c55ce1 | address |
charter() | 0xc1aadb4d | address, uint128, uint128, uint128, uint32, address[] |
remainingToday() | 0xfc3c5515 | uint256, uint256, uint256 |
boughtTokens() | 0x582c6d70 | uint256 |
sellableTokens() | 0x808bcddc | uint256 |
payees() | 0x4e8086aa | address[] |
retired() | 0x2eb38ae0 | bool |
| Interface | Kind | sha256 |
|---|---|---|
| DualFillFactory | ABI | 03fa98cbb68a540f6b08740101167f7a5b385363da58a8168922a100c0fc7eb8 |
| DualFill | ABI | 2fbf4bbb563a3d23595afcb998e8ee993427b17668c562b1b0ee857b5327adeb |
| LinkedDualFillFactory | ABI | 9b4e277866be8461d24bf6c5fd3ae9acb2667568ac6511234b076dea77df033d |
| LinkedDualFill | ABI | 9693cff83bb3ed4f5710cc33b6128805c3f1bc80072706034478e5a5e92b6cf2 |
| DualFillAgentFactory | ABI | 9e3aace11bec64624f45c4fdb3da4a32daa773f34afe97b24981a60722500427 |
| DualFillAgentTreasury | ABI | 14f28dc37c34ea5921b41c69116cd02386437a98beb883a9dc822bd46ef34ed9 |
| dual_fill_dbc | Anchor IDL | d3411047aa15da3d9fc4cc220e5663a9301e8004dfad9db8c0394b5ccb49a253 |
| dual_fill | Anchor IDL | 43cb738a99fe6d3ea47c7af9e480b92bdd4c23d3e304dc7391373a8022accf03 |
| dual_fill.Cros7xBrWN2ty4BZs1fmugFvsXTQKweBqFEqcCtTWRVq | Anchor IDL | ce5b0e9ce9cfd9f3e8b4526a3c02be864ffca58fcc185d489540e4373ebeb6b7 |
| dual_fill.mainnet-beta | Anchor IDL | 957d2184ac7e0c1ef4c6f7978b821e697c470c74ed59d096efeec54faa8aa5a0 |
| dual_fill.devnet | Anchor IDL | deeee916af52b731a8241b87e77664d20349f8f71ef6dc0c0d87fe9be669b436 |
| agent_vault.mainnet-beta | Anchor IDL | e1f879aea10b13c3c8af7ea6cf248bf02e1a37439d1ee1ab0ade157fb93bcb36 |
| agent_vault.devnet | Anchor IDL | e1f879aea10b13c3c8af7ea6cf248bf02e1a37439d1ee1ab0ade157fb93bcb36 |
Every path below is on https://api.ripples.run. A route that needs a session takes one from a Robinhood wallet: POST /v1/auth/evm/challenge returns a message to sign, and POST /v1/auth/evm/verify exchanges the signature for a session.
| Route | Session | Answers |
|---|---|---|
GET /v1/dual-fills | None | Crosscurrents on the board, newest first, or every Crosscurrent of one creator. |
POST /v1/dual-fills | Wallet | Save a Crosscurrent before either chain sees a transaction, and receive everything both chains commit to. |
GET /v1/dual-fills/terms | None | Today's terms for a token, combined or agent Crosscurrent, the contracts they use and the shapes offered. |
GET /v1/dual-fills/by-address/:address | None | The Crosscurrent that recorded an address, with the side it belongs to and its role there. |
POST /v1/dual-fills/artwork | Wallet | Start a collection's artwork draft, which takes pieces for 24 hours. |
PUT /v1/dual-fills/artwork/:draft/pieces/:tokenId | Wallet | Upload one piece of a draft's artwork. |
POST /v1/dual-fills/artwork/:draft/seal | Wallet | Publish a draft as content-addressed folders, one for each chain its pieces mint on. |
GET /v1/dual-fills/:id | None | One Crosscurrent as both chains hold it now. |
DELETE /v1/dual-fills/:id | Wallet | Stop setting up a Crosscurrent before either side exists. |
POST /v1/dual-fills/:id/legs | None | Add a side once its transaction has confirmed; the API checks it against chain state. |
POST /v1/dual-fills/:id/reprice | Wallet | Price an Open now Crosscurrent's Solana side again before it is created. |
Every answer about a Crosscurrent starts with statusLabel and summary, the words ripples.run shows.
The manifest
Every address, topic, selector and rule on this page is read from our deployment records and the compiled contracts, so a redeploy that moves an address moves the page.
The factories above are the ones the site creates on today. Earlier factories still hold the launches they made, and those markets still trade, so they still answer launchCount and launches for them. Every market any of them created is keyed to one of the hooks above, so a reader filtering the pool manager on those hooks sees every Ripples market on Robinhood without knowing which factory made it.
The machine-readable manifest is at /integrate/manifest.json. If an address here ever disagrees with the chain, the chain is right and we want to hear about it: the support page reaches us.